Now that I upgraded my webapp to Java 8, I'm running into strange classloading problem with an axis webservice that is running in Tomcat 8.
The very first call to the webservice after installing the webapp will cause a RuntimeException and a "No compiler found in your classpath! (you may need to add 'tools.jar')" fault.
All following calls to that webservice work correctly (apparently tools.jar is there after all?).
The behaviour is reproducable by deleting the exploded webapp folder in the deploy directory. After the next tomcat start, the first call will fail again. If the exploded folder is already there, a tomcat restart does not cause the error.
The error did not occur when tomcat/the webapp were still running with Java 7.
Now, that Axis error has a long, long tradition. The solution in earlier times was to copy tools.jar into tomcats lib directory (Aka make tools.jar available in tomcats classpath). Its not there by default, because axis apparently runs with a JRE (even if you start tomcat with a JDK in JAVA_HOME).
Sadly that did not help. I tried several ways to put tools.jar into tomcats classpath:
- I added it to the libs folder
- I added it to the classpath via setenv.bat
- I added it to the endorsed lib folder
None helped, the very first call was still failing.
I then played around with JAVA_HOME and JRE_HOME. Tomcat starts with a JRE whenever possible and only uses a JDK if you use some functions that need a JDK. I tried to get tomcat to use a JDK instad of a JRE, but the error persistet.
So, question time:
Whats the difference in classloading when tomcat explodes a webapp.war compared to the case that the war has already been exploded in an earlier server run?
When starting, tomcat writes the following to the logfile:
Server version: Apache Tomcat/8.0.15
Server built: Nov 2 2014 19:25:20 UTC
Server number: 8.0.15.0
OS Name: Windows Server 2008 R2
OS Version: 6.1
Architecture: x86
JAVA_HOME: C:\Dev\Java\jdk1.8.0_25\jre
JVM Version: 1.8.0_25-b18
JVM Vendor: Oracle Corporation
CATALINA_BASE: C:\Dev\apache-tomcat-8.0.15
CATALINA_HOME: C:\Dev\apache-tomcat-8.0.15
Command line argument: -Djava.util.logging.config.file=c:\Dev\apache-tomcat-8.0.15\conf\logging.properties
Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
Command line argument: -Djava.endorsed.dirs=c:\Dev\apache-tomcat-8.0.15\endorsed
Command line argument: -Dcatalina.base=c:\Dev\apache-tomcat-8.0.15
Command line argument: -Dcatalina.home=c:\Dev\apache-tomcat-8.0.15
Command line argument: -Djava.io.tmpdir=c:\Dev\apache-tomcat-8.0.15\temp
so apparently it got itself a reference to the JRE somehow (although I only specified a JDK, see above). How can I change that?
- More ideas?
Edit2: The culprit is the compilation of .jws files that axis does the first time a webservice is called. The existence of those compiled files is the reason the error only happens on the very first call.
Of course that does not explain at all why the first call fails with the 'compiler missing' error even though the necessary compiled files are created and are available for subsequent calls...
Edit: Stacktrace of the axis error as requested. Nothing special compared to all the other topics here that deal with a missing tools.jar:
java.lang.RuntimeException: No compiler found in your classpath! (you may need to add 'tools.jar')
at org.apache.axis.components.compiler.Javac.compile(Javac.java:156)
at org.apache.axis.handlers.JWSHandler.setupService(JWSHandler.java:199)
at org.apache.axis.handlers.JWSHandler.invoke(JWSHandler.java:72)
at org.apache.axis.strategies.InvocationStrategy.visit(InvocationStrategy.java:32)
at org.apache.axis.SimpleChain.doVisiting(SimpleChain.java:118)
at org.apache.axis.SimpleChain.invoke(SimpleChain.java:83)
at org.apache.axis.server.AxisServer.invoke(AxisServer.java:249) at org.apache.axis.transport.http.QSMethodHandler.invokeEndpointFromGet(QSMethodHandler.java:129)
at org.apache.axis.transport.http.QSMethodHandler.invoke(QSMethodHandler.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.axis.transport.http.AxisServlet.processQuery(AxisServlet.java:1226)
at org.apache.axis.transport.http.AxisServlet.doGet(AxisServlet.java:249)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2407)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2396)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)