From: <le...@us...> - 2010-01-31 06:16:27
|
Revision: 6973 http://jython.svn.sourceforge.net/jython/?rev=6973&view=rev Author: leosoto Date: 2010-01-31 06:16:21 +0000 (Sun, 31 Jan 2010) Log Message: ----------- Fixed problems introduced with the recent class loading refactor. Note that we still do not have a stable/consistent classloading hierarchy in place. But we are closer. Modified Paths: -------------- trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/imp.java Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2010-01-30 16:36:46 UTC (rev 6972) +++ trunk/jython/src/org/python/core/Py.java 2010-01-31 06:16:21 UTC (rev 6973) @@ -787,7 +787,7 @@ * @param name Name of the Java class to load and initialize * @param reason Reason for loading it, used for debugging. No debug output * is generated if it is null - * @return the loaded class, or null if no class loader is accessible + * @return the loaded class * @throws ClassNotFoundException if the class wasn't found by the class loader */ private static Class<?> findClassInternal(String name, String reason) throws ClassNotFoundException { @@ -799,39 +799,42 @@ } return loadAndInitClass(name, classLoader); } - if (!syspathJavaLoaderRestricted) { try { classLoader = imp.getSyspathJavaLoader(); + if (classLoader != null && reason != null) { + writeDebug("import", "trying " + name + " as " + reason + + " in SysPathJavaLoader"); + } } catch (SecurityException e) { syspathJavaLoaderRestricted = true; } - if (classLoader != null) { - if (reason != null) { - writeDebug("import", "trying " + name + " as " + reason + - " in SysPathJavaLoader"); - } - try { - return loadAndInitClass(name, classLoader); - } catch (ClassNotFoundException cnfe) { - // let the default classloader try - } + } + if (syspathJavaLoaderRestricted) { + classLoader = imp.getParentClassLoader(); + if (classLoader != null && reason != null) { + writeDebug("import", "trying " + name + " as " + reason + + " in Jython's parent class loader"); } + } + if (classLoader != null) { + try { + return loadAndInitClass(name, classLoader); + } catch (ClassNotFoundException cnfe) { + // let the default classloader try + // XXX: by trying another classloader that may not be on a + // parent/child relationship with the Jython's parent + // classsloader we are risking some nasty class loading + // problems (such as having two incompatible copies for + // the same class that is itself a dependency of two + // classes loaded from these two different class loaders) + } } if (reason != null) { writeDebug("import", "trying " + name + " as " + reason + - " in Jython's parent class loader"); + " in context class loader, for backwards compatibility"); } - classLoader = imp.getParentClassLoader(); - if (classLoader != null) { - return loadAndInitClass(name, classLoader); - } - - if (reason != null) { - writeDebug("import", "trying " + name + " as " + reason + - " in Class.forName"); - } - return Class.forName(name); + return loadAndInitClass(name, Thread.currentThread().getContextClassLoader()); } /** Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-01-30 16:36:46 UTC (rev 6972) +++ trunk/jython/src/org/python/core/imp.java 2010-01-31 06:16:21 UTC (rev 6973) @@ -48,36 +48,63 @@ } /** - * Returns the parent class loader for Jython. In most environments - * is just the class loader that loaded this class (imp.class). However, - * when that class loader is null (e.g., when Jython has been - * loaded using the boot loader) we return the Thread's context class - * loader (which can also be null, but in such case we return null anyway). + * <p> + * Selects the parent class loader for Jython, used for dinamically load classes and resources * - * @return the parent class loader for Jython + * <p> + * The current implementation chooses between the current and context + * classloader based on the following criteria:<ul> + * + * <li>If both are the same, that one is returned. + * <li>If either is null, the non-null one is selected. + * <li>If both are not null, and a parent/child relationship can be determined, + * the child is selected. + * <li>If both are not null and not on a parent/child relationship, the + * current class loader is returned (since it is likely for the + * context class loader to <b>not</b> see the Jython classes) + * + * @return the parent class loader for Jython or null if both the current and context classloaders are null; */ public static ClassLoader getParentClassLoader() { - ClassLoader parent = null; - // XXX: While trying the current class loader before using the context class - // loader seems like the saner approach, there may be legacy code - // expecting Jython to use the context class loader, - // - // Se we should uncomment the following line when we feel like - // doing backwards-incompatible changes (3.0?) - // - // parent = imp.class.getClassLoader(); - if (parent == null) { - // Try the context class loader - try { - parent = Thread.currentThread().getContextClassLoader(); - } catch (SecurityException e) { - // We just give up - } - } - return parent; - } + ClassLoader current = imp.class.getClassLoader(); + ClassLoader context = Thread.currentThread().getContextClassLoader(); + if (context == current) { + return current; + } + if (context == null) { + return current; + } + if (current == null) { + return context; + } + if (isParentClassLoader(context, current)) { + return current; + } + if (isParentClassLoader(current, context)) { + return context; + } + return current; + } - private imp() { + private static boolean isParentClassLoader( + ClassLoader suspectedParent, ClassLoader child) { + try { + ClassLoader parent = child.getParent(); + if (suspectedParent == parent) { + return true; + } + if (parent == null || parent == child) { + // We reached the boot class loader + return false; + } + return isParentClassLoader(suspectedParent, parent); + + } catch (SecurityException e) { + return false; + } + } + + private imp() { } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |