7191322: add test for 7064927 to java.lang.instrument
Add support for canRetransform attribute to the test manager. Add test for 7064927. Reviewed-by: dsamersoff, sspitsyn, ohair
This commit is contained in:
parent
630647752a
commit
3be453e452
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -98,13 +98,29 @@ ATransformerManagementTestCase
|
||||
addTransformerToManager(
|
||||
Instrumentation manager,
|
||||
ClassFileTransformer transformer)
|
||||
{
|
||||
addTransformerToManager(manager, transformer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method addTransformerToManager.
|
||||
* @param manager
|
||||
* @param transformer
|
||||
* @param canRetransform
|
||||
*/
|
||||
protected void
|
||||
addTransformerToManager(
|
||||
Instrumentation manager,
|
||||
ClassFileTransformer transformer,
|
||||
boolean canRetransform)
|
||||
{
|
||||
if (transformer != null)
|
||||
{
|
||||
fTransformers.add(transformer);
|
||||
}
|
||||
manager.addTransformer(transformer);
|
||||
verbosePrint("Added transformer " + transformer);
|
||||
manager.addTransformer(transformer, canRetransform);
|
||||
verbosePrint("Added transformer " + transformer
|
||||
+ " with canRetransform=" + canRetransform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
45
jdk/test/java/lang/instrument/DummyClassWithLVT.java
Normal file
45
jdk/test/java/lang/instrument/DummyClassWithLVT.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
public class DummyClassWithLVT
|
||||
{
|
||||
public static void main(String[] args) {
|
||||
boolean b = true;
|
||||
byte by = 0x42;
|
||||
char c = 'X';
|
||||
double d = 1.1;
|
||||
float f = (float) 1.2;
|
||||
int i = 42;
|
||||
long l = 0xCAFEBABE;
|
||||
short s = 88;
|
||||
|
||||
System.out.println("b=" + b);
|
||||
System.out.println("by=" + by);
|
||||
System.out.println("c=" + c);
|
||||
System.out.println("d=" + d);
|
||||
System.out.println("f=" + f);
|
||||
System.out.println("i=" + i);
|
||||
System.out.println("l=" + l);
|
||||
System.out.println("s=" + s);
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.net.*;
|
||||
import java.security.ProtectionDomain;
|
||||
|
||||
public class
|
||||
VerifyLocalVariableTableOnRetransformTest
|
||||
extends ATransformerManagementTestCase
|
||||
{
|
||||
private byte[] fTargetClassBytes;
|
||||
private boolean fTargetClassMatches;
|
||||
private String fTargetClassName = "DummyClassWithLVT";
|
||||
private boolean fTargetClassSeen;
|
||||
|
||||
/**
|
||||
* Constructor for VerifyLocalVariableTableOnRetransformTest.
|
||||
* @param name
|
||||
*/
|
||||
public VerifyLocalVariableTableOnRetransformTest(String name)
|
||||
{
|
||||
super(name);
|
||||
|
||||
String resourceName = fTargetClassName + ".class";
|
||||
File f = new File(System.getProperty("test.classes", "."), resourceName);
|
||||
System.out.println("Reading test class from " + f);
|
||||
try
|
||||
{
|
||||
InputStream redefineStream = new FileInputStream(f);
|
||||
fTargetClassBytes = NamedBuffer.loadBufferFromStream(redefineStream);
|
||||
System.out.println("Read " + fTargetClassBytes.length + " bytes.");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
fail("Could not load the class: "+resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void
|
||||
main (String[] args)
|
||||
throws Throwable {
|
||||
ATestCaseScaffold test = new VerifyLocalVariableTableOnRetransformTest(args[0]);
|
||||
test.runTest();
|
||||
}
|
||||
|
||||
protected final void
|
||||
doRunTest()
|
||||
throws Throwable {
|
||||
verifyClassFileBuffer();
|
||||
}
|
||||
|
||||
public void
|
||||
verifyClassFileBuffer()
|
||||
throws Throwable
|
||||
{
|
||||
beVerbose();
|
||||
|
||||
// With this call here, we will see the target class twice:
|
||||
// first when it gets loaded and second when it gets retransformed.
|
||||
addTransformerToManager(fInst, new MyObserver(), true);
|
||||
|
||||
ClassLoader loader = getClass().getClassLoader();
|
||||
|
||||
Class target = loader.loadClass(fTargetClassName);
|
||||
assertEquals(fTargetClassName, target.getName());
|
||||
|
||||
// make an instance to prove the class was really loaded
|
||||
Object testInstance = target.newInstance();
|
||||
|
||||
// With this call here, we will see the target class once:
|
||||
// when it gets retransformed.
|
||||
//addTransformerToManager(fInst, new MyObserver(), true);
|
||||
|
||||
assertTrue(fTargetClassName + " was not seen by transform()",
|
||||
fTargetClassSeen);
|
||||
|
||||
// The HotSpot VM hands us class file bytes at initial class
|
||||
// load time that match the .class file contents. However,
|
||||
// according to the following spec that is not required:
|
||||
// http://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html#retransformClasses(java.lang.Class...)
|
||||
// This test exists to catch any unintentional change in
|
||||
// behavior by the HotSpot VM. If this behavior is intentionally
|
||||
// changed in the future, then this test will need to be
|
||||
// updated.
|
||||
assertTrue(fTargetClassName + " did not match .class file",
|
||||
fTargetClassMatches);
|
||||
|
||||
fTargetClassSeen = false;
|
||||
fTargetClassMatches = false;
|
||||
|
||||
fInst.retransformClasses(target);
|
||||
|
||||
assertTrue(fTargetClassName + " was not seen by transform()",
|
||||
fTargetClassSeen);
|
||||
|
||||
// The HotSpot VM doesn't currently preserve the LocalVariable
|
||||
// Table (LVT) attribute so the class file bytes seen by the
|
||||
// retransformClasses() call will not match the class file bytes
|
||||
// seen at initial class load time.
|
||||
assertTrue(fTargetClassName + " did not match .class file",
|
||||
fTargetClassMatches);
|
||||
}
|
||||
|
||||
public class MyObserver implements ClassFileTransformer {
|
||||
public MyObserver() {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return MyObserver.this.getClass().getName();
|
||||
}
|
||||
|
||||
private void saveMismatchedBytes(byte[] classfileBuffer) {
|
||||
try {
|
||||
FileOutputStream fos = null;
|
||||
// This file will get created in the test execution
|
||||
// directory so there is no conflict with the file
|
||||
// in the test classes directory.
|
||||
String resourceName = fTargetClassName + ".class";
|
||||
fos = new FileOutputStream(resourceName);
|
||||
fos.write(classfileBuffer);
|
||||
fos.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public byte[]
|
||||
transform(
|
||||
ClassLoader loader,
|
||||
String className,
|
||||
Class<?> classBeingRedefined,
|
||||
ProtectionDomain protectionDomain,
|
||||
byte[] classfileBuffer) {
|
||||
|
||||
System.out.println(this + ".transform() sees '" + className
|
||||
+ "' of " + classfileBuffer.length + " bytes.");
|
||||
if (className.equals(fTargetClassName)) {
|
||||
fTargetClassSeen = true;
|
||||
|
||||
if (classfileBuffer.length != fTargetClassBytes.length) {
|
||||
System.out.println("Warning: " + fTargetClassName
|
||||
+ " lengths do not match.");
|
||||
fTargetClassMatches = false;
|
||||
saveMismatchedBytes(classfileBuffer);
|
||||
return null;
|
||||
} else {
|
||||
System.out.println("Info: " + fTargetClassName
|
||||
+ " lengths match.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < classfileBuffer.length; i++) {
|
||||
if (classfileBuffer[i] != fTargetClassBytes[i]) {
|
||||
System.out.println("Warning: " + fTargetClassName
|
||||
+ "[" + i + "]: '" + classfileBuffer[i]
|
||||
+ "' != '" + fTargetClassBytes[i] + "'");
|
||||
fTargetClassMatches = false;
|
||||
saveMismatchedBytes(classfileBuffer);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
fTargetClassMatches = true;
|
||||
System.out.println("Info: verified '" + fTargetClassName
|
||||
+ ".class' matches 'classfileBuffer'.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 7064927
|
||||
# @summary Verify LocalVariableTable (LVT) exists when passed to
|
||||
# transform() on a retransform operation.
|
||||
# @author Daniel D. Daugherty
|
||||
#
|
||||
# @run build VerifyLocalVariableTableOnRetransformTest
|
||||
# @run compile -g DummyClassWithLVT.java
|
||||
# @run shell MakeJAR.sh retransformAgent
|
||||
# @run shell VerifyLocalVariableTableOnRetransformTest.sh
|
||||
|
||||
|
||||
if [ "${TESTJAVA}" = "" ]
|
||||
then
|
||||
echo "TESTJAVA not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${TESTSRC}" = "" ]
|
||||
then
|
||||
echo "TESTSRC not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${TESTCLASSES}" = "" ]
|
||||
then
|
||||
echo "TESTCLASSES not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JAVA="${TESTJAVA}"/bin/java
|
||||
|
||||
"${JAVA}" ${TESTVMOPTS} -Dtest.classes="${TESTCLASSES}" \
|
||||
-javaagent:retransformAgent.jar \
|
||||
-classpath "${TESTCLASSES}" \
|
||||
VerifyLocalVariableTableOnRetransformTest \
|
||||
VerifyLocalVariableTableOnRetransformTest \
|
||||
> output.log 2>&1
|
||||
cat output.log
|
||||
|
||||
MESG="did not match .class file"
|
||||
grep "$MESG" output.log
|
||||
result=$?
|
||||
if [ "$result" = 0 ]; then
|
||||
echo "FAIL: found '$MESG' in the test output"
|
||||
|
||||
echo "INFO: 'javap -v' comparison between the .class files:"
|
||||
${JAVA}p -v -classpath "${TESTCLASSES}" DummyClassWithLVT > orig.javap
|
||||
${JAVA}p -v DummyClassWithLVT > mismatched.javap
|
||||
diff orig.javap mismatched.javap
|
||||
|
||||
result=1
|
||||
else
|
||||
echo "PASS: did NOT find '$MESG' in the test output"
|
||||
result=0
|
||||
fi
|
||||
|
||||
exit $result
|
3
jdk/test/java/lang/instrument/retransformAgent.mf
Normal file
3
jdk/test/java/lang/instrument/retransformAgent.mf
Normal file
@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Premain-Class: InstrumentationHandoff
|
||||
Can-Retransform-Classes: true
|
Loading…
x
Reference in New Issue
Block a user