ADDITIONAL SYSTEM INFORMATION :
java version "17.0.1" 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
JVM crashes after some time due to erorr in C2 compiler while processing potentially invalid bytecode.
Flags -XX:-TieredCompilation -Xcomp -Xbatch were used to simplify the test case.
Part of the core dump:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (ciEnv.cpp:687), pid=1404, tid=4804
# Error: ShouldNotReachHere()
#
# JRE version: Java(TM) SE Runtime Environment (17.0.1+12) (build 17.0.1+12-LTS-39)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (17.0.1+12-LTS-39, compiled mode, sharing, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
# https://bugreport.java.com/bugreport/crash.jsp
#
REGRESSION : Last worked in version 16.0.2
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile a class that contains virtual/static method in it.
Change it's access to be virtual if it was static, and vice versa.
Keep invoking the method till C2 compiler crashes.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
JVM does not crash
ACTUAL -
JVM crashes with core dump
---------- BEGIN SOURCE ----------
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Type;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.objectweb.asm.Opcodes.*;
public class CompilerCrash {
public static void main(String[] args) throws Exception {
var cw = new ClassWriter(0);
cw.visit(V17, ACC_PUBLIC, "BadClass", null, "java/lang/Object", null);
var mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "crash", "()V", null, null);
mv.visitCode();
mv.visitLdcInsn(
new Handle(
H_INVOKESTATIC,
"java/lang/Class",
"cast",
"(Ljava/lang/Object;)Ljava/lang/Object;",
false));
mv.visitLdcInsn(Type.getType(String.class));
mv.visitLdcInsn("some object");
mv.visitMethodInsn(
INVOKEVIRTUAL,
"java/lang/invoke/MethodHandle",
"invoke",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 0);
byte[] classBytes = cw.toByteArray();
var loader = new BytesClassLoader("BadClass", classBytes);
var method = Class.forName("BadClass", true, loader).getMethod("crash");
for (int i = 0; i < 16000; i++)
try {
method.invoke(null);
} catch (InvocationTargetException ignored) {
}
}
private static final class BytesClassLoader extends ClassLoader {
private final String name;
private final byte[] bytes;
BytesClassLoader(String name, byte[] bytes) {
this.name = name;
this.bytes = bytes;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
if (!this.name.equals(name)) {
throw new ClassNotFoundException(name);
}
byte[] bytes = this.bytes;
return defineClass(name, bytes, 0, bytes.length);
}
}
}
---------- END SOURCE ----------
FREQUENCY : always