--- /dev/null
+/*
+ * Copyright (c) 2010, 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.
+ *
+ */
+package com.github.dcevm.test.fields;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import static com.github.dcevm.test.util.HotSwapTestHelper.__toVersion__;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for replacing field with MethodHandle pointing to it.
+ *
+ * @author Ivan Dubrov
+ */
+public class InstanceFieldHandleTest {
+
+ // Version 0
+ public static class A {
+ public int fieldA;
+ public int fieldB;
+ }
+
+ // Version 1 (fields swapped and new one is added)
+ public static class A___1 {
+ public String fieldC;
+ public int fieldB;
+ public int fieldA;
+ }
+
+ // Version 2 (fields removed)
+ public static class A___2 {
+ }
+
+ // Version 3 (field type changed)
+ public static class A___3 {
+ public String fieldA;
+ public int fieldB;
+ }
+
+ @Before
+ @After
+ public void setUp() throws Exception {
+ __toVersion__(0);
+ }
+
+ @Test
+ public void testFieldChangeOrder() throws Throwable {
+ A a = new A();
+ MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+
+ a.fieldA = 3;
+ assertEquals(3, handle.invoke(a));
+
+ // Swap fields
+ __toVersion__(1);
+ assertEquals(3, handle.invoke(a));
+ }
+
+ @Test
+ @Ignore
+ public void testStaticFieldRemoved() throws Throwable {
+ MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ A a = new A();
+ a.fieldA = 3;
+ assertEquals(3, handle.invoke(a));
+
+ // Remove fieldA
+ __toVersion__(2);
+
+ handle.invoke(a);
+ }
+
+ @Test
+ @Ignore
+ public void testStaticFieldTypeChange() throws Throwable {
+ MethodHandle handle = MethodHandles.publicLookup().findGetter(A.class, "fieldA", int.class);
+ A a = new A();
+ a.fieldA = 3;
+ assertEquals(3, handle.invoke(a));
+
+ // Remove fieldA
+ __toVersion__(3);
+
+ handle.invoke(a);
+ }
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/src/share/vm/prims/jvmtiRedefineClasses2.cpp
-@@ -0,0 +1,2100 @@
+@@ -0,0 +1,2101 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ 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)) {
-+ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) {
-+ InstanceKlass* ik = InstanceKlass::cast(obj->klass());
-+ if (java_lang_invoke_MemberName::vmindex(mem_name) != 0) {
-+ // 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);
++ // 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);
+ }
+ }
+ }