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:
Daniel D. Daugherty 2012-08-17 12:51:23 -07:00
parent 630647752a
commit 3be453e452
5 changed files with 342 additions and 3 deletions

View File

@ -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);
}
/**

View 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);
}
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Premain-Class: InstrumentationHandoff
Can-Retransform-Classes: true