# HG changeset patch # User chegar # Date 1361876809 0 # Node ID 7aa557d76163d4994e89808dea4b4e605b933364 # Parent 265a0d86c9ffa47a61f79e3f47373599d68203a3# Parent 1bef8507dec2ee058973e40510eff3dcd14c907c Merge diff -r 265a0d86c9ff -r 7aa557d76163 jdk/src/share/classes/java/sql/CallableStatement.java --- a/jdk/src/share/classes/java/sql/CallableStatement.java Tue Feb 26 11:05:26 2013 +0000 +++ b/jdk/src/share/classes/java/sql/CallableStatement.java Tue Feb 26 11:06:49 2013 +0000 @@ -2621,7 +2621,7 @@ * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. *

- * This version of {@code registrOutParameter} should be + * This version of {@code registerOutParameter} should be * used when the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}. *

@@ -2649,7 +2649,7 @@ /** * Registers the designated output parameter. * This version of - * the method {@code registrOutParameter} + * the method {@code registerOutParameter} * should be used for a user-defined or {@code REF} output parameter. * Examples * of user-defined types include: {@code STRUCT}, {@code DISTINCT}, @@ -2717,7 +2717,7 @@ * register the OUT Parameter. * If the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}, the version of - * {@code registrOutParameter} that accepts a scale value + * {@code registerOutParameter} that accepts a scale value * should be used. * @exception SQLException if parameterName does not correspond to a named * parameter; if a database access error occurs or @@ -2745,7 +2745,7 @@ * parameter determines the Java type that must be used * in the {@code get} method to read the value of that parameter. *

- * This version of {@code registrOutParameter} should be + * This version of {@code registerOutParameter} should be * used when the parameter is of JDBC type {@code JDBCType.NUMERIC} * or {@code JDBCType.DECIMAL}. *

@@ -2774,7 +2774,7 @@ /** * Registers the designated output parameter. This version of - * the method {@code registrOutParameter} + * the method {@code registerOutParameter} * should be used for a user-named or REF output parameter. Examples * of user-named types include: STRUCT, DISTINCT, JAVA_OBJECT, and * named array types. diff -r 265a0d86c9ff -r 7aa557d76163 jdk/src/share/classes/java/util/jar/JarFile.java --- a/jdk/src/share/classes/java/util/jar/JarFile.java Tue Feb 26 11:05:26 2013 +0000 +++ b/jdk/src/share/classes/java/util/jar/JarFile.java Tue Feb 26 11:06:49 2013 +0000 @@ -63,8 +63,13 @@ private JarVerifier jv; private boolean jvInitialized; private boolean verify; - private boolean computedHasClassPathAttribute; + + // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true) private boolean hasClassPathAttribute; + // indicates if Profile attribute present (only valid if hasCheckedSpecialAttributes true) + private boolean hasProfileAttribute; + // true if manifest checked for special attributes + private volatile boolean hasCheckedSpecialAttributes; // Set up JavaUtilJarAccess in SharedSecrets static { @@ -421,27 +426,45 @@ jv); } - // Statics for hand-coded Boyer-Moore search in hasClassPathAttribute() + // Statics for hand-coded Boyer-Moore search + private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'}; + private static final char[] PROFILE_CHARS = { 'p', 'r', 'o', 'f', 'i', 'l', 'e' }; // The bad character shift for "class-path" - private static int[] lastOcc; + private static final int[] CLASSPATH_LASTOCC; // The good suffix shift for "class-path" - private static int[] optoSft; - // Initialize the shift arrays to search for "class-path" - private static char[] src = {'c','l','a','s','s','-','p','a','t','h'}; + private static final int[] CLASSPATH_OPTOSFT; + // The bad character shift for "profile" + private static final int[] PROFILE_LASTOCC; + // The good suffix shift for "profile" + private static final int[] PROFILE_OPTOSFT; + static { - lastOcc = new int[128]; - optoSft = new int[10]; - lastOcc[(int)'c']=1; - lastOcc[(int)'l']=2; - lastOcc[(int)'s']=5; - lastOcc[(int)'-']=6; - lastOcc[(int)'p']=7; - lastOcc[(int)'a']=8; - lastOcc[(int)'t']=9; - lastOcc[(int)'h']=10; + CLASSPATH_LASTOCC = new int[128]; + CLASSPATH_OPTOSFT = new int[10]; + CLASSPATH_LASTOCC[(int)'c'] = 1; + CLASSPATH_LASTOCC[(int)'l'] = 2; + CLASSPATH_LASTOCC[(int)'s'] = 5; + CLASSPATH_LASTOCC[(int)'-'] = 6; + CLASSPATH_LASTOCC[(int)'p'] = 7; + CLASSPATH_LASTOCC[(int)'a'] = 8; + CLASSPATH_LASTOCC[(int)'t'] = 9; + CLASSPATH_LASTOCC[(int)'h'] = 10; for (int i=0; i<9; i++) - optoSft[i]=10; - optoSft[9]=1; + CLASSPATH_OPTOSFT[i] = 10; + CLASSPATH_OPTOSFT[9]=1; + + PROFILE_LASTOCC = new int[128]; + PROFILE_OPTOSFT = new int[7]; + PROFILE_LASTOCC[(int)'p'] = 1; + PROFILE_LASTOCC[(int)'r'] = 2; + PROFILE_LASTOCC[(int)'o'] = 3; + PROFILE_LASTOCC[(int)'f'] = 4; + PROFILE_LASTOCC[(int)'i'] = 5; + PROFILE_LASTOCC[(int)'l'] = 6; + PROFILE_LASTOCC[(int)'e'] = 7; + for (int i=0; i<6; i++) + PROFILE_OPTOSFT[i] = 7; + PROFILE_OPTOSFT[6] = 1; } private JarEntry getManEntry() { @@ -466,17 +489,55 @@ return manEntry; } - // Returns true iff this jar file has a manifest with a class path - // attribute. Returns false if there is no manifest or the manifest - // does not contain a "Class-Path" attribute. Currently exported to - // core libraries via sun.misc.SharedSecrets. + /** + * Returns {@code true} iff this JAR file has a manifest with the + * Class-Path attribute + */ boolean hasClassPathAttribute() throws IOException { - if (computedHasClassPathAttribute) { - return hasClassPathAttribute; + checkForSpecialAttributes(); + return hasClassPathAttribute; + } + + /** + * Returns {@code true} iff this JAR file has a manifest with the + * Profile attribute + */ + boolean hasProfileAttribute() throws IOException { + checkForSpecialAttributes(); + return hasProfileAttribute; + } + + /** + * Returns true if the pattern {@code src} is found in {@code b}. + * The {@code lastOcc} and {@code optoSft} arrays are the precomputed + * bad character and good suffix shifts. + */ + private boolean match(char[] src, byte[] b, int[] lastOcc, int[] optoSft) { + int len = src.length; + int last = b.length - len; + int i = 0; + next: + while (i<=last) { + for (int j=(len-1); j>=0; j--) { + char c = (char) b[i+j]; + c = (((c-'A')|('Z'-c)) >= 0) ? (char)(c + 32) : c; + if (c != src[j]) { + i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]); + continue next; + } + } + return true; } + return false; + } - hasClassPathAttribute = false; - if (!isKnownToNotHaveClassPathAttribute()) { + /** + * On first invocation, check if the JAR file has the Class-Path + * and/or Profile attributes. A no-op on subsequent calls. + */ + private void checkForSpecialAttributes() throws IOException { + if (hasCheckedSpecialAttributes) return; + if (!isKnownNotToHaveSpecialAttributes()) { JarEntry manEntry = getManEntry(); if (manEntry != null) { byte[] b = new byte[(int)manEntry.getSize()]; @@ -484,31 +545,18 @@ super.getInputStream(manEntry))) { dis.readFully(b, 0, b.length); } - - int last = b.length - src.length; - int i = 0; - next: - while (i<=last) { - for (int j=9; j>=0; j--) { - char c = (char) b[i+j]; - c = (((c-'A')|('Z'-c)) >= 0) ? (char)(c + 32) : c; - if (c != src[j]) { - i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]); - continue next; - } - } + if (match(CLASSPATH_CHARS, b, CLASSPATH_LASTOCC, CLASSPATH_OPTOSFT)) hasClassPathAttribute = true; - break; - } + if (match(PROFILE_CHARS, b, PROFILE_LASTOCC, PROFILE_OPTOSFT)) + hasProfileAttribute = true; } } - computedHasClassPathAttribute = true; - return hasClassPathAttribute; + hasCheckedSpecialAttributes = true; } private static String javaHome; - private static String[] jarNames; - private boolean isKnownToNotHaveClassPathAttribute() { + private static volatile String[] jarNames; + private boolean isKnownNotToHaveSpecialAttributes() { // Optimize away even scanning of manifest for jar files we // deliver which don't have a class-path attribute. If one of // these jars is changed to include such an attribute this code @@ -518,19 +566,20 @@ new GetPropertyAction("java.home")); } if (jarNames == null) { - String[] names = new String[10]; + String[] names = new String[11]; String fileSep = File.separator; int i = 0; names[i++] = fileSep + "rt.jar"; - names[i++] = fileSep + "sunrsasign.jar"; names[i++] = fileSep + "jsse.jar"; names[i++] = fileSep + "jce.jar"; names[i++] = fileSep + "charsets.jar"; names[i++] = fileSep + "dnsns.jar"; - names[i++] = fileSep + "ldapsec.jar"; + names[i++] = fileSep + "zipfs.jar"; names[i++] = fileSep + "localedata.jar"; + names[i++] = fileSep = "cldrdata.jar"; names[i++] = fileSep + "sunjce_provider.jar"; names[i++] = fileSep + "sunpkcs11.jar"; + names[i++] = fileSep + "sunec.jar"; jarNames = names; } diff -r 265a0d86c9ff -r 7aa557d76163 jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java --- a/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Tue Feb 26 11:05:26 2013 +0000 +++ b/jdk/src/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Tue Feb 26 11:06:49 2013 +0000 @@ -37,6 +37,10 @@ return jar.hasClassPathAttribute(); } + public boolean jarFileHasProfileAttribute(JarFile jar) throws IOException { + return jar.hasProfileAttribute(); + } + public CodeSource[] getCodeSources(JarFile jar, URL url) { return jar.getCodeSources(url); } diff -r 265a0d86c9ff -r 7aa557d76163 jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java --- a/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java Tue Feb 26 11:05:26 2013 +0000 +++ b/jdk/src/share/classes/sun/misc/JavaUtilJarAccess.java Tue Feb 26 11:06:49 2013 +0000 @@ -35,6 +35,7 @@ public interface JavaUtilJarAccess { public boolean jarFileHasClassPathAttribute(JarFile jar) throws IOException; + public boolean jarFileHasProfileAttribute(JarFile jar) throws IOException; public CodeSource[] getCodeSources(JarFile jar, URL url); public CodeSource getCodeSource(JarFile jar, URL url, String name); public Enumeration entryNames(JarFile jar, CodeSource[] cs); diff -r 265a0d86c9ff -r 7aa557d76163 jdk/src/share/classes/sun/misc/URLClassPath.java --- a/jdk/src/share/classes/sun/misc/URLClassPath.java Tue Feb 26 11:05:26 2013 +0000 +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java Tue Feb 26 11:06:49 2013 +0000 @@ -808,9 +808,6 @@ /** * If the Profile attribute is present then this method checks that the runtime * supports that profile. - * - * ## Add a fast path like Class-Path to avoid reading the manifest when the attribute - * is not present. */ void checkProfileAttribute() throws IOException { Manifest man = jar.getManifest(); @@ -998,7 +995,8 @@ parseExtensionsDependencies(); // check Profile attribute if present - if (!profileCheckSuppressedByLauncher) { + if (!profileCheckSuppressedByLauncher && + SharedSecrets.javaUtilJarAccess().jarFileHasProfileAttribute(jar)) { checkProfileAttribute(); } diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodInBacktrace.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktrace.sh Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,87 @@ +# +# Copyright (c) 2013, 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 7174978 +# @summary Redefine a class with a method stored in a backtrace. +# @author Stefan Karlsson +# +# @run shell MakeJAR3.sh RedefineMethodInBacktraceAgent 'Can-Redefine-Classes: true' +# @run build RedefineMethodInBacktraceTarget RedefineMethodInBacktraceApp +# @run shell RedefineMethodInBacktrace.sh +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + +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 + +JAVAC="${COMPILEJAVA}"/bin/javac +JAVA="${TESTJAVA}"/bin/java + +cp "${TESTSRC}"/RedefineMethodInBacktraceTarget_2.java \ + RedefineMethodInBacktraceTarget.java +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . RedefineMethodInBacktraceTarget.java + +"${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodInBacktraceAgent.jar \ + -classpath "${TESTCLASSES}" RedefineMethodInBacktraceApp > output.log 2>&1 +RUN_RESULT=$? + +if [ $RUN_RESULT != 0 ]; then + echo "FAIL: the run failed with exit code '$RUN_RESULT'" + exit $RUN_RESULT +fi + +cat output.log + +MESG="Exception" +grep "$MESG" output.log +result=$? +if [ "$result" = 0 ]; then + echo "FAIL: found '$MESG' in the test output" + result=1 +else + echo "PASS: did NOT find '$MESG' in the test output" + result=0 +fi + +exit $result diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodInBacktraceAgent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceAgent.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.lang.instrument.Instrumentation; + +public class RedefineMethodInBacktraceAgent { + private static Instrumentation instrumentation; + + private RedefineMethodInBacktraceAgent() {} + + public static void premain(String agentArgs, Instrumentation inst) { + System.out.println("Hello from RedefineMethodInBacktraceAgent!"); + System.out.println("isRedefineClassesSupported()=" + + inst.isRedefineClassesSupported()); + + instrumentation = inst; + } + + public static Instrumentation getInstrumentation() { + return instrumentation; + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, 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.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.instrument.ClassDefinition; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * When an exception is thrown, the JVM collects just enough information + * about the stack trace to be able to create a full fledged stack trace + * (StackTraceElement[]). The backtrace contains this information and the + * JVM must make sure that the data in the backtrace is still usable after + * a class redefinition. + * + * After the PermGen removal there was a bug when the last reference to a Method + * was in the backtrace. The class of the method was kept alive, because of the + * mirror stored in the backtrace, but the old versions of the redefined method + * could be freed, since class redefinition didn't know about the backtraces. + */ +public class RedefineMethodInBacktraceApp { + public static void main(String args[]) throws Exception { + System.out.println("Hello from RedefineMethodInBacktraceApp!"); + + new RedefineMethodInBacktraceApp().doTest(); + + System.exit(0); + } + + private void doTest() throws Exception { + doMethodInBacktraceTest(); + } + + private void doMethodInBacktraceTest() throws Exception { + Throwable t = getThrowableFromMethodToRedefine(); + + doRedefine(RedefineMethodInBacktraceTarget.class); + + doClassUnloading(); + + touchRedefinedMethodInBacktrace(t); + } + + private static Throwable getThrowableFromMethodToRedefine() throws Exception { + Class c = + RedefineMethodInBacktraceTarget.class; + Method method = c.getMethod("methodToRedefine"); + + Throwable thrownFromMethodToRedefine = null; + try { + method.invoke(null); + } catch (InvocationTargetException e) { + thrownFromMethodToRedefine = e.getCause(); + if (!(thrownFromMethodToRedefine instanceof RuntimeException)) { + throw e; + } + } + method = null; + c = null; + + return thrownFromMethodToRedefine; + } + + private static void doClassUnloading() { + // This will clean out old, unused redefined methods. + System.gc(); + } + + private static void touchRedefinedMethodInBacktrace(Throwable throwable) { + // Make sure that we can convert the backtrace, which is referring to + // the redefined method, to a StrackTraceElement[] without crashing. + throwable.getStackTrace(); + } + + private static void doRedefine(Class clazz) throws Exception { + // Load the second version of this class. + File f = new File(clazz.getName() + ".class"); + System.out.println("Reading test class from " + f.getAbsolutePath()); + InputStream redefineStream = new FileInputStream(f); + + byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream); + + ClassDefinition redefineParamBlock = new ClassDefinition( + clazz, redefineBuffer); + + RedefineMethodInBacktraceAgent.getInstrumentation().redefineClasses( + new ClassDefinition[] {redefineParamBlock}); + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, 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. + */ + +/** + * The first version of this class. The second version is in + * RedefineMethodInBacktraceTarget_2.java. + */ +public class RedefineMethodInBacktraceTarget { + public static void methodToRedefine() { + throw new RuntimeException("Test exception"); + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget_2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceTarget_2.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013, 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. + */ + +/** + * This is the second version of this class. The first version is in + * RedefineMethodInBacktraceTarget.java. + */ +public class RedefineMethodInBacktraceTarget { + public static void methodToRedefine() { + throw new RuntimeException("Test exception 2"); + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotations.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotations.sh Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,85 @@ +# +# Copyright (c) 2013, 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 7022100 +# @summary Method annotations are incorrectly set when redefining classes. +# @author Stefan Karlsson +# +# @run shell MakeJAR3.sh RedefineMethodWithAnnotationsAgent 'Can-Redefine-Classes: true' +# @run build RedefineMethodWithAnnotationsTarget RedefineMethodWithAnnotationsApp RedefineMethodWithAnnotationsAnnotations +# @run shell RedefineMethodWithAnnotations.sh +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${COMPILEJAVA}" = "" ] +then + COMPILEJAVA="${TESTJAVA}" +fi +echo "COMPILEJAVA=${COMPILEJAVA}" + +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 + +JAVAC="${COMPILEJAVA}"/bin/javac +JAVA="${TESTJAVA}"/bin/java + +cp "${TESTSRC}"/RedefineMethodWithAnnotationsTarget_2.java \ + RedefineMethodWithAnnotationsTarget.java +cp "${TESTSRC}"/RedefineMethodWithAnnotationsAnnotations.java \ + RedefineMethodWithAnnotationsAnnotations.java + +"${JAVAC}" ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . \ + RedefineMethodWithAnnotationsTarget.java \ + RedefineMethodWithAnnotationsAnnotations.java + +"${JAVA}" ${TESTVMOPTS} -javaagent:RedefineMethodWithAnnotationsAgent.jar \ + -cp "${TESTCLASSES}" RedefineMethodWithAnnotationsApp > output.log 2>&1 +cat output.log + +MESG="Exception" +grep "$MESG" output.log +result=$? +if [ "$result" = 0 ]; then + echo "FAIL: found '$MESG' in the test output" + result=1 +else + echo "PASS: did NOT find '$MESG' in the test output" + result=0 +fi + +exit $result diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAgent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAgent.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, 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.lang.instrument.Instrumentation; + +public class RedefineMethodWithAnnotationsAgent { + private static Instrumentation instrumentation; + + private RedefineMethodWithAnnotationsAgent() {} + + public static void premain(String agentArgs, Instrumentation inst) { + System.out.println("Hello from RedefineMethodWithAnnotationsAgent!"); + System.out.println("isRedefineClassesSupported()=" + + inst.isRedefineClassesSupported()); + + instrumentation = inst; + } + + public static Instrumentation getInstrumentation() { + return instrumentation; + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAnnotations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsAnnotations.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, 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.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@interface ParameterAnnotation { + // Values used for the annotations in the first version of the target class. + static final String STRING_VALUE_1 = "String1"; + static final String INT_VALUE_1 = "Int1"; + + // Values used for the annotations in the second version of the target class. + static final String STRING_VALUE_2 = "String2"; + static final String INT_VALUE_2 = "Int2"; + + String value(); +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsApp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsApp.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, 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.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.instrument.ClassDefinition; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; + +public class RedefineMethodWithAnnotationsApp { + public static void main(String args[]) throws Exception { + System.out.println("Hello from RedefineMethodWithAnnotationsApp!"); + + new RedefineMethodWithAnnotationsApp().doTest(); + + System.exit(0); + } + + private void doTest() throws Exception { + doMethodParameterAnnotationsTest(); + } + + private void doMethodParameterAnnotationsTest() throws Exception { + verifyMethodParameterAnnotationsValue( + ParameterAnnotation.STRING_VALUE_1); + + doRedefine(RedefineMethodWithAnnotationsTarget.class); + + verifyMethodParameterAnnotationsValue( + ParameterAnnotation.STRING_VALUE_2); + } + + private static void verifyMethodParameterAnnotationsValue( + String expectedValue) throws Exception { + Class c = + RedefineMethodWithAnnotationsTarget.class; + Method method = c.getMethod("annotatedMethod", String.class); + + Annotation [][] parametersAnnotations = + method.getParameterAnnotations(); + if (parametersAnnotations.length != 1) { + throw new Exception("Incorrect number of parameters to method: " + + method.getName() + "." + + " Expected: 1," + + " got: " + parametersAnnotations.length); + } + + Annotation[] parameterAnnotations = parametersAnnotations[0]; + if (parameterAnnotations.length != 1) { + throw new Exception("Incorrect number of annotations." + + " Expected: 1" + + ", got " + parameterAnnotations.length); + } + + Annotation parameterAnnotation = parameterAnnotations[0]; + if (!(parameterAnnotation instanceof ParameterAnnotation)) { + throw new Exception("Incorrect Annotation class." + + " Expected: " + ParameterAnnotation.class.getName() + + ", got: " + parameterAnnotation.getClass().getName()); + } + + ParameterAnnotation pa = (ParameterAnnotation)parameterAnnotation; + String annotationValue = pa.value(); + if (!expectedValue.equals(annotationValue)) { + throw new Exception("Incorrect parameter annotation value." + + " Expected: " + expectedValue + + ", got: " + annotationValue); + } + } + + private static void doRedefine(Class clazz) throws Exception { + // Load the second version of this class. + File f = new File(clazz.getName() + ".class"); + System.out.println("Reading test class from " + f); + InputStream redefineStream = new FileInputStream(f); + + byte[] redefineBuffer = NamedBuffer.loadBufferFromStream(redefineStream); + + ClassDefinition redefineParamBlock = new ClassDefinition( + clazz, redefineBuffer); + + RedefineMethodWithAnnotationsAgent.getInstrumentation().redefineClasses( + new ClassDefinition[] {redefineParamBlock}); + } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, 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. + */ + +/** + * The first version of this class. The second version is in + * RedefineMethodWithAnnotationsTarget_2.java. + */ +public class RedefineMethodWithAnnotationsTarget { + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.STRING_VALUE_1) String parameter) { } + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.INT_VALUE_1) int parameter) { } +} diff -r 265a0d86c9ff -r 7aa557d76163 jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget_2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/instrument/RedefineMethodWithAnnotationsTarget_2.java Tue Feb 26 11:06:49 2013 +0000 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, 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. + */ + +/** + * This is the second version of this class. The first version is in + * RedefineMethodWithAnnotationsTarget.java. + *

+ * It has the same methods but with different annotations and order. + */ +public class RedefineMethodWithAnnotationsTarget { + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.INT_VALUE_2) int parameter) { } + public void annotatedMethod(@ParameterAnnotation( + value = ParameterAnnotation.STRING_VALUE_2) String parameter) { } +}