mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-17 11:23:19 +00:00
8267555: Fix class file version during redefinition after 8238048
Reviewed-by: coleenp, sspitsyn
This commit is contained in:
parent
97ec5ad0a6
commit
1d2c7ac3f7
@ -73,7 +73,6 @@ void ConstantPool::copy_fields(const ConstantPool* orig) {
|
||||
set_has_dynamic_constant();
|
||||
}
|
||||
|
||||
// Copy class version
|
||||
set_major_version(orig->major_version());
|
||||
set_minor_version(orig->minor_version());
|
||||
|
||||
|
||||
@ -1852,9 +1852,12 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
|
||||
return JVMTI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
// Save fields from the old_cp.
|
||||
merge_cp->copy_fields(old_cp());
|
||||
scratch_cp->copy_fields(old_cp());
|
||||
// Set dynamic constants attribute from the original CP.
|
||||
if (old_cp->has_dynamic_constant()) {
|
||||
scratch_cp->set_has_dynamic_constant();
|
||||
}
|
||||
// Copy attributes from scratch_cp to merge_cp
|
||||
merge_cp->copy_fields(scratch_cp());
|
||||
|
||||
log_info(redefine, class, constantpool)("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count);
|
||||
|
||||
@ -4396,6 +4399,16 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
|
||||
|
||||
swap_annotations(the_class, scratch_class);
|
||||
|
||||
// Replace minor version number of class file
|
||||
u2 old_minor_version = the_class->constants()->minor_version();
|
||||
the_class->constants()->set_minor_version(scratch_class->constants()->minor_version());
|
||||
scratch_class->constants()->set_minor_version(old_minor_version);
|
||||
|
||||
// Replace major version number of class file
|
||||
u2 old_major_version = the_class->constants()->major_version();
|
||||
the_class->constants()->set_major_version(scratch_class->constants()->major_version());
|
||||
scratch_class->constants()->set_major_version(old_major_version);
|
||||
|
||||
// Replace CP indexes for class and name+type of enclosing method
|
||||
u2 old_class_idx = the_class->enclosing_method_class_index();
|
||||
u2 old_method_idx = the_class->enclosing_method_method_index();
|
||||
|
||||
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. 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 8267555
|
||||
* @requires vm.jvmti
|
||||
* @summary Class redefinition with a different class file version
|
||||
* @library /test/lib
|
||||
* @compile TestClassOld.jasm TestClassNew.jasm
|
||||
* @run main RedefineClassHelper
|
||||
* @run main/othervm -javaagent:redefineagent.jar ClassVersionAfterRedefine
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static jdk.test.lib.Asserts.assertTrue;
|
||||
|
||||
public class ClassVersionAfterRedefine extends ClassLoader {
|
||||
|
||||
private static String myName = ClassVersionAfterRedefine.class.getName();
|
||||
|
||||
private static byte[] getBytecodes(String name) throws Exception {
|
||||
InputStream is = ClassVersionAfterRedefine.class.getResourceAsStream(name + ".class");
|
||||
byte[] buf = is.readAllBytes();
|
||||
System.out.println("sizeof(" + name + ".class) == " + buf.length);
|
||||
return buf;
|
||||
}
|
||||
|
||||
private static int getStringIndex(String needle, byte[] buf) {
|
||||
return getStringIndex(needle, buf, 0);
|
||||
}
|
||||
|
||||
private static int getStringIndex(String needle, byte[] buf, int offset) {
|
||||
outer:
|
||||
for (int i = offset; i < buf.length - offset - needle.length(); i++) {
|
||||
for (int j = 0; j < needle.length(); j++) {
|
||||
if (buf[i + j] != (byte)needle.charAt(j)) continue outer;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void replaceString(byte[] buf, String name, int index) {
|
||||
for (int i = index; i < index + name.length(); i++) {
|
||||
buf[i] = (byte)name.charAt(i - index);
|
||||
}
|
||||
}
|
||||
|
||||
private static void replaceAllStrings(byte[] buf, String oldString, String newString) throws Exception {
|
||||
assertTrue(oldString.length() == newString.length(), "must have same length");
|
||||
int index = -1;
|
||||
while ((index = getStringIndex(oldString, buf, index + 1)) != 0) {
|
||||
replaceString(buf, newString, index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] s) throws Exception {
|
||||
|
||||
byte[] buf = getBytecodes("TestClassOld");
|
||||
// Poor man's renaming of class "TestClassOld" to "TestClassXXX"
|
||||
replaceAllStrings(buf, "TestClassOld", "TestClassXXX");
|
||||
ClassVersionAfterRedefine cvar = new ClassVersionAfterRedefine();
|
||||
Class<?> old = cvar.defineClass(null, buf, 0, buf.length);
|
||||
Method foo = old.getMethod("foo");
|
||||
Object result = foo.invoke(null);
|
||||
assertTrue("java-lang-String".equals(result));
|
||||
System.out.println(old.getSimpleName() + ".foo() = " + result);
|
||||
|
||||
buf = getBytecodes("TestClassNew");
|
||||
// Rename class "TestClassNew" to "TestClassXXX" so we can use it for
|
||||
// redefining the original version of "TestClassXXX" (i.e. "TestClassOld").
|
||||
replaceAllStrings(buf, "TestClassNew", "TestClassXXX");
|
||||
// Now redine the original version of "TestClassXXX" (i.e. "TestClassOld").
|
||||
RedefineClassHelper.redefineClass(old, buf);
|
||||
result = foo.invoke(null);
|
||||
assertTrue("java.lang.String".equals(result));
|
||||
System.out.println(old.getSimpleName() + ".foo() = " + result);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. 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.
|
||||
*/
|
||||
|
||||
super public final class TestClassNew version 49:0 {
|
||||
|
||||
public Method "<init>":"()V" stack 1 locals 1 {
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
public static Method foo:"()Ljava/lang/String;" stack 1 locals 1 {
|
||||
ldc class java/lang/String;
|
||||
invokevirtual Method java/lang/Class.getName:"()Ljava/lang/String;";
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 {
|
||||
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
||||
invokestatic Method TestClassNew.foo:"()Ljava/lang/String;";
|
||||
invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright Amazon.com Inc. 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.
|
||||
*/
|
||||
|
||||
super public final class TestClassOld version 48:0 {
|
||||
|
||||
public Method "<init>":"()V" stack 1 locals 1 {
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
public static Method foo:"()Ljava/lang/String;" stack 1 locals 1 {
|
||||
ldc String "java-lang-String";
|
||||
areturn;
|
||||
}
|
||||
|
||||
public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 {
|
||||
getstatic Field java/lang/System.out:"Ljava/io/PrintStream;";
|
||||
invokestatic Method TestClassOld.foo:"()Ljava/lang/String;";
|
||||
invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/String;)V";
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user