From: David H. <dav...@gm...> - 2007-07-24 14:58:56
|
My Jython code needs to run under a custom classloader to find the classes it needs. I'm embedding Jython in Java and using a factory for Jython objects similar to the ones found in the wiki. The classloader is no problem when initializing a Jython object: PySystemState state = new PySystemState(); ClassLoader myLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader()); state.setClassLoader(myLoader); PythonInterpreter interpreter = new PythonInterpreter(null, state); I use the interpreter to load Jython modules and create objects. The code works fine at this stage and finds all the classes it needs. Then, when I extract objects from the interpreter using interpreter.get(objectName), the extracted objects seem to use a *different* classloader -- different from the one I set on the interpreter's PySystemState, and different from the classloader used by the Java code where the interpreter was instantiated. I don't understand why this would be so, but I'm pretty sure it's true. I inserted logging statements into my custom classloader so it is obvious when it is used. It is used when the Jython objects are being created inside the JythonFactory, but when my Jython code attempts to load a class *after* being extracted using interepreter.get, my classloader is not used, and I get a ClassNotFoundException. Help! -David |
From: Charlie G. <cha...@gm...> - 2007-07-25 05:10:14
|
On 7/24/07, David Huebel <dav...@gm...> wrote: > I use the interpreter to load Jython modules and create objects. The > code works fine at this stage and finds all the classes it needs. > Then, when I extract objects from the interpreter using > interpreter.get(objectName), the extracted objects seem to use a > *different* classloader -- different from the one I set on the > interpreter's PySystemState, and different from the classloader used > by the Java code where the interpreter was instantiated. > > I don't understand why this would be so, but I'm pretty sure it's > true. I inserted logging statements into my custom classloader so it > is obvious when it is used. It is used when the Jython objects are > being created inside the JythonFactory, but when my Jython code > attempts to load a class *after* being extracted using > interepreter.get, my classloader is not used, and I get a > ClassNotFoundException. I'm not quite following what you're saying here. What code throws a ClassCastException? Is it Python code running in your interpreter operating after the extraction? Or is it Java code using the extracted object? Could you include the code where the exception is thrown? Charlie |
From: David H. <dav...@gm...> - 2007-07-25 14:42:43
|
On 7/25/07, Charlie Groves <cha...@gm...> wrote: > I'm not quite following what you're saying here. What code throws a > ClassCastException? Is it Python code running in your interpreter > operating after the extraction? Oops, I meant ClassNotFoundException. I investigated further, and it happens that the code that runs before the extraction uses import, and the code that runs after the extraction uses Class.forName. import works both before and after extraction for the class in question. Class.forName throws ClassNotFoundException after extraction (don't know about before.) I assumed import and Class.forName should work the same when loading a Java class, but after a careful look I can't justify that assumption. The documentation for Class.forName(String className) states, "Invoking this method is equivalent to: Class.forName(className, true, currentLoader) where currentLoader denotes the defining class loader of the current class." It isn't clear what the correct Jython behavior should be in this case, since there isn't always a "current class" when executing Jython code (at least from the point of view of the Python code,) and in any case it isn't obvious what the "defining class loader" of a Jython class would be. Anyway, taking the difference between import and Class.forName into account, I don't believe that the extraction changed anything after all. The class in question is a jdbc driver, and using import followed by DriverManager.getConnection(url) results in "No suitable driver found." I don't know if that's expected or not, but I translated the code into Java (replacing import with Class.forName) and it works, so no worries. David |