diff options
6 files changed, 251 insertions, 2 deletions
@@ -8,6 +8,15 @@ The purpose of the project is to maintain enhanced class redefinition functional You can download binaries [here](https://dcevm.github.io/). +## Dcevm for Java9 and Java10 + +Dcevm8 is last version supported by this project. New versions are moved to separated projects extended from OpenJDK under HotswapProjects umbrella. + +* [Dcevm9](https://github.com/HotswapProjects/openjdk-jdk9) +* [Dcevm10](https://github.com/HotswapProjects/openjdk-jdk10) + +Dcevm patch is hosted in dedicated **dcevm** branch in each repository. + ## Supported versions [hotspot/.hg/patches/](hotspot/.hg/patches/) contains patches for all supported versions. Each patch is named by concatenating prefix `full` or `light` with the OpenJDK HotSpot tag. `full` patches support full redefenition capabilities (including removal of superclasses, for example). `light` patches are easier to maintain, but they only support limited functionality (generally, additions to class hierarchies are fine, removals are not). diff --git a/dcevm/src/test/java7/com/github/dcevm/test/TestUtil.java b/dcevm/src/test/java7/com/github/dcevm/test/TestUtil.java index 7208af20..41d9b0bc 100644 --- a/dcevm/src/test/java7/com/github/dcevm/test/TestUtil.java +++ b/dcevm/src/test/java7/com/github/dcevm/test/TestUtil.java @@ -26,6 +26,7 @@ package com.github.dcevm.test; import com.github.dcevm.HotSwapTool; import org.junit.Assert; +import java.lang.reflect.Field; /** * Utility methods for unit testing. @@ -71,4 +72,17 @@ public class TestUtil { }); } + public static int getClassRedefinedCount(Class type) { + try { + Field field = Class.class.getDeclaredField("classRedefinedCount"); + boolean accessibility = field.isAccessible(); + field.setAccessible(true); + int classRedefinedCount = (Integer) field.get(type); + field.setAccessible(accessibility); + return classRedefinedCount; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } diff --git a/dcevm/src/test/java7/com/github/dcevm/test/fields/FieldOperationsUpdateClassRedefinedCount.java b/dcevm/src/test/java7/com/github/dcevm/test/fields/FieldOperationsUpdateClassRedefinedCount.java new file mode 100644 index 00000000..ff7ddaa1 --- /dev/null +++ b/dcevm/src/test/java7/com/github/dcevm/test/fields/FieldOperationsUpdateClassRedefinedCount.java @@ -0,0 +1,86 @@ +package com.github.dcevm.test.fields; + +import com.github.dcevm.HotSwapTool; +import com.github.dcevm.test.TestUtil; +import com.github.dcevm.test.category.Light; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import static com.github.dcevm.test.util.HotSwapTestHelper.__toVersion__; +import static org.junit.Assert.assertEquals; + + +@Category(Light.class) +public class FieldOperationsUpdateClassRedefinedCount { + + // Version 0 + public static class A { + + public int x; + + int getFieldInOldCode() { + + __toVersion__(1); + + // This field does no longer exist + return x; + } + int getVer() { + return 0; + } + } + + // Version 1 + public static class A___1 { + public int x; + public int y; + int getVer() { + return 1; + } + } + + public static class A___2 { + int getVer() { + return 2; + } + } + + @Before + public void setUp() throws Exception { + __toVersion__(0); + } + + @Test + public void addingFieldUpdatesClassRedifinedCount() throws NoSuchFieldException, IllegalAccessException { + // setup + A a = new A(); + __toVersion__(0); + int prevVersion = TestUtil.getClassRedefinedCount(A.class); + // examine + __toVersion__(1); + + Object y = A.class.getDeclaredField("y").get(a); + // verify + assertEquals(0,y); + assertEquals(1, a.getVer()); + assertEquals(prevVersion+1, TestUtil.getClassRedefinedCount(A.class)); + } + + @Test + public void deletingFieldUpdatesClassRedifinedCount() { + // setup + A a= new A(); + __toVersion__(0); + int prevVersion = TestUtil.getClassRedefinedCount(A.class); + // examine + __toVersion__(2); + + // verify + assertEquals(2, a.getVer()); + assertEquals(prevVersion+1, TestUtil.getClassRedefinedCount(A.class)); + } + + + +} diff --git a/dcevm/src/test/java7/com/github/dcevm/test/methods/OperationsOnMethodsUpdateClassRedefinedCount.java b/dcevm/src/test/java7/com/github/dcevm/test/methods/OperationsOnMethodsUpdateClassRedefinedCount.java new file mode 100644 index 00000000..96522914 --- /dev/null +++ b/dcevm/src/test/java7/com/github/dcevm/test/methods/OperationsOnMethodsUpdateClassRedefinedCount.java @@ -0,0 +1,111 @@ +package com.github.dcevm.test.methods; + +import com.github.dcevm.test.TestUtil; +import org.junit.Before; +import org.junit.Test; + +import static com.github.dcevm.test.util.HotSwapTestHelper.__toVersion__; +import static org.junit.Assert.assertEquals; + +public class OperationsOnMethodsUpdateClassRedefinedCount { + // Version 0 + public static class A { + public int value(int newVersion) { + return newVersion; + } + } + + // Version 1 + public static class A___1 { + + public int value(int newVersion) { + + int x = 1; + try { + x = 2; + } catch (NumberFormatException e) { + x = 3; + } catch (Exception e) { + x = 4; + } finally { + x = x * 2; + } + __toVersion__(newVersion); + throw new IllegalArgumentException(); + } + } + + // Version 2 + public static class A___2 { + + public int value2() { + return 2; + } + + public int value(int newVersion) { + + int x = 1; + try { + x = 2; + } catch (NumberFormatException e) { + x = 3; + } catch (Exception e) { + x = 4; + } finally { + x = x * 2; + } + __toVersion__(newVersion); + throw new IllegalArgumentException(); + } + + public int value3() { + return 3; + } + + public int value4() { + return 4; + } + + public int value5() { + return 5; + } + } + + @Before + public void setUp() throws Exception { + __toVersion__(0); + } + + @Test + public void changingMethodUpdatesClassRedefinedCount() { + // setup + __toVersion__(0); + int prevVersion = TestUtil.getClassRedefinedCount(A.class); + // examine + __toVersion__(1); + // verify + assertEquals(prevVersion+1, TestUtil.getClassRedefinedCount(A.class)); + } + + @Test + public void addingMethodUpdatesClassRedefinedCount() { + // setup + __toVersion__(0); + int prevVersion = TestUtil.getClassRedefinedCount(A.class); + // examine + __toVersion__(2); + // verify + assertEquals(prevVersion+1, TestUtil.getClassRedefinedCount(A.class)); + } + + @Test + public void deletingMethodUpdatesClassRedefinedCount() { + // setup + __toVersion__(2); + int prevVersion = TestUtil.getClassRedefinedCount(A.class); + // examine + __toVersion__(0); + // verify + assertEquals(prevVersion+1, TestUtil.getClassRedefinedCount(A.class)); + } +} diff --git a/hotspot/.hg/patches/light-updateClassRedefinedCount-java8.patch b/hotspot/.hg/patches/light-updateClassRedefinedCount-java8.patch new file mode 100644 index 00000000..31ca8952 --- /dev/null +++ b/hotspot/.hg/patches/light-updateClassRedefinedCount-java8.patch @@ -0,0 +1,28 @@ +diff -r 7bb5278e8ce7 src/share/vm/prims/jvmtiRedefineClasses2.cpp +--- a/src/share/vm/prims/jvmtiRedefineClasses2.cpp Fri Mar 23 15:32:54 2018 +0100 ++++ b/src/share/vm/prims/jvmtiRedefineClasses2.cpp Sat Mar 24 15:49:52 2018 +0100 +@@ -1763,8 +1763,8 @@ + + // increment the classRedefinedCount field in the_class and in any + // direct and indirect subclasses of the_class +- increment_class_counter((InstanceKlass *)the_old_class(), THREAD); +- ++ increment_class_counter((InstanceKlass *)the_new_class(), THREAD); ++ + } + + +@@ -1864,10 +1864,10 @@ + + // Increment the classRedefinedCount field in the specific InstanceKlass + // and in all direct and indirect subclasses. +-void VM_EnhancedRedefineClasses::increment_class_counter(Klass* klass, TRAPS) { +- oop class_mirror = klass->java_mirror(); ++void VM_EnhancedRedefineClasses::increment_class_counter(Klass* klass, TRAPS) { ++ oop class_mirror = klass->old_version()->java_mirror(); + int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1; +- java_lang_Class::set_classRedefinedCount(class_mirror, new_count); ++ java_lang_Class::set_classRedefinedCount(klass->java_mirror(), new_count); + RC_TRACE(0x00000008, ("updated count for class=%s to %d", klass->external_name(), new_count)); + } + diff --git a/hotspot/.hg/patches/series b/hotspot/.hg/patches/series index ef3bea27..6d6d06eb 100644 --- a/hotspot/.hg/patches/series +++ b/hotspot/.hg/patches/series @@ -54,5 +54,6 @@ light-jdk8u152-b16.patch #+light-jdk8u152-b16 #+light-jdk8u161-b12 #+light-jdk8u jvmti-getLoadedClasses-java8.patch #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 #+light-jdk8u161-b12 #+light-jdk8u162-b12 jvmti-lockRedefine-java8.patch #+light-jdk8u144-b01delete light-jdk8u20-deopt-cp.patch #+light-jdk8u20-b22 #+light-jdk8u31-b13 #+light-jdk8u40-b25 #+light-jdk8u45-b14 #+light-jdk8u51-b16 -light-jdk8u66-b17-deopt-cp.patch #+light-jdk8u66-b17 #+light-jdk8u74-b02 #+light-jdk8u92-b14 #+light-jdk8u102-b31 #+light-jdk8u111-b14 #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 #+light-jdk8u161-b12 #+light-jdk8u162-b12 -dont-clear-f1.patch #+light-jdk8u74-b02 #+light-jdk8u92-b14 #+light-jdk8u102-b31 #+light-jdk8u111-b14 #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 #+light-jdk8u161-b12 #+light-jdk8u162-b12 +light-jdk8u66-b17-deopt-cp.patch #+light-jdk8u66-b17 #+light-jdk8u74-b02 #+light-jdk8u92-b14 #+light-jdk8u102-b31 #+light-jdk8u111-b14 #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 +dont-clear-f1.patch #+light-jdk8u74-b02 #+light-jdk8u92-b14 #+light-jdk8u102-b31 #+light-jdk8u111-b14 #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 +light-updateClassRedefinedCount-java8.patch #+light-jdk8u112-b16 #+light-jdk8u144-b01 #+light-jdk8u152-b16 |