-
Bug
-
Resolution: Fixed
-
P3
-
6
-
mustang
-
x86, sparc
-
solaris_2.5.1, solaris_9
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2123794 | 5.0u3 | Serguei Spitsyn | P3 | Resolved | Fixed | b05 |
Name: tb29552 Date: 08/26/2004
FULL PRODUCT VERSION :
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b60)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b60, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux deepspace1 2.4.22-10mdk #1 Thu Sep 18 12:30:58 CEST 2003 i686 unknown unknown GNU/Linux
A DESCRIPTION OF THE PROBLEM :
I have added a very simple example, that reproduces the problem:
The class (test.Startup) contains the instrumentation. It does nothing but replace the loaded class "test.Instrumented" with a new version (which is exactly the same as the old version). The loaded byte arrays is dumped to a file, so it is possible to compare it to the original classfile.
After reloading the class, invoking the constructor of "test.Instrumented" leads to a VerifyError. But since the classfile is exactly the same as before this should not happen.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.) Make a directory "test"
2.) Create the three java files in this directory ("Startup.java", "Instrumentation.java", "Test.java")
3.) Save the manifest as "manifest.mf"
3.) Compile the classes
javac test/*.java
4.) Build the jar file
jar -cvfm test.jar manifest.mf test/Startup.class
5.) Run the Test
java -classpath . -javaagent:test.jar test.Test
6.) A VerifyError is thrown.
7.) Observe that result.dump has exactly the same contents as test/Instrumentation.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception.
ACTUAL -
An VerifyError is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: (class: test/Instrument, method: <init> signature: ()V) Illegal constant pool index
at test.Test.main(Test.java:12)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
----------------------------------------------
Instrumented.java:
----------------------------------------------
package test;
public class Instrument {
}
----------------------------------------------
Startup.java:
----------------------------------------------
package test;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.ClassDefinition;
public class Startup {
private static Instrumentation instrumentation;
public static void premain(String options, Instrumentation instrumentation) {
Startup.instrumentation = instrumentation;
}
public static void init()
throws Exception {
Class[] allClasses = instrumentation.getAllLoadedClasses();
for (int i=0; i<allClasses.length; i++) {
String className = allClasses[i].getName();
if ("test.Instrument".equals(className)) {
byte[] classfileBuffer = getClassFileBuffer(className, allClasses[i].getClassLoader());
instrumentation.redefineClasses(new ClassDefinition[] {new ClassDefinition(allClasses[i], classfileBuffer)});
FileOutputStream fout = new FileOutputStream("result.dump");
fout.write(classfileBuffer);
fout.close();
}
}
}
private static final byte[] getClassFileBuffer(String className, ClassLoader cl) throws IOException {
InputStream is = cl.getResourceAsStream(className.replace('.', '/') + ".class");
byte[] buf = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream(is.available());
int read;
do {
read = is.read(buf);
if (read > -1) {
baos.write(buf, 0, read);
}
} while (read > -1);
is.close();
return baos.toByteArray();
}
}
----------------------------------------------
Test.java:
----------------------------------------------
package test;
public class Test {
public static void main(String[] args) throws Exception {
// load the class
System.out.println(Instrument.class.getName());
Startup.init();
// try to use it again -> causes VerifyError
new Instrument();
}
}
----------------------------------------------
manifest.mf:
----------------------------------------------
premain-class: test.Startup
Can-Redefine-Classes: true
---------- END SOURCE ----------
(Incident Review ID: 300972)
======================================================================
###@###.### 10/7/04 00:12 GMT
FULL PRODUCT VERSION :
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b60)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b60, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux deepspace1 2.4.22-10mdk #1 Thu Sep 18 12:30:58 CEST 2003 i686 unknown unknown GNU/Linux
A DESCRIPTION OF THE PROBLEM :
I have added a very simple example, that reproduces the problem:
The class (test.Startup) contains the instrumentation. It does nothing but replace the loaded class "test.Instrumented" with a new version (which is exactly the same as the old version). The loaded byte arrays is dumped to a file, so it is possible to compare it to the original classfile.
After reloading the class, invoking the constructor of "test.Instrumented" leads to a VerifyError. But since the classfile is exactly the same as before this should not happen.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.) Make a directory "test"
2.) Create the three java files in this directory ("Startup.java", "Instrumentation.java", "Test.java")
3.) Save the manifest as "manifest.mf"
3.) Compile the classes
javac test/*.java
4.) Build the jar file
jar -cvfm test.jar manifest.mf test/Startup.class
5.) Run the Test
java -classpath . -javaagent:test.jar test.Test
6.) A VerifyError is thrown.
7.) Observe that result.dump has exactly the same contents as test/Instrumentation.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No Exception.
ACTUAL -
An VerifyError is thrown.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.VerifyError: (class: test/Instrument, method: <init> signature: ()V) Illegal constant pool index
at test.Test.main(Test.java:12)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
----------------------------------------------
Instrumented.java:
----------------------------------------------
package test;
public class Instrument {
}
----------------------------------------------
Startup.java:
----------------------------------------------
package test;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.ClassDefinition;
public class Startup {
private static Instrumentation instrumentation;
public static void premain(String options, Instrumentation instrumentation) {
Startup.instrumentation = instrumentation;
}
public static void init()
throws Exception {
Class[] allClasses = instrumentation.getAllLoadedClasses();
for (int i=0; i<allClasses.length; i++) {
String className = allClasses[i].getName();
if ("test.Instrument".equals(className)) {
byte[] classfileBuffer = getClassFileBuffer(className, allClasses[i].getClassLoader());
instrumentation.redefineClasses(new ClassDefinition[] {new ClassDefinition(allClasses[i], classfileBuffer)});
FileOutputStream fout = new FileOutputStream("result.dump");
fout.write(classfileBuffer);
fout.close();
}
}
}
private static final byte[] getClassFileBuffer(String className, ClassLoader cl) throws IOException {
InputStream is = cl.getResourceAsStream(className.replace('.', '/') + ".class");
byte[] buf = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream(is.available());
int read;
do {
read = is.read(buf);
if (read > -1) {
baos.write(buf, 0, read);
}
} while (read > -1);
is.close();
return baos.toByteArray();
}
}
----------------------------------------------
Test.java:
----------------------------------------------
package test;
public class Test {
public static void main(String[] args) throws Exception {
// load the class
System.out.println(Instrument.class.getName());
Startup.init();
// try to use it again -> causes VerifyError
new Instrument();
}
}
----------------------------------------------
manifest.mf:
----------------------------------------------
premain-class: test.Startup
Can-Redefine-Classes: true
---------- END SOURCE ----------
(Incident Review ID: 300972)
======================================================================
###@###.### 10/7/04 00:12 GMT
- backported by
-
JDK-2123794 RedefineClasses causes VerifyError
- Resolved
- duplicates
-
JDK-6191049 java.lang.Instrumentation.redefineClass and -Xfuture cause VerifyError
- Closed
- relates to
-
JDK-8220783 InternalError on Instrumentation.retransformClasses()
- Open