JDK-8160513 : ClassNotFoundException sun.misc.GC when running Tomcat 9 with JDK 9
  • Type: Bug
  • Component: core-libs
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • Submitted: 2016-06-29
  • Updated: 2016-08-24
  • Resolved: 2016-07-28
Related Reports
Duplicate :  
Description
Download and configure Tomcat 9 to run with JDK 9 ea b124
source: https://tomcat.apache.org/download-90.cgi#9.0.0.M8
Load http://localhost:8080/ page
returns,
HTTP Status 500 - java.lang.ClassNotFoundException: org.apache.jsp.index_jsp


type Exception report

message java.lang.ClassNotFoundException: org.apache.jsp.index_jsp

description The server encountered an internal error that prevented it from fulfilling this request.

exception
org.apache.jasper.JasperException: java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
	org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:176)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:380)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)


root cause
java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
	java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java:384)
	org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:129)
	org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:60)
	org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:171)
	org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:380)
	org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
	org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
note The full stack trace of the root cause is available in the Apache Tomcat/9.0.0.M8 logs.
==============
From the log it appears that the ClassLoader in JDK 9 fails to trigger creation of GC Daemon thread during Tomcat start which is expected in non-Sun JVMs.
---------------
 java.lang.ClassNotFoundException: sun.misc.GC
        at java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java:
384)
----------------
For details refer to attached logs.

This works fine with 8u91.
Comments
This issue has been fixed by JDK-8157570. I will follow up on tomcat-dev to propose that the use of sun.misc.GC be removed from the Tomcat JDK 9 trunk.
28-07-2016

As part of preparatory work for JEP 260, JDK-8132928, sun.misc.GC was moved to an alternative internal location and encapsulated, JDK-8153286. The most relevant stacktrace is as follows: 29-Jun-2016 09:33:27.770 SEVERE [main] org.apache.catalina.core.JreMemoryLeakPre ventionListener.lifecycleEvent Failed to trigger creation of the GC Daemon threa d during Tomcat start to prevent possible memory leaks. This is expected on non- Sun JVMs. java.lang.ClassNotFoundException: sun.misc.GC at java.net.URLClassLoader.findClass(java.base@9-ea/URLClassLoader.java: 384) at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:486) at java.lang.ClassLoader.loadClass(java.base@9-ea/ClassLoader.java:419) at java.lang.Class.forName0(java.base@9-ea/Native Method) at java.lang.Class.forName(java.base@9-ea/Class.java:294) at org.apache.catalina.core.JreMemoryLeakPreventionListener.lifecycleEve nt(JreMemoryLeakPreventionListener.java:217) at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBa se.java:94) at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase .java:401) at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:104) at org.apache.catalina.startup.Catalina.load(Catalina.java:606) at org.apache.catalina.startup.Catalina.load(Catalina.java:629) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/ Native Method) at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/N ativeMethodAccessorImpl.java:62) at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9- ea/DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(java.base@9-ea/Method.java:533) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:311) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:494) The Tomcat code in JreMemoryLeakPreventionListener is attempting to eagerly load the JDK internal GC class and create the GC.Daemon thread, invoking requestLatency((Long.MAX_VALUE - 1) to effectively prevent the thread from ever terminating. The reason for this appears to be to stop the GC.Daemon thread from being created lazily. If the thread is created lazily it will inherit the thread context class loader (TCCL) from its parent ( the thread triggering the creation ). The TCCL when tomcat is running may be the web application's class loader, which is problematic since the reference to the web application's class loader, from the GC.Daemon thread, will prevent the web application's class loader from being garbage collected ( and also may keep descriptors open to the underlying web application's jar files ). The GC.Daemon thread has no need of any user defined class loader, so should set its context class loader to null before starting. Suggested change: $ hg diff src/java.rmi/share/classes/sun/rmi/transport/GC.java diff -r 4a4fa69bb061 src/java.rmi/share/classes/sun/rmi/transport/GC.java --- a/src/java.rmi/share/classes/sun/rmi/transport/GC.java Sat Jul 16 11:49:58 2016 +0100 +++ b/src/java.rmi/share/classes/sun/rmi/transport/GC.java Tue Jul 26 10:39:31 2016 +0100 @@ -144,6 +144,11 @@ Daemon d = new Daemon(tg); d.setDaemon(true); d.setPriority(Thread.MIN_PRIORITY + 1); + /* Set context class loader to null in order to avoid + * keeping a strong reference to the loader of whatever + * thread triggered the creation of this Daemon. + */ + d.setContextClassLoader(null); d.start(); GC.daemon = d; With the above change, the Tomcat code that reflectively tries to access sun.misc.GC can be removed, if there is a JDK 9 specific Tomcat source trunk. Otherwise, if the code needs to run on older releases, it can be be made version specific, where it is not executed on JDK 9 or greater.
26-07-2016