Prevent startup when runtime cannot be initialized#910
Conversation
Instead of just logging exceptions on startup they are not handled anymore and will now prevent startup of JaCoCo runtime. This strategy avoids deferred failures due to partially initialized runtimes.
|
This PR breaks on JDK >= 11 due to JDK-8228485. As discussed with @Godin a workaround would be to replace the static initializer in |
| <pathelement path="${temp.dir}"/> | ||
| </classpath> | ||
| </java> | ||
| <au:assertLogContains text="Caused by: java.lang.RuntimeException: Failed to initialize JaCoCo."/> |
There was a problem hiding this comment.
@marchof indeed now JVMs do not crash! 👍 and test succeeds for Java 11+ class files, because access is performed via bootstrap method for condy and so exception indeed looks as
Exception in thread "main" java.lang.BootstrapMethodError: bootstrap method initialization exception
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:194)
at java.base/java.lang.invoke.ConstantBootstraps.makeConstant(ConstantBootstraps.java:67)
at java.base/java.lang.invoke.MethodHandleNatives.linkDynamicConstantImpl(MethodHandleNatives.java:314)
at java.base/java.lang.invoke.MethodHandleNatives.linkDynamicConstant(MethodHandleNatives.java:306)
at org.jacoco.ant.TestTarget.main(TestTarget.java)
Caused by: java.lang.RuntimeException: Failed to initialize JaCoCo.
at org.jacoco.agent.rt.internal_9f79065.Offline.getRuntimeData(Offline.java:40)
at org.jacoco.agent.rt.internal_9f79065.Offline.getProbes(Offline.java:59)
at org.jacoco.ant.TestTarget.$jacocoInit(TestTarget.java)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:204)
at java.base/java.lang.invoke.BootstrapMethodInvoker.invoke(BootstrapMethodInvoker.java:90)
... 4 more
Caused by: java.lang.NumberFormatException: For input string: "foo"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at org.jacoco.agent.rt.internal_9f79065.core.runtime.AgentOptions.getOption(AgentOptions.java:583)
at org.jacoco.agent.rt.internal_9f79065.core.runtime.AgentOptions.getPort(AgentOptions.java:452)
at org.jacoco.agent.rt.internal_9f79065.output.TcpServerOutput.createServerSocket(TcpServerOutput.java:106)
at org.jacoco.agent.rt.internal_9f79065.output.TcpServerOutput.startup(TcpServerOutput.java:53)
at org.jacoco.agent.rt.internal_9f79065.Agent.startup(Agent.java:127)
at org.jacoco.agent.rt.internal_9f79065.Agent.getInstance(Agent.java:53)
at org.jacoco.agent.rt.internal_9f79065.Offline.getRuntimeData(Offline.java:38)
... 8 more
However test fails for class files of lower versions, because access is direct and so exception looks a bit differently
Exception in thread "main" java.lang.RuntimeException: Failed to initialize JaCoCo.
at org.jacoco.agent.rt.internal_9f79065.Offline.getRuntimeData(Offline.java:40)
at org.jacoco.agent.rt.internal_9f79065.Offline.getProbes(Offline.java:59)
at org.jacoco.ant.TestTarget.$jacocoInit(TestTarget.java)
at org.jacoco.ant.TestTarget.main(TestTarget.java)
Caused by: java.lang.NumberFormatException: For input string: "foo"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at org.jacoco.agent.rt.internal_9f79065.core.runtime.AgentOptions.getOption(AgentOptions.java:583)
at org.jacoco.agent.rt.internal_9f79065.core.runtime.AgentOptions.getPort(AgentOptions.java:452)
at org.jacoco.agent.rt.internal_9f79065.output.TcpServerOutput.createServerSocket(TcpServerOutput.java:106)
at org.jacoco.agent.rt.internal_9f79065.output.TcpServerOutput.startup(TcpServerOutput.java:53)
at org.jacoco.agent.rt.internal_9f79065.Agent.startup(Agent.java:127)
at org.jacoco.agent.rt.internal_9f79065.Agent.getInstance(Agent.java:53)
at org.jacoco.agent.rt.internal_9f79065.Offline.getRuntimeData(Offline.java:38)
... 3 more
😉
Maybe we can simply remove first prefix Caused by: from the test
| <au:assertLogContains text="Caused by: java.lang.RuntimeException: Failed to initialize JaCoCo."/> | |
| <au:assertLogContains text="java.lang.RuntimeException: Failed to initialize JaCoCo."/> |
?
This avoids JVM crashes, see JDK-8228485.
278e8bb to
bd40de1
Compare
| jmxRegistration = new JmxRegistration(this); | ||
| } | ||
| } catch (final Exception e) { | ||
| logger.logExeption(e); |
There was a problem hiding this comment.
@marchof maybe we should keep this output in addition to throwing of exception for the case when caller swallows exception, e.g. offline instrumented classes of app inside of app-server? WDYT?
There was a problem hiding this comment.
@Godin Perfectly valid point. I restored logging.
Instead of just logging exceptions on startup they are not handled anymore and will now prevent startup of JaCoCo runtime. This strategy avoids deferred failures due to partially initialized runtimes.