geronimo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andy McCright <j.andrew.mccri...@gmail.com>
Subject JDK 7 Classloading Behavior Change
Date Wed, 03 Jul 2013 16:38:04 GMT
Hi All,

I have noticed that IBM has changed the classloader used to load com.sun.*
(specifically com.sun.script.javascript) classes in JDK 7.  In JDK 6, these
classes were loaded by the JVM's boot classloader - in JDK 7, they are
loaded via the JVM's ext classloader (a child classloader of the boot
loader).  This change has the effect of breaking servlet code like this:


        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        if(engine == null) {
         throw new RuntimeException("Oh no, unable to find a script
engine found for JavaScript");
        }

When running Geronimo 3.0.1 on JDK 6, this code works (engine is non-null,
no exception is thrown).  When I switch to JDK7, I see:
ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory:
Provider com.sun.script.javascript.RhinoScriptEngineFactory not found
java.lang.RuntimeException: Oh no, unable to find a script engine found for
JavaScript
    at org.apache.jsp.HelloWorld_jsp._jspService(HelloWorld_jsp.java:96)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
    at
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
    at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at
org.apache.geronimo.tomcat.GeronimoStandardContext$SystemMethodValve.invoke(GeronimoStandardContext.java:731)
    at
org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve.invoke(GeronimoBeforeAfterValve.java:48)
    at
org.apache.geronimo.tomcat.valve.ProtectedTargetValve.invoke(ProtectedTargetValve.java:53)
    at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
    at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
    at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at org.apache.geronimo.pool.ThreadPool$1.run(ThreadPool.java:267)
    at
org.apache.geronimo.pool.ThreadPool$ContextClassLoaderRunnable.run(ThreadPool.java:397)
    at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1121)
    at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
    at java.lang.Thread.run(Thread.java:769)

The reason this fails is that the bundle's classloader's parent loader is
the JVM's boot classloader, not the ext loader - so it cannot load the
com.sun.* classes that it needs (and that it could in JDK6).

One solution to this is to add the following line to
<geronimo_home>/etc/system.properties:
osgi.parentClassloader=ext

This forces the bundle's to search the ext loader (in addition to the boot
loader) on boot delegated loads.

I'm wondering if there should be a more permanent fix...  here are a few
suggestions:
1) Work with the JDK teams to revert back to the old behavior - I have a
ticket open with JDK support, but they apparently moved the com.sun.*
classes to the ext loader for a security issue, so it may be a hard sell to
get them to move it back.
2) Update the default system.properties to include
osgi.parentClassloader=ext
3) Modify the ClassLoaderHook's getBundleClassLoaderParent() method to
return the ext loader ( ClassLoader.getSystemClassLoader().getParent() ).

If #1 is not an option, then I think I like optino #2 better than #3, as it
allows users to change it easily if they want a different behavior.

Does anybody have strong opinions?  Or other suggestions?

Thanks, Andy

Mime
View raw message