HyukjinKwon closed pull request #15591: [SPARK-17922] [SQL] ClassCastException 
..GeneratedClass$GeneratedIterator cannot be cast to 
...expressions.UnsafeProjection
URL: https://github.com/apache/spark/pull/15591
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala
index 6cab50ae1bf8d..62b9751bfc5d4 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodeGenerator.scala
@@ -40,6 +40,7 @@ import org.apache.spark.sql.types._
 import org.apache.spark.unsafe.Platform
 import org.apache.spark.unsafe.types._
 import org.apache.spark.util.{ParentClassLoader, Utils}
+import org.apache.spark.sql.catalyst.util.DelegateClassLoader
 
 /**
  * Java source for evaluating an [[Expression]] given a [[InternalRow]] of 
input.
@@ -874,7 +875,7 @@ object CodeGenerator extends Logging {
     // find other possible classes (see 
org.codehaus.janinoClassLoaderIClassLoader's
     // findIClass method). Please also see 
https://issues.apache.org/jira/browse/SPARK-15622 and
     // https://issues.apache.org/jira/browse/SPARK-11636.
-    val parentClassLoader = new 
ParentClassLoader(Utils.getContextOrSparkClassLoader)
+    val parentClassLoader = new 
DelegateClassLoader(Utils.getContextOrSparkClassLoader, 
"org.apache.spark.sql.catalyst.expressions.GeneratedClass")
     evaluator.setParentClassLoader(parentClassLoader)
     // Cannot be under package codegen, or fail with 
java.lang.InstantiationException
     
evaluator.setClassName("org.apache.spark.sql.catalyst.expressions.GeneratedClass")
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DelegateClassLoader.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DelegateClassLoader.scala
new file mode 100644
index 0000000000000..dc4d31d024388
--- /dev/null
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/DelegateClassLoader.scala
@@ -0,0 +1,37 @@
+package org.apache.spark.sql.catalyst.util
+/*
+ * See : https://issues.apache.org/jira/browse/SPARK-17922. 
+ * Janino compiler internally creates a byteclassloader 
(http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.janino/janino/2.5.15/org/codehaus/janino/ByteArrayClassLoader.java#ByteArrayClassLoader)
+ * to load the compiled generated class. But this class loader doesnot 
override load class to load the class from byte array for the generated class.
+ * Instead the call first goes to parent class loader and if somehow the 
classloader finds the old generatedClass( all the generated class names are 
same)
+ * it will incorrectly load the old generated class. This class loader will be 
used to intercept delegation to parent if the class has to be loaded by the 
current byte class loader.
+ * This will be set as the parent class loader for janino compiler in 
CodeGenerator.doCompile
+ * Special classloader to skip delegating to parent class loader when the 
class name is same as the generated class name.
+ * Because that class should be loaded by the current class loader 
+ */
+class DelegateClassLoader(parent:ClassLoader, skipClass: String) extends 
ClassLoader(parent) {
+  override def findClass(name: String): Class[_] = {
+    if(checkClassName(name)) {
+      return null
+    }
+    super.findClass(name)
+  }
+
+  override def loadClass(name: String): Class[_] = {
+     if(checkClassName(name)) {
+      return null
+    }
+    super.loadClass(name)
+  }
+
+  override def loadClass(name: String, resolve: Boolean): Class[_] = {
+     if(checkClassName(name)) {
+      return null
+    }
+    super.loadClass(name, resolve)
+  }
+  
+  def checkClassName(name: String): Boolean = {
+    skipClass.equals(name)
+  }
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to