aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dcevm/src/test/java7/com/github/dcevm/test/fields/InstanceFieldHandleTest.java69
-rw-r--r--dcevm/src/test/java7/com/github/dcevm/test/fields/StaticFieldHandleTest.java64
-rw-r--r--hotspot/.hg/patches/light-jdk8u5-b13.patch167
3 files changed, 197 insertions, 103 deletions
diff --git a/dcevm/src/test/java7/com/github/dcevm/test/fields/InstanceFieldHandleTest.java b/dcevm/src/test/java7/com/github/dcevm/test/fields/InstanceFieldHandleTest.java
index 48f3f46f..4253c3b8 100644
--- a/dcevm/src/test/java7/com/github/dcevm/test/fields/InstanceFieldHandleTest.java
+++ b/dcevm/src/test/java7/com/github/dcevm/test/fields/InstanceFieldHandleTest.java
@@ -24,8 +24,8 @@
package com.github.dcevm.test.fields;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import java.lang.invoke.MethodHandle;
@@ -45,13 +45,21 @@ public class InstanceFieldHandleTest {
public static class A {
public int fieldA;
public int fieldB;
+
+ public int getFieldA() {
+ return -1;
+ }
}
// Version 1 (fields swapped and new one is added)
public static class A___1 {
- public String fieldC;
public int fieldB;
public int fieldA;
+ public String fieldC;
+
+ public int getFieldA() {
+ return fieldA;
+ }
}
// Version 2 (fields removed)
@@ -73,41 +81,72 @@ public class InstanceFieldHandleTest {
@Test
public void testFieldChangeOrder() throws Throwable {
A a = new A();
- MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class);
a.fieldA = 3;
- assertEquals(3, handle.invoke(a));
+ assertEquals(3, getter.invoke(a));
// Swap fields
__toVersion__(1);
- assertEquals(3, handle.invoke(a));
+
+ assertEquals(3, getter.invoke(a));
+ setter.invoke(a, 53);
+ assertEquals(53, a.getFieldA());
+ assertEquals(53, getter.invoke(a));
}
@Test
- @Ignore
- public void testStaticFieldRemoved() throws Throwable {
- MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ public void testFieldRemoved() throws Throwable {
A a = new A();
+ MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class);
+
a.fieldA = 3;
- assertEquals(3, handle.invoke(a));
+ assertEquals(3, getter.invoke(a));
// Remove fieldA
__toVersion__(2);
- handle.invoke(a);
+ try {
+ getter.invoke(a);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
+
+ try {
+ setter.invoke(a, 10);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
}
@Test
- @Ignore
- public void testStaticFieldTypeChange() throws Throwable {
- MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ public void testFieldTypeChange() throws Throwable {
A a = new A();
+ MethodHandle getter = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findSetter(A.class, "fieldA", int.class);
+
a.fieldA = 3;
- assertEquals(3, handle.invoke(a));
+ assertEquals(3, getter.invoke(a));
// Remove fieldA
__toVersion__(3);
- handle.invoke(a);
+ try {
+ getter.invoke(a);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
+
+ try {
+ setter.invoke(a, 10);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
}
} \ No newline at end of file
diff --git a/dcevm/src/test/java7/com/github/dcevm/test/fields/StaticFieldHandleTest.java b/dcevm/src/test/java7/com/github/dcevm/test/fields/StaticFieldHandleTest.java
index 6f565252..237cff25 100644
--- a/dcevm/src/test/java7/com/github/dcevm/test/fields/StaticFieldHandleTest.java
+++ b/dcevm/src/test/java7/com/github/dcevm/test/fields/StaticFieldHandleTest.java
@@ -23,19 +23,15 @@
*/
package com.github.dcevm.test.fields;
-import com.github.dcevm.test.TestUtil;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
import static com.github.dcevm.test.util.HotSwapTestHelper.__toVersion__;
-import static com.github.dcevm.test.util.HotSwapTestHelper.__version__;
import static org.junit.Assert.assertEquals;
/**
@@ -49,12 +45,21 @@ public class StaticFieldHandleTest {
public static class A {
public static int fieldA;
public static int fieldB;
+
+ public static int getFieldA() {
+ return -1;
+ }
}
// Version 1 (fields swapped)
public static class A___1 {
public static int fieldB;
public static int fieldA;
+ public static String fieldC;
+
+ public static int getFieldA() {
+ return fieldA;
+ }
}
// Version 2 (fields removed)
@@ -75,44 +80,73 @@ public class StaticFieldHandleTest {
@Test
public void testStaticFieldChangeOrder() throws Throwable {
- MethodHandle handle = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class);
A.fieldA = 3;
A.fieldB = 5;
- assertEquals(3, handle.invoke());
+ assertEquals(3, getter.invoke());
// Swap fields A and B
__toVersion__(1);
- assertEquals(3, handle.invoke());
+
+ assertEquals(3, getter.invoke());
+ setter.invoke(12);
+ assertEquals(12, A.getFieldA());
+ assertEquals(12, getter.invoke());
}
@Test
- @Ignore
public void testStaticFieldRemoved() throws Throwable {
- MethodHandle handle = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class);
A.fieldA = 3;
A.fieldB = 5;
- assertEquals(3, handle.invoke());
+ assertEquals(3, getter.invoke());
// Remove fieldA
__toVersion__(2);
- handle.invoke();
+ try {
+ getter.invoke();
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
+
+ try {
+ setter.invoke(15);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
}
@Test
- @Ignore
public void testStaticFieldTypeChange() throws Throwable {
- MethodHandle handle = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle getter = MethodHandles.publicLookup().findStaticGetter(A.class, "fieldA", int.class);
+ MethodHandle setter = MethodHandles.publicLookup().findStaticSetter(A.class, "fieldA", int.class);
A.fieldA = 3;
A.fieldB = 5;
- assertEquals(3, handle.invoke());
+ assertEquals(3, getter.invoke());
// Remove fieldA
__toVersion__(3);
- handle.invoke();
+ try {
+ getter.invoke();
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
+
+ try {
+ setter.invoke(15);
+ Assert.fail("Handle should have been cleared!");
+ } catch (NullPointerException e) {
+ // Handle was cleared!
+ }
}
} \ No newline at end of file
diff --git a/hotspot/.hg/patches/light-jdk8u5-b13.patch b/hotspot/.hg/patches/light-jdk8u5-b13.patch
index 4458820c..b7a0df54 100644
--- a/hotspot/.hg/patches/light-jdk8u5-b13.patch
+++ b/hotspot/.hg/patches/light-jdk8u5-b13.patch
@@ -1564,7 +1564,7 @@ diff --git a/src/share/vm/prims/jvmtiRedefineClasses2.cpp b/src/share/vm/prims/j
new file mode 100644
--- /dev/null
+++ b/src/share/vm/prims/jvmtiRedefineClasses2.cpp
-@@ -0,0 +1,2107 @@
+@@ -0,0 +1,2122 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -2631,6 +2631,88 @@ new file mode 100644
+
+template <class S>
+class ChangePointersOopClosure : public ExtendedOopClosure {
++ // import java_lang_invoke_MemberName.*
++ enum {
++ REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT,
++ REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
++ };
++
++
++ bool update_member_name(oop obj) {
++ int flags = java_lang_invoke_MemberName::flags(obj);
++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
++ if (MethodHandles::ref_kind_is_method(ref_kind)) {
++ Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj);
++ if (m != NULL && !m->method_holder()->is_newest_version()) {
++ // Let's try to re-resolve method
++ InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version());
++ Method* new_method = newest->find_method(m->name(), m->signature());
++
++ // Note: we might set NULL at this point, which should force AbstractMethodError at runtime
++ java_lang_invoke_MemberName::set_vmtarget(obj, new_method);
++ }
++ } else if (MethodHandles::ref_kind_is_field(ref_kind)) {
++ Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj);
++ if (k == NULL) {
++ return false; // Was cleared before, this MemberName is invalid.
++ }
++
++ if (k != NULL && !k->is_newest_version()) {
++ // Let's try to re-resolve field
++ fieldDescriptor fd;
++ int offset = java_lang_invoke_MemberName::vmindex(obj);
++ bool is_static = MethodHandles::ref_kind_is_static(ref_kind);
++ InstanceKlass* ik = InstanceKlass::cast(k);
++ if (ik->find_local_field_from_offset(offset, is_static, &fd)) {
++ InstanceKlass* newest = InstanceKlass::cast(k->newest_version());
++ fieldDescriptor fd_new;
++ if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) {
++ java_lang_invoke_MemberName::set_vmtarget(obj, newest);
++ java_lang_invoke_MemberName::set_vmindex(obj, fd_new.offset());
++ } else {
++ // Matching field is not found in new version, not much we can do here.
++ // JVM will crash once faulty MH is invoked.
++ // However, to avoid that all DMH's using this faulty MH are cleared (set to NULL)
++ // Eventually, we probably want to replace them with something more meaningful,
++ // like instance throwing NoSuchFieldError or DMH that will resort to dynamic
++ // field resolution (with possibility of type conversion)
++ java_lang_invoke_MemberName::set_vmtarget(obj, NULL);
++ java_lang_invoke_MemberName::set_vmindex(obj, 0);
++ return false;
++ }
++ }
++ }
++ }
++ return true;
++ }
++
++ bool update_direct_method_handle(oop obj) {
++ // Always update member name first.
++ oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj);
++ if (!update_member_name(mem_name)) {
++ return false;
++ }
++
++ // Here we rely on DirectMethodHandle implementation.
++ // The current implementation caches field offset in $StaticAccessor/$Accessor
++ int flags = java_lang_invoke_MemberName::flags(mem_name);
++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
++ if (MethodHandles::ref_kind_is_field(ref_kind)) {
++ // Note: we don't care about staticBase field (which is java.lang.Class)
++ // It should be processed during normal object update.
++ // Update offset in StaticAccessor
++ int offset = java_lang_invoke_MemberName::vmindex(mem_name);
++ if (offset != 0) { // index of 0 means that field no longer exist
++ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) {
++ java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(obj, offset);
++ } else if (java_lang_invoke_DirectMethodHandle_Accessor::is_instance(obj)) {
++ java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(obj, offset);
++ }
++ }
++ }
++ return true;
++ }
++
+ // Forward pointers to InstanceKlass and mirror class to new versions
+ template <class T>
+ inline void do_oop_work(T* p) {
@@ -2648,6 +2730,17 @@ new file mode 100644
+ }
+ }
+ }
++
++ // JSR 292 support, uptade java.lang.invoke.MemberName instances
++ if (java_lang_invoke_MemberName::is_instance(obj)) {
++ update_member_name(obj);
++ } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) {
++ if (!update_direct_method_handle(obj)) {
++ // DMH is no longer valid, replace it with null reference.
++ // See note above. We probably want to replace this with something more meaningful.
++ S::oop_store(p, NULL);
++ }
++ }
+ }
+
+ virtual void do_oop(oop* o) {
@@ -2697,12 +2790,6 @@ new file mode 100644
+ class ChangePointersObjectClosure : public ObjectClosure {
+ private:
+
-+ // import java_lang_invoke_MemberName.*
-+ enum {
-+ REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT,
-+ REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK,
-+ };
-+
+ OopClosure *_closure;
+ bool _needs_instance_update;
+ oop _tmp_obj;
@@ -2724,73 +2811,7 @@ new file mode 100644
+ Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)_tmp_obj, size);
+ }
+
-+ void update_member_name(oop obj) {
-+ int flags = java_lang_invoke_MemberName::flags(obj);
-+ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
-+ if (MethodHandles::ref_kind_is_method(ref_kind)) {
-+ Method* m = (Method*) java_lang_invoke_MemberName::vmtarget(obj);
-+ if (m != NULL && !m->method_holder()->is_newest_version()) {
-+ // Let's try to re-resolve method
-+ InstanceKlass* newest = InstanceKlass::cast(m->method_holder()->newest_version());
-+ Method* new_method = newest->find_method(m->name(), m->signature());
-+
-+ // Note: we might set NULL at this point, which should force AbstractMethodError at runtime
-+ java_lang_invoke_MemberName::set_vmtarget(obj, new_method);
-+ }
-+ } else if (MethodHandles::ref_kind_is_field(ref_kind)) {
-+ Klass* k = (Klass*) java_lang_invoke_MemberName::vmtarget(obj);
-+ if (k != NULL && !k->is_newest_version()) {
-+ // Let's try to re-resolve field
-+ fieldDescriptor fd;
-+ int offset = java_lang_invoke_MemberName::vmindex(obj);
-+ bool is_static = MethodHandles::ref_kind_is_static(ref_kind);
-+ InstanceKlass* ik = InstanceKlass::cast(k);
-+ if (ik->find_local_field_from_offset(offset, is_static, &fd)) {
-+ InstanceKlass* newest = InstanceKlass::cast(k->newest_version());
-+ fieldDescriptor fd_new;
-+ if (newest->find_local_field(fd.name(), fd.signature(), &fd_new)) {
-+ java_lang_invoke_MemberName::set_vmtarget(obj, newest);
-+ java_lang_invoke_MemberName::set_vmindex(obj, fd_new.offset());
-+ } else {
-+ // Well, not much we can do here. JVM will crash once faulty MH is invoked.
-+ }
-+ }
-+ }
-+ }
-+ }
-+
-+ void update_direct_method_handle(oop obj) {
-+ // Always update member name first.
-+ oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj);
-+ update_member_name(mem_name);
-+
-+ // Here we rely on DirectMethodHandle implementation.
-+ // The current implementation caches field offset in $StaticAccessor/$Accessor
-+ int flags = java_lang_invoke_MemberName::flags(mem_name);
-+ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
-+ if (MethodHandles::ref_kind_is_field(ref_kind)) {
-+ // Note: we don't care about staticBase field (which is java.lang.Class)
-+ // It should be processed during normal object update.
-+ // Update offset in StaticAccessor
-+ int offset = java_lang_invoke_MemberName::vmindex(mem_name);
-+ if (offset != 0) { // index of 0 means that field no longer exist
-+ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) {
-+ java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(obj, offset);
-+ } else if (java_lang_invoke_DirectMethodHandle_Accessor::is_instance(obj)) {
-+ java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(obj, offset);
-+ }
-+ }
-+ }
-+ }
-+
+ virtual void do_object(oop obj) {
-+ // JSR 292 support, uptade java.lang.invoke.MemberName instances
-+ if (java_lang_invoke_MemberName::is_instance(obj)) {
-+ update_member_name(obj);
-+ } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) {
-+ update_direct_method_handle(obj);
-+ }
-+
+ // FIXME: if (obj->is_instanceKlass()) return;
+ if (obj->is_instanceMirror()) {
+ // static fields may have references to old java.lang.Class instances, update them