Issue1127

classification
Title: Jython has problems to dynamically loading classes when installed on the boot classpath
Type: Severity: normal
Components: Documentation Versions:
process
Status: open Resolution: remind
Dependencies: Superseder:
Assigned To: Nosy List: fwierzbicki, leosoto, nriley, pjenvey, zyasoft
Priority: low Keywords:

Created on 2008-09-13.18:47:45 by leosoto, last changed 2014-10-06.13:08:30 by zyasoft.

Messages
msg3522 (view) Author: Leonardo Soto (leosoto) Date: 2008-09-13.18:47:45
As discussed on
<http://thread.gmane.org/gmane.comp.lang.jython.user/7156>, configuring
jython on the bootclasspath (as the current launcher script does) is
causing problems when dynamically loading classes which "live" on the
normal CLASSPATH (i.e, when using Class.forName()).

This typically impacts the use of JDBC drivers.
msg3523 (view) Author: Leonardo Soto (leosoto) Date: 2008-09-13.18:48:32
#1096 is clearly related to this issue.
msg3524 (view) Author: Leonardo Soto (leosoto) Date: 2008-09-13.18:49:04
Oh, and for the record, the current workaround is to use the --verify
flag when starting jython.
msg3543 (view) Author: Leonardo Soto (leosoto) Date: 2008-09-13.22:27:14
#1129 is also this problem
msg3580 (view) Author: Nicholas Riley (nriley) Date: 2008-09-14.04:05:26
So:

>>> Class.forName('com.apple.mrj.MRJPriv')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:169)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)

The full stack looks like:

Class<T>.forName(String) line: 169	
NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
Method.invoke(Object, Object...) line: 597	
PyReflectedFunction.__call__(PyObject, PyObject[], String[]) line: 162	
PyReflectedFunction.__call__(PyObject[], String[]) line: 170	
PyReflectedFunction(PyObject).__call__(PyObject) line: 273	
_pyx2.f$0(PyFrame) line: not available	
_pyx2.call_function(int, PyFrame) line: not available	
PyTableCode.call(PyFrame, PyObject) line: 187	
PyTableCode(PyCode).call(PyFrame) line: 14	
Py.runCode(PyCode, PyObject, PyObject) line: 1200	
Py.exec(PyObject, PyObject, PyObject) line: 1227	
InteractiveConsole(PythonInterpreter).exec(PyObject) line: 134	
InteractiveConsole(InteractiveInterpreter).runcode(PyObject) line: 90	
InteractiveConsole(InteractiveInterpreter).runsource(String, String, String) line: 71	
InteractiveConsole(InteractiveInterpreter).runsource(String, String) line: 46	
InteractiveConsole.push(String) line: 110	
InteractiveConsole.interact(String, PyObject) line: 90	
jython.run(String[]) line: 294	
jython.main(String[]) line: 114	

So the problem is that Class.forName uses ClassLoader.getCallerClassLoader, whereas we want it to use another 
one.

>>> Thread.currentThread().getContextClassLoader()
sun.misc.Launcher$AppClassLoader@e47858e
>>> Class.forName('com.apple.mrj.MRJPriv', True, Thread.currentThread().getContextClassLoader())
<jclass com.apple.mrj.MRJPriv 1>

At least for cases like #1129 and #1096, we could change Jython's and zxJDBC's Class.forName calls to 
explicitly specify a classloader, as above.

Another issue is people using Class.forName explicitly from Jython.  In general it looks like we need to have 
the invoking class have a "valid" classloader.  From instrumenting ClassLoader.getCallerClassLoader, that 
ends up being PyReflectedFunction.  So, maybe we can load PyReflectedFunction from somewhere else to get 
around this?
msg4229 (view) Author: Jim Baker (zyasoft) Date: 2009-03-12.07:28:43
Deferred to 2.5.1 (or later)
msg5050 (view) Author: Leonardo Soto (leosoto) Date: 2009-08-17.15:19:36
I think that the machinery needed to workaround the problem and support
using Class.forName from Python code is not worth the effort. 

I propose to explicitely discourage Class.forName('foo.bar.Baz'), since
you can get the desired effect either by doing  "import foo.bar.Baz", if
the class name is known beforehand, or __import__(className), if it's not.

We could even hack PyReflectedFunction to check if it is going to call
Class.forName(String) and print a loud warning.
msg5243 (view) Author: Philip Jenvey (pjenvey) Date: 2009-10-20.04:54:07
+1 on discouraging Class.forName, this was my original suggestion before 
we decided to remove it. However if we can hack PyReflectedFunction to 
warn on its call, how much harder would it be really to hack it to call 
another class loader instead?
msg9107 (view) Author: Jim Baker (zyasoft) Date: 2014-10-06.04:07:59
Maybe best to encourage the use of Py.findClass, which knows about Jython's class loaders. We could also add a function in the new library jythonlib that wraps this.

Changing Class.forName is probably not what we want to do, but we could document the right solution.

Note the use of JDBC drivers will go away with the move to jyjdbc in beta 4.
msg9110 (view) Author: Jim Baker (zyasoft) Date: 2014-10-06.13:08:30
Bad wording in my previous message:
"Note the use of JDBC drivers will go away with the move to jyjdbc in beta 4."

That should be something like the "problem with the use of JBDC drivers will go away" because jyjdbc is in Python.
History
Date User Action Args
2014-10-06 13:08:30zyasoftsetmessages: + msg9110
2014-10-06 04:07:59zyasoftsetmessages: + msg9107
2013-02-27 17:37:32fwierzbickisetresolution: remind
components: + Documentation, - Core
2009-10-20 04:54:08pjenveysetmessages: + msg5243
2009-08-17 15:19:36leosotosetmessages: + msg5050
2009-03-12 07:28:43zyasoftsetpriority: low
nosy: + zyasoft
messages: + msg4229
2008-12-14 17:14:47fwierzbickisetnosy: + fwierzbicki
2008-12-10 08:36:28pjenveysetnosy: + pjenvey
2008-09-14 04:05:27nrileysetnosy: + nriley
messages: + msg3580
2008-09-13 22:27:14leosotosetmessages: + msg3543
2008-09-13 18:49:04leosotosetmessages: + msg3524
2008-09-13 18:48:32leosotosetmessages: + msg3523
2008-09-13 18:47:46leosotocreate