beanshell / beanshell

Beanshell scripting language
Apache License 2.0
879 stars 183 forks source link

Wrong ClassLoader consulted #288

Closed sourceforge-issue-exporter closed 2 years ago

sourceforge-issue-exporter commented 21 years ago

There's a bug in The the plainClassName method of the bsh.classpath.ClassManagerImpl class.

The problem is, this method consults the context class loader *before* it checks the user-specified "externalClassLoader".

Because of this, under JDK1.2 or above, no matter what you specify to the setClassLoader method, it won't be consulted.

Nowadays there are many applications (such as Ant, Maven) that requires a rather sophisticated class loading scheme that doesn't use the context class loader.

This bug makes it impossible to use bsh in such context, and it defeats the purpose of the setClassLoader method.

The proper look up order shoud be:

1. externalClassLoader, if supplied. 2. contextClassLoader, if available. 3. Class.forName(...)

Reported by: kkawa

Original Ticket: "beanshell/bugs/150":https://sourceforge.net/p/beanshell/bugs/150

sourceforge-issue-exporter commented 20 years ago

Logged In: YES user_id=471725

I ran into the same problem, and ended up fixing it by tweaking the innards of plainClassForName to search the contextClassLoader (catching the ClassNotFoundException) and fall back to the externalClassLoader:

public Class plainClassForName( String name )
throws ClassNotFoundException { // Requires JDK 1.2+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); Class c = null; if ( contextClassLoader != null ) try { c = Class.forName( name, true, contextClassLoader ); } catch( ClassNotFoundException e ) {}

if ( c == null ) c = super.plainClassForName( name );

return c; }

I found this bug when I did a pre-submit search, and hadn't thought about checking the externalClassLoader first, but the current way seems to work fine.

Ryan

Original comment by: delscovich

nickl- commented 2 years ago

The current order is:

For bsh.* classes

  1. Interpreter.class.getClassLoader
  2. Class.forName

For the rest:

  1. baseLoader
  2. externalClassLoader
  3. contextClassLoader
  4. Class.forName
  5. loadSourceClass

I believe that is what the OP was after with the addition of a baseLoader and loading from source java, the other loaders are in the desired order.

Closed: resolved