-
Bug
-
Resolution: Fixed
-
P3
-
6
-
b26
-
x86
-
linux
-
Verified
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8040112 | 6u85 | Andreas Eriksson | P3 | Resolved | Fixed | b01 |
JDK-8040154 | 6u81 | Andreas Eriksson | P3 | Resolved | Fixed | b04 |
FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux d 2.6.18.5-XXX-mixed64-32 #1 SMP XXX x86_64 GNU/Linux
System is a modified ubuntu dapper.
EXTRA RELEVANT SYSTEM CONFIGURATION :
NPTL 2.3.6 from glibc 2.3.6.
A DESCRIPTION OF THE PROBLEM :
Calling Instrumentation.getObjectSize() while the JVM is attempting to exit causes the JVM to crash on an internal assertion instead of exiting gracefully.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Build the attached source into a jar and run with a command line like:
./javac-1.6.0_01 TriggerJPLISAssert.java && jar -cfm triggerjplisassert.jar manifest.mf TriggerJPLISAssert.class TriggerJPLISAssert\$RoundAndRound.class && ./java-1.6.0_01 -server -javaagent:triggerjplisassert.jar -jar triggerjplisassert.jar
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Nothing should be output other than the "exiting" message. The daemon threads should be quietly shut down as they are if one comments out the getObjectSize() line.
ACTUAL -
A (variable) number of JPLISAssert failure messages are printed after the "exiting" message is printed by the main thread. Different runs produce a different number of messages.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Sample output:
exiting
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
no other stderr/stdout/core/hs_err_pid output.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
manifest.mf file:
Premain-Class: TriggerJPLISAssert
Main-Class: TriggerJPLISAssert
TriggerJPLISAssert.java file:
import java.lang.instrument.Instrumentation;
public class TriggerJPLISAssert {
private static Instrumentation instrumentation;
private TriggerJPLISAssert() { }
public static void premain(String agentArgs, Instrumentation inst) {
instrumentation = inst;
}
public static void main(String args[]) throws InterruptedException {
RoundAndRound[] threads = new RoundAndRound[10];
for (int i=0; i<threads.length; ++i) {
threads[i] = new RoundAndRound(instrumentation);
threads[i].start();
}
Thread.sleep(1); // let all threads get going in their loops
System.out.println("exiting");
}
private static class RoundAndRound extends Thread {
private final Instrumentation inst;
private final Object anObject;
public RoundAndRound(Instrumentation inst) {
this.inst = inst;
this.anObject = new Object();
setDaemon(true);
}
public void run() {
long sum = 0;
while (true) {
sum += inst.getObjectSize(anObject);
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Adding a shutdown hook with Runtime.getRuntime().addShutdownHook() which sets an application-specific "stop calling getObjectSize()" flag seems to prevent the crashes and lets my application exit gracefully.
This is an unsatisfactory long-term workaround because it requires adding synchronization (around the shutdown-indicating flag) for each invocation of getObjectSize(), or else living with a slight race condition by making the flag volatile and hoping shutdown doesn't proceed beyond the point that triggers the assert between the check of the flag and the call to getObjectSize().
I've copied the test from the description and added it to the
INSTRUMENT_REGRESSION test suite as StressGetObjectSizeTest.java.
Using the test I can reproduce the failure:
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b24)
Java HotSpot(TM) Client VM (build 12.0-b01, mixed mode, sharing)
STATUS:Passed.
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
result: Passed. Execution successful
Obviously JavaTest/JTREG thinks the test has passed so I'll
have to tweak it a bit to show up as a failure.
The following new test will fail without the fix for this
bug in a promoted JDK:
java/lang/instrument/StressGetObjectSizeTest.sh
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux d 2.6.18.5-XXX-mixed64-32 #1 SMP XXX x86_64 GNU/Linux
System is a modified ubuntu dapper.
EXTRA RELEVANT SYSTEM CONFIGURATION :
NPTL 2.3.6 from glibc 2.3.6.
A DESCRIPTION OF THE PROBLEM :
Calling Instrumentation.getObjectSize() while the JVM is attempting to exit causes the JVM to crash on an internal assertion instead of exiting gracefully.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Build the attached source into a jar and run with a command line like:
./javac-1.6.0_01 TriggerJPLISAssert.java && jar -cfm triggerjplisassert.jar manifest.mf TriggerJPLISAssert.class TriggerJPLISAssert\$RoundAndRound.class && ./java-1.6.0_01 -server -javaagent:triggerjplisassert.jar -jar triggerjplisassert.jar
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Nothing should be output other than the "exiting" message. The daemon threads should be quietly shut down as they are if one comments out the getObjectSize() line.
ACTUAL -
A (variable) number of JPLISAssert failure messages are printed after the "exiting" message is printed by the main thread. Different runs produce a different number of messages.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Sample output:
exiting
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE" at ../../../src/share/instrument/JPLISAgent.c line: 1296
no other stderr/stdout/core/hs_err_pid output.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
manifest.mf file:
Premain-Class: TriggerJPLISAssert
Main-Class: TriggerJPLISAssert
TriggerJPLISAssert.java file:
import java.lang.instrument.Instrumentation;
public class TriggerJPLISAssert {
private static Instrumentation instrumentation;
private TriggerJPLISAssert() { }
public static void premain(String agentArgs, Instrumentation inst) {
instrumentation = inst;
}
public static void main(String args[]) throws InterruptedException {
RoundAndRound[] threads = new RoundAndRound[10];
for (int i=0; i<threads.length; ++i) {
threads[i] = new RoundAndRound(instrumentation);
threads[i].start();
}
Thread.sleep(1); // let all threads get going in their loops
System.out.println("exiting");
}
private static class RoundAndRound extends Thread {
private final Instrumentation inst;
private final Object anObject;
public RoundAndRound(Instrumentation inst) {
this.inst = inst;
this.anObject = new Object();
setDaemon(true);
}
public void run() {
long sum = 0;
while (true) {
sum += inst.getObjectSize(anObject);
}
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Adding a shutdown hook with Runtime.getRuntime().addShutdownHook() which sets an application-specific "stop calling getObjectSize()" flag seems to prevent the crashes and lets my application exit gracefully.
This is an unsatisfactory long-term workaround because it requires adding synchronization (around the shutdown-indicating flag) for each invocation of getObjectSize(), or else living with a slight race condition by making the flag volatile and hoping shutdown doesn't proceed beyond the point that triggers the assert between the check of the flag and the call to getObjectSize().
I've copied the test from the description and added it to the
INSTRUMENT_REGRESSION test suite as StressGetObjectSizeTest.java.
Using the test I can reproduce the failure:
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b24)
Java HotSpot(TM) Client VM (build 12.0-b01, mixed mode, sharing)
STATUS:Passed.
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
*** java.lang.instrument ASSERTION FAILED ***: "jvmtierror == JVMTI_ERROR_NONE"
at ../../../src/share/instrument/JPLISAgent.c line: 1328
result: Passed. Execution successful
Obviously JavaTest/JTREG thinks the test has passed so I'll
have to tweak it a bit to show up as a failure.
The following new test will fail without the fix for this
bug in a promoted JDK:
java/lang/instrument/StressGetObjectSizeTest.sh
- backported by
-
JDK-8040112 Instrumentation.getObjectSize triggers JVM crash in JPLISAssert in shutdown
- Resolved
-
JDK-8040154 Instrumentation.getObjectSize triggers JVM crash in JPLISAssert in shutdown
- Resolved