changeset 23281:4bbf0e9196f2 jdk8u66-b16

Merge
author asaha
date Mon, 28 Sep 2015 15:01:41 -0700
parents 3d13e757229c (diff) e48e953c86e8 (current diff)
children 97bb3fefe6b9
files .hgtags
diffstat 17 files changed, 462 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Sep 28 14:53:13 2015 -0700
+++ b/.hgtags	Mon Sep 28 15:01:41 2015 -0700
@@ -713,6 +713,7 @@
 e0d75c284bd1c09fd7d9ef09627d8a99b88d468d jdk8u60-b21
 ff8fdeb2fb6d6f3348597339c53412f8f6202c3f hs25.60-b22
 878cb0df27c22c6b1e9f4add1eb3da3edc8ab51d jdk8u60-b22
+ad04e0ef0f85625b68ed18e949c75399b8d9b99b hs25.66-b01
 0e4094950cd312c8f95c7f37336606323fe049fe jdk8u60-b23
 d89ceecf1bad55e1aee2932b8895d60fc64c15db hs25.60-b23
 fb157d537278cda4150740e27bb57cd8694e15bf jdk8u60-b24
@@ -738,3 +739,17 @@
 ccc03258fbcfbcdf515ceb87bd3699c8f849dc0d jdk8u65-b14
 03ca585abe68e4dcce5bc162a0fa0593eb8fa2ee jdk8u65-b15
 b4137dc9b1a83409fbd2b80d2ffd5ae949cd7a6b jdk8u65-b16
+878cb0df27c22c6b1e9f4add1eb3da3edc8ab51d jdk8u66-b00
+777a354cada52b831a32bfc5362ad7cedfde4450 jdk8u66-b01
+0366ad2644f58ec88af9cb2ea8c23a02559fb2d1 hs25.66-b02
+47110b037994f9006c22abcb12569fcafad84edb hs25.66-b03
+ae5624088d86abe8e7981dbb893c1b6da5140a1c jdk8u66-b02
+6594411c4eb4d00e439330a61744f077d0b96363 jdk8u66-b07
+aedefb75358f3cda5181bf594c2cda833056b25a jdk8u66-b08
+83621deea0fcb4a517b94c5546b4f8738588cb6c jdk8u66-b09
+5280a8174aea13bd242480419e6228857dac7b59 jdk8u66-b10
+8a23b6392c590b7bf5f6ad2c4746dc03981a7f60 jdk8u66-b11
+ab64d7ea4f48ea4bdbcc43d4a653be157d9c29e3 jdk8u66-b12
+4d699853544cf869d4edaf23b7cc9cfbb2900a2b jdk8u66-b13
+9f7f29ff487ae023ca1f697445004a532751b0d2 jdk8u66-b14
+5b67af3317bce1f940c5dc1535411a1002bed6c1 jdk8u66-b15
--- a/make/defs.make	Mon Sep 28 14:53:13 2015 -0700
+++ b/make/defs.make	Mon Sep 28 15:01:41 2015 -0700
@@ -116,6 +116,18 @@
 # hotspot version definitions
 include $(GAMMADIR)/make/hotspot_version
 
+# When config parameter --with-update-version is defined,
+# Hotspot minor version should be set to that
+ifneq ($(JDK_UPDATE_VERSION),)
+  HS_MINOR_VER=$(JDK_UPDATE_VERSION)
+endif
+
+# When config parameter --with-build-number is defined,
+# Hotspot build number should be set to that
+ifneq ($(JDK_BUILD_NUMBER),)
+  HS_BUILD_NUMBER=$(subst b,,$(JDK_BUILD_NUMBER))
+endif
+
 # Java versions needed
 ifeq ($(PREVIOUS_JDK_VERSION),)
   PREVIOUS_JDK_VERSION=$(JDK_PREVIOUS_VERSION)
--- a/make/hotspot_version	Mon Sep 28 14:53:13 2015 -0700
+++ b/make/hotspot_version	Mon Sep 28 15:01:41 2015 -0700
@@ -34,8 +34,8 @@
 HOTSPOT_VM_COPYRIGHT=Copyright 2015
 
 HS_MAJOR_VER=25
-HS_MINOR_VER=65
-HS_BUILD_NUMBER=01
+HS_MINOR_VER=66
+HS_BUILD_NUMBER=00
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
--- a/src/os/bsd/vm/jsig.c	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/os/bsd/vm/jsig.c	Mon Sep 28 15:01:41 2015 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, 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
@@ -36,6 +36,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <string.h>
 
 #define MAXSIGNUM 32
 #define MASK(sig) ((unsigned int)1 << sig)
@@ -43,6 +44,9 @@
 static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
 static unsigned int jvmsigs = 0; /* signals used by jvm */
 
