[CLJ-1157] Classes generated by gen-class aren't loadable from remote codebase for mis-implementation of static-initializer Created: 04/Feb/13 Updated: 10/Apr/14
|Affects Version/s:||Release 1.4, Release 1.5, Release 1.6|
Tested on Mac OS X 10.9.1 and Oracle JVM 1.7.0_51 with Clojure 1.6 master SNAPSHOT
When a genclass'ed object is serialized and sent to a remote system, the remote system throws an exception loading the object:
A gen-classed class (in this case, SampleInterfaceImpl.class) uses a static-initializer for loading SampleInterfaceImpl__init.class like:
RT.load in default uses a context-classloader for loading __init.class but all classes depending on a gen-classed class must be loaded from the same classloader. In this case, RT.load must use a remote URLClassLoader which loads the main class.
Instead produce the equivalent of this in the static initializer:
With this code, RT.load will uses a same classloader which load SampleInterfaceImpl.class.
|Comment by Stuart Halloway [ 01/Mar/13 10:20 AM ]|
This sounds reasonable, but anything touching classloaders must be considered very carefully.
|Comment by Stuart Halloway [ 01/Mar/13 12:12 PM ]|
It seems overly complex to have the patch do so much code generation. Why not implement a method that does this job, and have the generated code call that?
|Comment by Andy Fingerhut [ 11/Jan/14 2:47 PM ]|
Patch 20130204_fix_classloader.diff dated Feb 3, 2013 no longer applies cleanly as of the latest commits to Clojure master on Jan 11, 2014. The only conflict in applying the patch appears to be in the file src/jvm/clojure/asm/commons/GeneratorAdapter.java. This is probably due to the commit for ticket
|Comment by Tsutomu Yano [ 21/Jan/14 3:01 AM ]|
I put a new patch applicable on the latest master branch.
And I fixed my sample program and the 'HOW TO REPRODUCT THIS ISSUE' section of this ticket, because old description is not runnable on newest JVM. It is because the specification of remote method call of the newest JVM was changed from the old one. In the newest JVM, we need a 'java.rmi.server.useCodebaseOnly=false' option for making the behavior of remote call same as old one.