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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -98,13 +98,29 @@ ATransformerManagementTestCase
|
|||||||
addTransformerToManager(
|
addTransformerToManager(
|
||||||
Instrumentation manager,
|
Instrumentation manager,
|
||||||
ClassFileTransformer transformer)
|
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)
|
if (transformer != null)
|
||||||
{
|
{
|
||||||
fTransformers.add(transformer);
|
fTransformers.add(transformer);
|
||||||
}
|
}
|
||||||
manager.addTransformer(transformer);
|
manager.addTransformer(transformer, canRetransform);
|
||||||
verbosePrint("Added transformer " + transformer);
|
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