+static pthread_key_t reentry_flag_key;
+static pthread_once_t reentry_key_init_once = PTHREAD_ONCE_INIT;
+
 /* used to synchronize the installation of signal handlers */
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
@@ -59,6 +63,15 @@
 static bool jvm_signal_installing = false;
 static bool jvm_signal_installed = false;
 
+#define check_status(cmd) \
+  do { \
+    int status = (cmd); \
+    if (status != 0) { \
+      printf("error %s (%d) in " #cmd "\n", strerror(status), status); \
+      exit(1); \
+    } \
+  } while (0)
+
 static void signal_lock() {
   pthread_mutex_lock(&mutex);
   /* When the jvm is installing its set of signal handlers, threads
@@ -74,8 +87,15 @@
   pthread_mutex_unlock(&mutex);
 }
 
+static void reentry_tls_init() {
+    // value for reentry_flag_key will default to NULL (false)
+    check_status(pthread_key_create(&reentry_flag_key, NULL));
+}
+
 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
                                    bool is_sigset) {
+  sa_handler_t res;
+
   if (os_signal == NULL) {
     if (!is_sigset) {
       os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
@@ -87,7 +107,12 @@
       exit(0);
     }
   }
-  return (*os_signal)(sig, disp);
+  check_status(pthread_once(&reentry_key_init_once, reentry_tls_init));
+  // set reentry_flag_key to non-NULL to show reentry
+  check_status(pthread_setspecific(reentry_flag_key, &res));
+  res = (*os_signal)(sig, disp);
+  check_status(pthread_setspecific(reentry_flag_key, NULL));
+  return res;
 }
 
 static void save_signal_handler(int sig, sa_handler_t disp) {
@@ -161,6 +186,11 @@
   bool sigused;
   struct sigaction oldAct;
 
+  check_status(pthread_once(&reentry_key_init_once, reentry_tls_init));
+  if (pthread_getspecific(reentry_flag_key) != NULL) {
+    return call_os_sigaction(sig, act, oact);
+  }
+
   signal_lock();
 
   sigused = (MASK(sig) & jvmsigs) != 0;
--- a/src/share/vm/classfile/classFileParser.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -4421,9 +4421,15 @@
   Method* m = k->lookup_method(vmSymbols::finalize_method_name(),
                                  vmSymbols::void_method_signature());
   if (m != NULL && !m->is_empty_method()) {
-    f = true;
+      f = true;
   }
-  assert(f == k->has_finalizer(), "inconsistent has_finalizer");
+
+  // Spec doesn't prevent agent from redefinition of empty finalizer.
+  // Despite the fact that it's generally bad idea and redefined finalizer
+  // will not work as expected we shouldn't abort vm in this case
+  if (!k->has_redefined_this_or_super()) {
+    assert(f == k->has_finalizer(), "inconsistent has_finalizer");
+  }
 #endif
 
   // Check if this klass supports the java.lang.Cloneable interface
--- a/src/share/vm/classfile/javaClasses.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -782,6 +782,22 @@
   return name;
 }
 
+// Returns the Java name for this Java mirror (Resource allocated)
+// See Klass::external_name().
+// For primitive type Java mirrors, its type name is returned.
+const char* java_lang_Class::as_external_name(oop java_class) {
+  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
+  const char* name = NULL;
+  if (is_primitive(java_class)) {
+    name = type2name(primitive_type(java_class));
+  } else {
+    name = as_Klass(java_class)->external_name();
+  }
+  if (name == NULL) {
+    name = "<null>";
+  }
+  return name;
+}
 
 Klass* java_lang_Class::array_klass(oop java_class) {
   Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
--- a/src/share/vm/classfile/javaClasses.hpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp	Mon Sep 28 15:01:41 2015 -0700
@@ -270,6 +270,7 @@
   }
   static Symbol* as_signature(oop java_class, bool intern_if_not_found, TRAPS);
   static void print_signature(oop java_class, outputStream *st);
+  static const char* as_external_name(oop java_class);
   // Testing
   static bool is_instance(oop obj) {
     return obj != NULL && obj->klass() == SystemDictionary::Class_klass();
--- a/src/share/vm/oops/instanceKlass.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -439,6 +439,9 @@
     if (!constants()->is_shared()) {
       MetadataFactory::free_metadata(loader_data, constants());
     }
+    // Delete any cached resolution errors for the constant pool
+    SystemDictionary::delete_resolution_error(constants());
+
     set_constants(NULL);
   }
 
@@ -1569,6 +1572,21 @@
   return NULL;
 }
 
+#ifdef ASSERT
+// search through class hierarchy and return true if this class or
+// one of the superclasses was redefined
+bool InstanceKlass::has_redefined_this_or_super() const {
+  const InstanceKlass* klass = this;
+  while (klass != NULL) {
+    if (klass->has_been_redefined()) {
+      return true;
+    }
+    klass = InstanceKlass::cast(klass->super());
+  }
+  return false;
+}
+#endif
+
 // lookup a method in the default methods list then in all transitive interfaces
 // Do NOT return private or static methods
 Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
--- a/src/share/vm/oops/instanceKlass.hpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Mon Sep 28 15:01:41 2015 -0700
@@ -808,6 +808,11 @@
   bool implements_interface(Klass* k) const;
   bool is_same_or_direct_interface(Klass* k) const;
 
+#ifdef ASSERT
+  // check whether this class or one of its superclasses was redefined
+  bool has_redefined_this_or_super() const;
+#endif
+
   // Access to the implementor of an interface.
   Klass* implementor() const
   {
@@ -865,8 +870,8 @@
 
   // Casting from Klass*
   static InstanceKlass* cast(Klass* k) {
-    assert(k->is_klass(), "must be");
-    assert(k->oop_is_instance(), "cast to InstanceKlass");
+    assert(k == NULL || k->is_klass(), "must be");
+    assert(k == NULL || k->oop_is_instance(), "cast to InstanceKlass");
     return (InstanceKlass*) k;
   }
 
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -4071,9 +4071,6 @@
     mnt->adjust_method_entries(the_class(), &trace_name_printed);
   }
 
-  // Fix Resolution Error table also to remove old constant pools
-  SystemDictionary::delete_resolution_error(old_constants);
-
   if (the_class->oop_map_cache() != NULL) {
     // Flush references to any obsolete methods from the oop map cache
     // so that obsolete methods are not pinned.
--- a/src/share/vm/runtime/thread.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/runtime/thread.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -3307,6 +3307,9 @@
 
   extern void JDK_Version_init();
 
+  // Preinitialize version info.
+  VM_Version::early_initialize();
+
   // Check version
   if (!is_supported_jni_version(args->version)) return JNI_EVERSION;
 
--- a/src/share/vm/runtime/vframe.cpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/runtime/vframe.cpp	Mon Sep 28 15:01:41 2015 -0700
@@ -148,8 +148,7 @@
   if (obj.not_null()) {
     st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
     if (obj->klass() == SystemDictionary::Class_klass()) {
-      Klass* target_klass = java_lang_Class::as_Klass(obj());
-      st->print_cr("(a java.lang.Class for %s)", InstanceKlass::cast(target_klass)->external_name());
+      st->print_cr("(a java.lang.Class for %s)", java_lang_Class::as_external_name(obj()));
     } else {
       Klass* k = obj->klass();
       st->print_cr("(a %s)", k->external_name());
--- a/src/share/vm/runtime/vm_version.hpp	Mon Sep 28 14:53:13 2015 -0700
+++ b/src/share/vm/runtime/vm_version.hpp	Mon Sep 28 15:01:41 2015 -0700
@@ -56,6 +56,13 @@
  public:
   static void initialize();
 
+  // This allows for early initialization of VM_Version information
+  // that may be needed later in the initialization sequence but before
+  // full VM_Version initialization is possible. It can not depend on any
+  // other part of the VM being initialized when called. Platforms that
+  // need to specialize this define VM_Version::early_initialize().
+  static void early_initialize() { }
+
   // Name
   static const char* vm_name();
   // Vendor
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/RedefineFinalizer/RedefineFinalizer.java	Mon Sep 28 15:01:41 2015 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test
+ * @bug 6904403
+ * @summary Don't assert if we redefine finalize method
+ * @library /testlibrary
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+public class RedefineFinalizer {
+
+    public static String newB =
+                "class RedefineFinalizer$B {" +
+                "   protected void finalize() { " +
+                "       System.out.println(\"Finalizer called\");" +
+                "   }" +
+                "}";
+
+    public static void main(String[] args) throws Exception {
+        RedefineClassHelper.redefineClass(B.class, newB);
+
+        A a = new A();
+    }
+
+    static class A extends B {
+    }
+
+    static class B {
+        protected void finalize() {
+            // should be empty
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java	Mon Sep 28 15:01:41 2015 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, 2015, 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.
+ */
+
+/*
+ * @test
+ * @bug 8076110
+ * @summary Redefine running methods that have cached resolution errors
+ * @library /testlibrary
+ * @modules java.instrument
+ *          java.base/jdk.internal.org.objectweb.asm
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithResolutionErrors
+ */
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (name.equals("C")) {
+            byte[] b = loadC(false);
+            return defineClass(name, b, 0, b.length);
+        } else {
+            return super.findClass(name);
+        }
+    }
+
+    private static byte[] loadC(boolean redefine) {
+        ClassWriter cw = new ClassWriter(0);
+
+        cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+        {
+            MethodVisitor mv;
+
+            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
+            mv.visitCode();
+
+            // First time we run we will:
+            // 1) Cache resolution errors
+            // 2) Redefine the class / method
+            // 3) Try to read the resolution errors that were cached
+            //
+            // The redefined method will never run, throw error to be sure
+            if (redefine) {
+                createThrowRuntimeExceptionCode(mv, "The redefined method was called");
+            } else {
+                createMethodBody(mv);
+            }
+            mv.visitMaxs(3, 0);
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static void createMethodBody(MethodVisitor mv) {
+        Label classExists = new Label();
+
+        // Cache resolution errors
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Redefine our own class and method
+        mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
+
+        // Provoke the same error again to make sure the resolution error cache works
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Test passed
+        mv.visitInsn(RETURN);
+
+        mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
+        mv.visitLabel(classExists);
+
+        createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
+    }
+
+    private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
+        Label tryLoadBegin = new Label();
+        Label tryLoadEnd = new Label();
+        Label catchLoadBlock = new Label();
+        mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
+
+        // Try to load a class that does not exist to provoke resolution errors
+        mv.visitLabel(tryLoadBegin);
+        mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
+        mv.visitLabel(tryLoadEnd);
+
+        // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
+        mv.visitJumpInsn(GOTO, classExists);
+
+        mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
+        mv.visitLabel(catchLoadBlock);
+
+        // Ignore the expected NoClassDefFoundError
+        mv.visitInsn(POP);
+    }
+
+    private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
+        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+        mv.visitInsn(DUP);
+        mv.visitLdcInsn(msg);
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
+        mv.visitInsn(ATHROW);
+    }
+
+    private static Class<?> c;
+
+    public static void redefine() throws Exception {
+        RedefineClassHelper.redefineClass(c, loadC(true));
+    }
+
+    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
+        c.getMethod("m").invoke(null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary/RedefineClassHelper.java	Mon Sep 28 15:01:41 2015 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+import java.io.PrintWriter;
+import java.lang.instrument.*;
+import com.oracle.java.testlibrary.*;
+
+/*
+ * Helper class to write tests that redefine classes.
+ * When main method is run, it will create a redefineagent.jar that can be used
+ * with the -javaagent option to support redefining classes in jtreg tests.
+ *
+ * See sample test in test/testlibrary_tests/RedefineClassTest.java
+ */
+public class RedefineClassHelper {
+
+    public static Instrumentation instrumentation;
+    public static void premain(String agentArgs, Instrumentation inst) {
+        instrumentation = inst;
+    }
+
+    /**
+     * Redefine a class
+     *
+     * @param clazz Class to redefine
+     * @param javacode String with the new java code for the class to be redefined
+     */
+    public static void redefineClass(Class clazz, String javacode) throws Exception {
+        byte[] bytecode = InMemoryJavaCompiler.compile(clazz.getName(), javacode);
+        redefineClass(clazz, bytecode);
+    }
+
+    /**
+     * Redefine a class
+     *
+     * @param clazz Class to redefine
+     * @param bytecode byte[] with the new class
+     */
+    public static void redefineClass(Class clazz, byte[] bytecode) throws Exception {
+        instrumentation.redefineClasses(new ClassDefinition(clazz, bytecode));
+    }
+
+    /**
+     * Main method to be invoked before test to create the redefineagent.jar
+     */
+    public static void main(String[] args) throws Exception {
+        ClassFileInstaller.main("RedefineClassHelper");
+
+        PrintWriter pw = new PrintWriter("MANIFEST.MF");
+        pw.println("Premain-Class: RedefineClassHelper");
+        pw.println("Can-Redefine-Classes: true");
+        pw.close();
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineClassHelper.class" })) {
+            throw new Exception("jar operation failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testlibrary_tests/RedefineClassTest.java	Mon Sep 28 15:01:41 2015 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+ * @test
+ * @library /testlibrary
+ * @summary Proof of concept test for RedefineClassHelper
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineClassTest
+ */
+
+import static com.oracle.java.testlibrary.Asserts.*;
+import com.oracle.java.testlibrary.*;
+
+/*
+ * Proof of concept test for the test utility class RedefineClassHelper
+ */
+public class RedefineClassTest {
+
+    public static String newClass = "class RedefineClassTest$A { public int Method() { return 2; } }";
+    public static void main(String[] args) throws Exception {
+        A a = new A();
+        assertTrue(a.Method() == 1);
+        RedefineClassHelper.redefineClass(A.class, newClass);
+        assertTrue(a.Method() == 2);
+    }
+
+    static class A {
+        public int Method() {
+            return 1;
+        }
+    }
+}