FULL PRODUCT VERSION :
java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
SunOS mary 5.9 Generic_117171-07 sun4u sparc SUNW,Sun-Blade-100
A DESCRIPTION OF THE PROBLEM :
Instrumentation.redefineClasses ignores class redefinition.
The example given simulates instrumentation that is inserted and then removed. The "removal" does not work, which means that the instrumentation stays in the class file forever.
This is a regression, because the example worked for previous updates
(this is an update for the submission with internal ID 513516)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
In the directory where the files M.java, N.java and manif are, type
mkdir foo
echo 'package foo; public class Foo { public Foo() { System.out.println("1"); } public void print() { System.out.println("1"); System.out.println("print"); } }' > foo/Foo.java
javac foo/Foo.java
mv foo foo1
mkdir foo
echo 'package foo; public class Foo { public Foo() { System.out.println("1"); } public void print() { System.out.println("1"); System.out.println("print"); System.out.println("2"); } }' > foo/Foo.java
javac foo/Foo.java
mv foo foo2
mkdir foo
echo 'package foo; public class Foo { public Foo() { } public void print() { System.out.println("print"); } }' > foo/Foo.java
javac foo/Foo.java
javac *.java
jar cmf manif M.jar M.class
java -javaagent:M.jar N foo1/Foo.class foo2/Foo.class foo/Foo.class
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
print
using foo1/Foo.class
1
1
print
using foo2/Foo.class
1
1
print
2
using foo/Foo.class
print
This is the output with
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Server VM (build 1.5.0-b64, mixed mode)
ACTUAL -
print
using foo1/Foo.class
1
1
print
using foo2/Foo.class
1
1
print
2
using foo/Foo.class
1
print
The last "1" should not be there
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
-- M.java --
import java.io.*;
import java.lang.instrument.*;
public class M {
static Instrumentation instrumentation;
public static void redefine(Class cl, String fileName) {
try {
InputStream is = new FileInputStream(fileName);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int b;
while ((b = is.read()) != -1) {
out.write(b);
}
is.close();
ClassDefinition[] classDefs = {
new ClassDefinition(cl, out.toByteArray())
};
instrumentation.redefineClasses(classDefs);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public static void premain(String args, Instrumentation instrument) {
instrumentation = instrument;
}
}
-- cat N.java --
class N {
public static void main(String[] args) {
new foo.Foo().print();
for(String s: args) {
System.out.println("using " + s);
M.redefine(foo.Foo.class, s);
new foo.Foo().print();
}
}
}
-- manif --
Premain-Class: M
Boot-Class-Path: ./M.jar
Can-Redefine-Classes: true
---------- END SOURCE ----------