Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ClassVersionAfterRedefine.java
41153 views
/*1* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 826755526* @requires vm.jvmti27* @summary Class redefinition with a different class file version28* @library /test/lib29* @compile TestClassOld.jasm TestClassNew.jasm30* @run main RedefineClassHelper31* @run main/othervm -javaagent:redefineagent.jar ClassVersionAfterRedefine32*/3334import java.io.InputStream;35import java.lang.reflect.Method;3637import static jdk.test.lib.Asserts.assertTrue;3839public class ClassVersionAfterRedefine extends ClassLoader {4041private static String myName = ClassVersionAfterRedefine.class.getName();4243private static byte[] getBytecodes(String name) throws Exception {44InputStream is = ClassVersionAfterRedefine.class.getResourceAsStream(name + ".class");45byte[] buf = is.readAllBytes();46System.out.println("sizeof(" + name + ".class) == " + buf.length);47return buf;48}4950private static int getStringIndex(String needle, byte[] buf) {51return getStringIndex(needle, buf, 0);52}5354private static int getStringIndex(String needle, byte[] buf, int offset) {55outer:56for (int i = offset; i < buf.length - offset - needle.length(); i++) {57for (int j = 0; j < needle.length(); j++) {58if (buf[i + j] != (byte)needle.charAt(j)) continue outer;59}60return i;61}62return 0;63}6465private static void replaceString(byte[] buf, String name, int index) {66for (int i = index; i < index + name.length(); i++) {67buf[i] = (byte)name.charAt(i - index);68}69}7071private static void replaceAllStrings(byte[] buf, String oldString, String newString) throws Exception {72assertTrue(oldString.length() == newString.length(), "must have same length");73int index = -1;74while ((index = getStringIndex(oldString, buf, index + 1)) != 0) {75replaceString(buf, newString, index);76}77}7879public static void main(String[] s) throws Exception {8081byte[] buf = getBytecodes("TestClassOld");82// Poor man's renaming of class "TestClassOld" to "TestClassXXX"83replaceAllStrings(buf, "TestClassOld", "TestClassXXX");84ClassVersionAfterRedefine cvar = new ClassVersionAfterRedefine();85Class<?> old = cvar.defineClass(null, buf, 0, buf.length);86Method foo = old.getMethod("foo");87Object result = foo.invoke(null);88assertTrue("java-lang-String".equals(result));89System.out.println(old.getSimpleName() + ".foo() = " + result);9091buf = getBytecodes("TestClassNew");92// Rename class "TestClassNew" to "TestClassXXX" so we can use it for93// redefining the original version of "TestClassXXX" (i.e. "TestClassOld").94replaceAllStrings(buf, "TestClassNew", "TestClassXXX");95// Now redine the original version of "TestClassXXX" (i.e. "TestClassOld").96RedefineClassHelper.redefineClass(old, buf);97result = foo.invoke(null);98assertTrue("java.lang.String".equals(result));99System.out.println(old.getSimpleName() + ".foo() = " + result);100}101}102103104