Skip to content

Commit 09b5c56

Browse files
committed
[EXT][SPARK-15622] [SQL] Wrap the parent classloader of Janino's classloader in the ParentClassLoader. apache#13366
1 parent 5ef570f commit 09b5c56

File tree

2 files changed

+14
-10
lines changed

2 files changed

+14
-10
lines changed

repl/src/main/scala/org/apache/spark/repl/ExecutorClassLoader.scala

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,7 @@ class ExecutorClassLoader(conf: SparkConf, classUri: String, parent: ClassLoader
7575
case e: ClassNotFoundException => {
7676
val classOption = findClassLocally(name)
7777
classOption match {
78-
case None =>
79-
// If this class has a cause, it will break the internal assumption of Janino
80-
// (the compiler used for Spark SQL code-gen).
81-
// See org.codehaus.janino.ClassLoaderIClassLoader's findIClass, you will see
82-
// its behavior will be changed if there is a cause and the compilation
83-
// of generated class will fail.
84-
throw new ClassNotFoundException(name)
78+
case None => throw new ClassNotFoundException(name, e)
8579
case Some(a) => a
8680
}
8781
}

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ package org.apache.spark.sql.catalyst.expressions.codegen
1919

2020
import scala.collection.mutable
2121
import scala.collection.mutable.ArrayBuffer
22-
import scala.language.existentials
2322

2423
import com.google.common.cache.{CacheBuilder, CacheLoader}
2524
import org.codehaus.janino.ClassBodyEvaluator
25+
import scala.language.existentials
2626

2727
import org.apache.spark.Logging
2828
import org.apache.spark.sql.catalyst.InternalRow
@@ -31,7 +31,7 @@ import org.apache.spark.sql.catalyst.util.{MapData, ArrayData}
3131
import org.apache.spark.sql.types._
3232
import org.apache.spark.unsafe.Platform
3333
import org.apache.spark.unsafe.types._
34-
import org.apache.spark.util.Utils
34+
import org.apache.spark.util.{ParentClassLoader, Utils}
3535

3636
/**
3737
* Java source for evaluating an [[Expression]] given a [[InternalRow]] of input.
@@ -567,7 +567,17 @@ abstract class CodeGenerator[InType <: AnyRef, OutType <: AnyRef] extends Loggin
567567
*/
568568
private[this] def doCompile(code: CodeAndComment): GeneratedClass = {
569569
val evaluator = new ClassBodyEvaluator()
570-
evaluator.setParentClassLoader(Utils.getContextOrSparkClassLoader)
570+
571+
// A special classloader used to wrap the actual parent classloader of
572+
// [[org.codehaus.janino.ClassBodyEvaluator]] (see CodeGenerator.doCompile). This classloader
573+
// does not throw a ClassNotFoundException with a cause set (i.e. exception.getCause returns
574+
// a null). This classloader is needed because janino will throw the exception directly if
575+
// the parent classloader throws a ClassNotFoundException with cause set instead of trying to
576+
// find other possible classes (see org.codehaus.janinoClassLoaderIClassLoader's
577+
// findIClass method). Please also see https://issues.apache.org/jira/browse/SPARK-15622 and
578+
// https://issues.apache.org/jira/browse/SPARK-11636.
579+
val parentClassLoader = new ParentClassLoader(Utils.getContextOrSparkClassLoader)
580+
evaluator.setParentClassLoader(parentClassLoader)
571581
// Cannot be under package codegen, or fail with java.lang.InstantiationException
572582
evaluator.setClassName("org.apache.spark.sql.catalyst.expressions.GeneratedClass")
573583
evaluator.setDefaultImports(Array(

0 commit comments

Comments
 (0)