7191322: add test for 7064927 to java.lang.instrument
Summary: Add support for canRetransform attribute to the test manager. Add test for 7064927.
Reviewed-by: dsamersoff, sspitsyn, ohair
--- a/jdk/test/java/lang/instrument/ATransformerManagementTestCase.java Fri Aug 17 14:32:50 2012 -0400
+++ b/jdk/test/java/lang/instrument/ATransformerManagementTestCase.java Fri Aug 17 12:51:23 2012 -0700
@@ -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
@@ -99,12 +99,28 @@
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);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/DummyClassWithLVT.java Fri Aug 17 12:51:23 2012 -0700
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/VerifyLocalVariableTableOnRetransformTest.java Fri Aug 17 12:51:23 2012 -0700
@@ -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;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/VerifyLocalVariableTableOnRetransformTest.sh Fri Aug 17 12:51:23 2012 -0700
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/instrument/retransformAgent.mf Fri Aug 17 12:51:23 2012 -0700
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Premain-Class: InstrumentationHandoff
+Can-Retransform-Classes: true