--- old/make/data/jdwp/jdwp.spec 2018-05-18 03:44:00.136581721 -0400 +++ new/make/data/jdwp/jdwp.spec 2018-05-18 03:43:58.516487947 -0400 @@ -396,7 +396,7 @@ "classes?") (boolean canUnrestrictedlyRedefineClasses "Can the VM redefine classes" - "in arbitrary ways?") + "in ways that are normally restricted?") (boolean canPopFrames "Can the VM pop stack frames?") (boolean canUseInstanceFilters @@ -460,12 +460,23 @@ "PopFrames command can be used " "to pop frames with obsolete methods." "

" + "Unless the canUnrestrictedlyRedefineClasses capability is present the following " + "redefinitions are restricted: " + "

" + "

" "Requires canRedefineClasses capability - see " "CapabilitiesNew. " "In addition to the canRedefineClasses capability, the target VM must " "have the canAddMethod capability to add methods when redefining classes, " - "or the canUnrestrictedlyRedefineClasses to redefine classes in arbitrary " - "ways." + "or the canUnrestrictedlyRedefineClasses capability to redefine classes in ways " + "that are normally restricted." (Out (Repeat classes "Number of reference types that follow." (Group ClassDef @@ -496,6 +507,7 @@ (Error DELETE_METHOD_NOT_IMPLEMENTED) (Error CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED) (Error METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED) + (Error CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED) (Error VM_DEAD) ) ) @@ -3149,12 +3161,16 @@ "different from the name in the old class object.") (Constant CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED =70 "The new class version has different modifiers and " - "and canUnrestrictedlyRedefineClasses is false.") + "canUnrestrictedlyRedefineClasses is false.") (Constant METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED =71 "A method in the new class version has " "different modifiers " "than its counterpart in the old class version and " - "and canUnrestrictedlyRedefineClasses is false.") + "canUnrestrictedlyRedefineClasses is false.") + (Constant CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED + =72 "The new class version has different NestHost or " + "NestMembers class attribute and " + "canUnrestrictedlyRedefineClasses is false.") (Constant NOT_IMPLEMENTED =99 "The functionality is not implemented in " "this virtual machine.") (Constant NULL_POINTER =100 "Invalid pointer.") --- old/src/hotspot/share/prims/jvmti.xml 2018-05-18 03:44:04.864855403 -0400 +++ new/src/hotspot/share/prims/jvmti.xml 2018-05-18 03:44:03.328766490 -0400 @@ -358,7 +358,7 @@ ]> @@ -7631,9 +7631,12 @@ <eventlink id="ClassFileLoadHook"/> event will be sent. <p/> - The retransformation may change method bodies, the constant pool and attributes. + The retransformation may change method bodies, the constant pool and attributes + (unless explicitly prohibited). The retransformation must not add, remove or rename fields or methods, change the signatures of methods, change modifiers, or change inheritance. + The retransformation must not change the <code>NestHost</code> or + <code>NestMembers</code> attributes. These restrictions may be lifted in future versions. See the error return description below for information on error codes returned if an unsupported retransformation is attempted. @@ -7704,6 +7707,9 @@ A retransformed class file does not declare a method declared in the old class version. </error> + <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED"> + A retransformed class file has unsupported differences in class attributes. + </error> <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED"> A retransformed class file has different class modifiers. </error> @@ -7778,9 +7784,12 @@ <eventlink id="ClassFileLoadHook">Class File Load Hook</eventlink> will be sent (if enabled), but no other <jvmti/> events will be sent. <p/> - The redefinition may change method bodies, the constant pool and attributes. + The redefinition may change method bodies, the constant pool and attributes + (unless explicitly prohibited). The redefinition must not add, remove or rename fields or methods, change the signatures of methods, change modifiers, or change inheritance. + The retransformation must not change the <code>NestHost</code> or + <code>NestMembers</code> attributes. These restrictions may be lifted in future versions. See the error return description below for information on error codes returned if an unsupported redefinition is attempted. @@ -7855,6 +7864,9 @@ A new class version does not declare a method declared in the old class version. </error> + <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED"> + A new class version has unsupported differences in class attributes. + </error> <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED"> A new class version has different modifiers. </error> @@ -11739,6 +11751,9 @@ A method in the new class version has different modifiers than its counterpart in the old class version. </errorid> + <errorid id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED" num="72"> + A new class version has unsupported differences in class attributes. + </errorid> </errorcategory> </errorsection> @@ -14811,6 +14826,13 @@ - The function may return NULL in the start phase if the can_generate_early_vmstart capability is enabled. </change> + <change date="7 February 2018" version="11.0.0"> + Minor update for new class file NestHost and NestMembers attributes: + - Specify that RedefineClasses and RetransformClasses are not allowed + to change the class file NestHost and NestMembers attributes. + - Add new error JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED + that can be returned by RedefineClasses and RetransformClasses. + </change> </changehistory> </specification> --- old/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp 2018-05-18 03:44:09.485122836 -0400 +++ new/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp 2018-05-18 03:44:07.953034155 -0400 @@ -388,6 +388,40 @@ } } +// NestHost_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 host_class_index; +// } +void JvmtiClassFileReconstituter::write_nest_host_attribute() { + int length = sizeof(u2); + int host_class_index = ik()->nest_host_index(); + + write_attribute_name_index("NestHost"); + write_u4(length); + write_u2(host_class_index); +} + +// NestMembers_attribute { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 number_of_classes; +// u2 classes[number_of_classes]; +// } +void JvmtiClassFileReconstituter::write_nest_members_attribute() { + Array<u2>* nest_members = ik()->nest_members(); + int number_of_classes = nest_members->length(); + int length = sizeof(u2) * (1 + number_of_classes); + + write_attribute_name_index("NestMembers"); + write_u4(length); + write_u2(number_of_classes); + for (int i = 0; i < number_of_classes; i++) { + u2 class_cp_index = nest_members->at(i); + write_u2(class_cp_index); + } +} + // Write InnerClasses attribute // JVMSpec| InnerClasses_attribute { @@ -658,6 +692,12 @@ if (cpool()->operands() != NULL) { ++attr_count; } + if (ik()->nest_host_index() != 0) { + ++attr_count; + } + if (ik()->nest_members() != Universe::the_empty_short_array()) { + ++attr_count; + } write_u2(attr_count); @@ -682,6 +722,12 @@ if (cpool()->operands() != NULL) { write_bootstrapmethod_attribute(); } + if (ik()->nest_host_index() != 0) { + write_nest_host_attribute(); + } + if (ik()->nest_members() != Universe::the_empty_short_array()) { + write_nest_members_attribute(); + } } // Write the method information portion of ClassFile structure --- old/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp 2018-05-18 03:44:13.925379849 -0400 +++ new/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp 2018-05-18 03:44:12.377290239 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, 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 @@ -116,6 +116,8 @@ void write_attribute_name_index(const char* name); void write_annotations_attribute(const char* attr_name, AnnotationArray* annos); void write_bootstrapmethod_attribute(); + void write_nest_host_attribute(); + void write_nest_members_attribute(); address writeable_address(size_t size); void write_u1(u1 x); --- old/src/hotspot/share/prims/jvmtiExport.cpp 2018-05-18 03:44:18.657653763 -0400 +++ new/src/hotspot/share/prims/jvmtiExport.cpp 2018-05-18 03:44:16.805546558 -0400 @@ -370,6 +370,14 @@ return JNI_EVERSION; // unsupported minor version number } break; + case 11: + switch (minor) { + case 0: // version 11.0.<micro> is recognized + break; + default: + return JNI_EVERSION; // unsupported minor version number + } + break; default: return JNI_EVERSION; // unsupported major version number } --- old/src/hotspot/share/prims/jvmtiH.xsl 2018-05-18 03:44:23.117911937 -0400 +++ new/src/hotspot/share/prims/jvmtiH.xsl 2018-05-18 03:44:21.573822561 -0400 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 2018, 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 @@ -20,7 +20,7 @@ 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. - + --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" @@ -47,7 +47,7 @@ /* Constants */ </xsl:text> <xsl:apply-templates select="//constants"/> - + <xsl:text> /* Errors */ @@ -91,7 +91,7 @@ <xsl:apply-templates select="functionsection"/> <xsl:call-template name="outro"/> - + </xsl:template> <xsl:template name="intro"> @@ -114,6 +114,7 @@ JVMTI_VERSION_1_1 = 0x30010100, JVMTI_VERSION_1_2 = 0x30010200, JVMTI_VERSION_9 = 0x30090000, + JVMTI_VERSION_11 = 0x300B0000, JVMTI_VERSION = 0x30000000 + (</xsl:text> <xsl:value-of select="//specification/@majorversion"/> @@ -298,7 +299,7 @@ </xsl:when> <xsl:otherwise> <xsl:text> RESERVED */ - void *reserved</xsl:text> + void *reserved</xsl:text> <xsl:value-of select="$index"/> </xsl:otherwise> </xsl:choose> --- old/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2018-05-18 03:44:27.554168720 -0400 +++ new/src/hotspot/share/prims/jvmtiRedefineClasses.cpp 2018-05-18 03:44:26.014079574 -0400 @@ -683,6 +683,13 @@ _operands_index_map_count = 0; } // end finalize_operands_merge() +// Symbol* comparator for qsort +// The caller must have an active ResourceMark. +static int symcmp(const void* a, const void* b) { + char* astr = (*(Symbol**)a)->as_C_string(); + char* bstr = (*(Symbol**)b)->as_C_string(); + return strcmp(astr, bstr); +} jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( InstanceKlass* the_class, @@ -725,6 +732,100 @@ return JVMTI_ERROR_INVALID_CLASS; } + // Check whether the class NestHost attribute has been changed. + { + Thread* thread = Thread::current(); + ResourceMark rm(thread); + JvmtiThreadState *state = JvmtiThreadState::state_for((JavaThread*)thread); + RedefineVerifyMark rvm(the_class, scratch_class, state); + u2 the_nest_host_idx = the_class->nest_host_index(); + u2 scr_nest_host_idx = scratch_class->nest_host_index(); + + if (the_nest_host_idx != 0 && scr_nest_host_idx != 0) { + Symbol* the_sym = the_class->constants()->klass_name_at(the_nest_host_idx); + Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_nest_host_idx); + if (the_sym != scr_sym) { + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestHost class: %s replaced with: %s", + the_class->external_name(), the_sym->as_C_string(), scr_sym->as_C_string()); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + } else if ((the_nest_host_idx == 0) ^ (scr_nest_host_idx == 0)) { + const char* action_str = (the_nest_host_idx != 0) ? "removed" : "added"; + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestHost attribute %s", + the_class->external_name(), action_str); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + + // Check whether the class NestMembers attribute has been changed. + Array<u2>* the_nest_members = the_class->nest_members(); + Array<u2>* scr_nest_members = scratch_class->nest_members(); + bool the_members_exists = the_nest_members != Universe::the_empty_short_array(); + bool scr_members_exists = scr_nest_members != Universe::the_empty_short_array(); + + int members_len = the_nest_members->length(); + if (the_members_exists && scr_members_exists) { + if (members_len != scr_nest_members->length()) { + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestMember len=%d changed to len=%d", + the_class->external_name(), members_len, scr_nest_members->length()); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + + // The order of entries in the NestMembers array is not specified so we + // have to explicitly check for the same contents. We do this by copying + // the referenced symbols into their own arrays, sorting them and then + // comparing each element pair. + + Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len); + Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len); + + if (the_syms == NULL || scr_syms == NULL) { + return JVMTI_ERROR_OUT_OF_MEMORY; + } + + for (int i = 0; i < members_len; i++) { + int the_cp_index = the_nest_members->at(i); + int scr_cp_index = scr_nest_members->at(i); + the_syms[i] = the_class->constants()->klass_name_at(the_cp_index); + scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index); + } + + qsort(the_syms, members_len, sizeof(Symbol*), symcmp); + qsort(scr_syms, members_len, sizeof(Symbol*), symcmp); + + for (int i = 0; i < members_len; i++) { + if (the_syms[i] != scr_syms[i]) { + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s", + the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string()); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + } + /* + for (int i = 0; i < members_len; i++) { + int the_cp_index = the_nest_members->at(i); + int scr_cp_index = scr_nest_members->at(i); + Symbol* the_sym = the_class->constants()->klass_name_at(the_cp_index); + Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_cp_index); + if (the_sym != scr_sym) { + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s", + the_class->external_name(), i, the_sym->as_C_string(), scr_sym->as_C_string()); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + } + */ + } else if (the_members_exists ^ scr_members_exists) { + const char* action_str = (the_members_exists) ? "removed" : "added"; + log_trace(redefine, class, nestmates) + ("redefined class %s attribute change error: NestMembers attribute %s", + the_class->external_name(), action_str); + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; + } + } + // Check whether class modifiers are the same. jushort old_flags = (jushort) the_class->access_flags().get_flags(); jushort new_flags = (jushort) scratch_class->access_flags().get_flags(); @@ -1598,6 +1699,12 @@ bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class, TRAPS) { + // rewrite constant pool references in the nest attributes: + if (!rewrite_cp_refs_in_nest_attributes(scratch_class)) { + // propagate failure back to caller + return false; + } + // rewrite constant pool references in the methods: if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) { // propagate failure back to caller @@ -1680,6 +1787,22 @@ return true; } // end rewrite_cp_refs() +// Rewrite constant pool references in the NestHost and NestMembers attributes. +bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes( + InstanceKlass* scratch_class) { + + u2 cp_index = scratch_class->nest_host_index(); + if (cp_index != 0) { + scratch_class->set_nest_host_index(find_new_index(cp_index)); + } + Array<u2>* nest_members = scratch_class->nest_members(); + for (int i = 0; i < nest_members->length(); i++) { + u2 cp_index = nest_members->at(i); + nest_members->at_put(i, find_new_index(cp_index)); + } + return true; +} + // Rewrite constant pool references in the methods. bool VM_RedefineClasses::rewrite_cp_refs_in_methods( InstanceKlass* scratch_class, TRAPS) { --- old/src/hotspot/share/prims/jvmtiRedefineClasses.hpp 2018-05-18 03:44:32.838474592 -0400 +++ new/src/hotspot/share/prims/jvmtiRedefineClasses.hpp 2018-05-18 03:44:30.582344001 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -469,6 +469,7 @@ AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS); bool rewrite_cp_refs_in_fields_annotations( InstanceKlass* scratch_class, TRAPS); + bool rewrite_cp_refs_in_nest_attributes(InstanceKlass* scratch_class); void rewrite_cp_refs_in_method(methodHandle method, methodHandle * new_method_p, TRAPS); bool rewrite_cp_refs_in_methods(InstanceKlass* scratch_class, TRAPS); --- old/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java 2018-05-18 03:44:37.318733924 -0400 +++ new/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java 2018-05-18 03:44:35.766644084 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -219,10 +219,14 @@ * Instances of the retransformed class are not affected. * * <P> - * The retransformation may change method bodies, the constant pool and attributes. + * The retransformation may change method bodies, the constant pool and + * attributes (unless explicitly prohibited). * The retransformation must not add, remove or rename fields or methods, change the - * signatures of methods, or change inheritance. These restrictions maybe be - * lifted in future versions. The class file bytes are not checked, verified and installed + * signatures of methods, or change inheritance. + * The retransformation must not change the <code>NestHost</code> or + * <code>NestMembers</code> attributes. + * These restrictions maybe be lifted in future versions. + * The class file bytes are not checked, verified and installed * until after the transformations have been applied, if the resultant bytes are in * error this method will throw an exception. * @@ -306,10 +310,14 @@ * Instances of the redefined class are not affected. * * <P> - * The redefinition may change method bodies, the constant pool and attributes. + * The redefinition may change method bodies, the constant pool and attributes + * (unless explicitly prohibited). * The redefinition must not add, remove or rename fields or methods, change the - * signatures of methods, or change inheritance. These restrictions maybe be - * lifted in future versions. The class file bytes are not checked, verified and installed + * signatures of methods, or change inheritance. + * The retransformation must not change the <code>NestHost</code> or + * <code>NestMembers</code> attributes. + * These restrictions maybe be lifted in future versions. + * The class file bytes are not checked, verified and installed * until after the transformations have been applied, if the resultant bytes are in * error this method will throw an exception. * --- old/src/java.instrument/share/native/libinstrument/JavaExceptions.c 2018-05-18 03:44:41.778992099 -0400 +++ new/src/java.instrument/share/native/libinstrument/JavaExceptions.c 2018-05-18 03:44:40.234902721 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -214,6 +214,11 @@ message = "class redefinition failed: attempted to change the class modifiers"; break; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED: + throwableClassName = "java/lang/UnsupportedOperationException"; + message = "class redefinition failed: attempted to change the class NestHost or NestMembers attribute"; + break; + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED: throwableClassName = "java/lang/UnsupportedOperationException"; message = "class redefinition failed: attempted to change method modifiers"; --- old/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java 2018-05-18 03:44:46.255251200 -0400 +++ new/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java 2018-05-18 03:44:44.691160665 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -219,10 +219,11 @@ * this exception * <UL> * <LI>changing the schema (the fields) - * <LI>changing the hierarchy (subclasses, interfaces) + * <LI>changing the hierarchy (superclasses, interfaces) * <LI>deleting a method * <LI>changing class modifiers * <LI>changing method modifiers + * <LI>changing the {@code NestHost} or {@code NestMembers} class attributes * </UL> * </UL> * @@ -595,8 +596,9 @@ boolean canAddMethod(); /** - * Determines if the target VM supports unrestricted - * changes when performing class redefinition. + * Determines if the target VM supports + * changes when performing class redefinition that are + * otherwise restricted by {@link #redefineClasses}. * @see #redefineClasses * * @return <code>true</code> if the feature is supported, --- old/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java 2018-05-18 03:44:50.803514470 -0400 +++ new/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java 2018-05-18 03:44:49.235423704 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -395,6 +395,9 @@ case JDWP.Error.METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED : throw new UnsupportedOperationException( "changes to method modifiers not implemented"); + case JDWP.Error.CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED : + throw new UnsupportedOperationException( + "changes to class attribute not implemented"); case JDWP.Error.NAMES_DONT_MATCH : throw new NoClassDefFoundError( "class names do not match"); --- old/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java 2018-05-18 03:44:55.291774268 -0400 +++ new/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java 2018-05-18 03:44:53.739684427 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -52,7 +52,7 @@ private final ThreadGroup mainGroupForJDI; private ResourceBundle messages = null; private int vmSequenceNumber = 0; - private static final int majorVersion = 9; + private static final int majorVersion = 11; private static final int minorVersion = 0; private static final Object lock = new Object(); --- old/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c 2018-05-18 03:44:59.804035455 -0400 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c 2018-05-18 03:44:58.171940983 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -35,7 +35,7 @@ #include "FrameID.h" static char *versionName = "Java Debug Wire Protocol (Reference Implementation)"; -static int majorVersion = 9; /* JDWP major version */ +static int majorVersion = 11; /* JDWP major version */ static int minorVersion = 0; /* JDWP minor version */ static jboolean --- old/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c 2018-05-18 03:45:05.536367266 -0400 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c 2018-05-18 03:45:03.788266079 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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 @@ -285,6 +285,7 @@ CASE_RETURN_JDWP_ERROR_TEXT(NAMES_DONT_MATCH) CASE_RETURN_JDWP_ERROR_TEXT(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED) CASE_RETURN_JDWP_ERROR_TEXT(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED) + CASE_RETURN_JDWP_ERROR_TEXT(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED) CASE_RETURN_JDWP_ERROR_TEXT(NOT_IMPLEMENTED) CASE_RETURN_JDWP_ERROR_TEXT(NULL_POINTER) CASE_RETURN_JDWP_ERROR_TEXT(ABSENT_INFORMATION) --- old/src/jdk.jdwp.agent/share/native/libjdwp/util.c 2018-05-18 03:45:12.060744925 -0400 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/util.c 2018-05-18 03:45:09.740610626 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2018, 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 @@ -1888,6 +1888,8 @@ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED; case JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED): return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED; + case JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED): + return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; case JDWP_ERROR(NOT_IMPLEMENTED): return JVMTI_ERROR_NOT_AVAILABLE; case JDWP_ERROR(NULL_POINTER): @@ -2220,6 +2222,8 @@ return JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED); case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED: return JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED); + case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED: + return JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED); case AGENT_ERROR_NOT_CURRENT_FRAME: return JDWP_ERROR(NOT_CURRENT_FRAME); case AGENT_ERROR_INVALID_TAG: --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/Host/Host.java 2018-05-18 03:45:16.477000556 -0400 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "Host/Host.java";} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/Host/redef/Host.java 2018-05-18 03:45:21.365283514 -0400 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "Host/redef/Host.java";} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostA/Host.java 2018-05-18 03:45:26.133559525 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostA/Host.java";} + public static class A {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostA/redef/Host.java 2018-05-18 03:45:31.917894351 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostA/redef/Host.java"; } + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAB/Host.java 2018-05-18 03:45:40.506391497 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAB/Host.java";} + public static class A {} + public static class B {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAB/redef/Host.java 2018-05-18 03:45:45.402674921 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAB/redef/Host.java"; } + public static class A {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABC/Host.java 2018-05-18 03:45:51.467025959 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABC/Host.java";} + public static class A {} + public static class B {} + public static class C {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABC/redef/Host.java 2018-05-18 03:45:58.023405481 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABC/redef/Host.java"; } + public static class A {} + public static class B {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABCD/redef/Host.java 2018-05-18 03:46:04.059754901 -0400 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABCD/redef/Host.java"; } + public static class A {} + public static class B {} + public static class C {} + public static class D {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABD/redef/Host.java 2018-05-18 03:46:08.448008919 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABD/redef/Host.java"; } + public static class A {} + public static class B {} + public static class D {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAC/redef/Host.java 2018-05-18 03:46:12.804261087 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAC/redef/Host.java"; } + public static class A {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostACB/redef/Host.java 2018-05-18 03:46:17.216516497 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostACB/redef/Host.java"; } + public static class A {} + public static class C {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostB/redef/Host.java 2018-05-18 03:46:21.948790432 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostB/redef/Host.java"; } + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBA/redef/Host.java 2018-05-18 03:46:26.369046303 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBA/redef/Host.java"; } + public static class B {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBAC/redef/Host.java 2018-05-18 03:46:30.825304263 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBAC/redef/Host.java"; } + public static class B {} + public static class A {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBCA/redef/Host.java 2018-05-18 03:46:36.017604830 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBCA/redef/Host.java"; } + public static class B {} + public static class C {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostCAB/redef/Host.java 2018-05-18 03:46:40.557867652 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostCAB/redef/Host.java"; } + public static class C {} + public static class A {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostCBA/redef/Host.java 2018-05-18 03:46:45.030126539 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostCBA/redef/Host.java"; } + public static class C {} + public static class B {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/java/lang/instrument/RedefineNestmateAttr/TestNestmateAttr.java 2018-05-18 03:46:49.966412290 -0400 @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2018, 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 8010319 + * @summary Class redefinition must preclude changes to nest attributes + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @modules java.compiler + * java.instrument + * jdk.jartool/sun.tools.jar + * @compile ../NamedBuffer.java + * @run main RedefineClassHelper + * @compile Host/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr Host + * @compile HostA/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostA + * @compile HostAB/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostAB + * @compile HostABC/Host.java + * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostABC + */ + +/* Test Description + +The basic test class is call Host and we have variants that have zero or more +nested classes named A, B, C etc. Each variant of Host is defined in source +code in its own directory i.e. + +Host/Host.java defines zero nested classes +HostA/Host.java defines one nested class A +HostAB/Host.java defines two nested classes A and B (in that order) +etc. + +Each Host class has the form: + + public class Host { + public static String getID() { return "<directory name>/Host.java"; } + + < zero or more empty nested classes> + + public int m() { + return 1; // original class + } + } + +Under each directory is a directory "redef" with a modified version of the Host +class that changes the ID to e.g. Host/redef/Host.java, and the method m() +returns 2. This allows us to check we have the redefined class loaded. + +Using Host' to represent the redefined version we test redefinition +combinations as follows: + +Host: + Host -> Host' - succeeds m() returns 2 + Host -> HostA' - fails - added a nest member + +HostA: + HostA -> HostA' - succeeds m() returns 2 + HostA -> Host' - fails - removed a nest member + HostA -> HostAB' - fails - added a nest member + HostA -> HostB' - fails - replaced a nest member + +HostAB: + HostAB -> HostAB' - succeeds m() returns 2 + HostAB -> HostBA' - succeeds m() returns 2 + HostAB -> HostA' - fails - removed a nest member + HostAB -> HostABC' - fails - added a nest member + HostAB -> HostAC' - fails - replaced a nest member + +HostABC: + HostABC -> HostABC' - succeeds m() returns 2 + HostABC -> HostACB' - succeeds m() returns 2 + HostABC -> HostBAC' - succeeds m() returns 2 + HostABC -> HostBCA' - succeeds m() returns 2 + HostABC -> HostCAB' - succeeds m() returns 2 + HostABC -> HostCBA' - succeeds m() returns 2 + HostABC -> HostAB' - fails - removed a nest member + HostABC -> HostABCD' - fails - added a nest member + HostABC -> HostABD' - fails - replaced a nest member + +More than three nested classes doesn't add to the code coverage so +we stop here. + +Note that we always try to load the redefined version even when we expect it +to fail. + +We can only directly load one class Host per classloader, so to run all the +groups we either need to use new classloaders, or we reinvoke the test +requesting a different primary directory. We chose the latter using +multiple @run tags. So we preceed as follows: + + @compile Host/Host.java + @run TestNestmateAttr Host + @compile HostA/Host.java - replaces previous Host.class + @run TestNestmateAttr HostA + @compile HostAB/Host.java - replaces previous Host.class + @run TestNestmateAttr HostAB +etc. + +Within the test we directly compile redefined versions of the classes, +using CompilerUtil, and then read the .class file directly as a byte[] +to use with the RedefineClassHelper. + +Finally we test redefinition of the NestHost attribute - which is +conceptually simple, but in fact very tricky to do. We do that +when testing HostA so we can reuse the Host$A class. + +*/ + +import java.io.File; +import java.io.FileInputStream; +import jdk.test.lib.ByteCodeLoader; +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import static jdk.test.lib.Asserts.assertTrue; + +public class TestNestmateAttr { + + static final String SRC = System.getProperty("test.src"); + static final String DEST = System.getProperty("test.classes"); + static final boolean VERBOSE = Boolean.getBoolean("verbose"); + + public static void main(String[] args) throws Throwable { + String origin = args[0]; + System.out.println("Testing original Host class from " + origin); + + // Make sure the Host class loaded directly is an original version + // and from the expected location + Host h = new Host(); + assertTrue(h.m() == 1); + assertTrue(Host.getID().startsWith(origin + "/")); + + String[] badTransforms; // directories of bad classes + String[] goodTransforms; // directories of good classes + + boolean testNestHostChanges = false; + + switch (origin) { + case "Host": + badTransforms = new String[] { + "HostA" // add member + }; + goodTransforms = new String[] { + origin + }; + break; + + case "HostA": + badTransforms = new String[] { + "Host", // remove member + "HostAB", // add member + "HostB" // change member + }; + goodTransforms = new String[] { + origin + }; + testNestHostChanges = true; + break; + + case "HostAB": + badTransforms = new String[] { + "HostA", // remove member + "HostABC", // add member + "HostAC" // change member + }; + goodTransforms = new String[] { + origin, + "HostBA" // reorder members + }; + break; + + case "HostABC": + badTransforms = new String[] { + "HostAB", // remove member + "HostABCD", // add member + "HostABD" // change member + }; + goodTransforms = new String[] { + origin, + "HostACB", // reorder members + "HostBAC", // reorder members + "HostBCA", // reorder members + "HostCAB", // reorder members + "HostCBA" // reorder members + }; + break; + + default: throw new Error("Unknown test directory: " + origin); + } + + // Compile and check bad transformations + checkBadTransforms(Host.class, badTransforms); + + // Compile and check good transformations + checkGoodTransforms(Host.class, goodTransforms); + + if (testNestHostChanges) + checkNestHostChanges(); + } + + static void checkNestHostChanges() throws Throwable { + // case 1: remove NestHost attribute + // - try to redefine Host$A with a top-level + // class called Host$A + System.out.println("Trying bad retransform that removes the NestHost attribute"); + + String name = "Host$A"; + // This is compiled as a top-level class: the $ in the name is not + // significant to the compiler. + String hostA = "public class " + name + " {}"; + + // Have to do this reflectively as there is no Host$A + // when compiling the "Host/" case. + Class<?> nestedA = Class.forName(name); + + try { + RedefineClassHelper.redefineClass(nestedA, hostA); + throw new Error("Retransformation to top-level class " + name + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("attempted to change the class Nest")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + // case 2: add NestHost attribute + // - This is tricky because the class with no NestHost attribute + // has to have the name of a nested class! Plus we need the + // redefining class in bytecode form. + // - Use the InMemoryJavaCompiler plus ByteCodeLoader to load + // the top-level Host$A class + // - Try to redefine that class with a real nested Host$A + + System.out.println("Trying bad retransform that adds the NestHost attribute"); + byte[] bytes = InMemoryJavaCompiler.compile(name, hostA); + Class<?> topLevelHostA = ByteCodeLoader.load(name, bytes); + + byte[] nestedBytes; + File clsfile = new File(DEST + "/" + name + ".class"); + if (VERBOSE) System.out.println("Reading bytes from " + clsfile); + try (FileInputStream str = new FileInputStream(clsfile)) { + nestedBytes = NamedBuffer.loadBufferFromStream(str); + } + try { + RedefineClassHelper.redefineClass(topLevelHostA, nestedBytes); + throw new Error("Retransformation to nested class " + name + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("attempted to change the class Nest")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + // case 3: replace the NestHost attribute + // - the easiest way (perhaps only reasonable way) to do this + // is to search for the Utf8 entry used by the Constant_ClassRef, + // set in the NestHost attribute, and edit it to refer to a different + // name. + System.out.println("Trying bad retransform that changes the NestHost attribute"); + int utf8Entry_length = 7; + boolean found = false; + for (int i = 0; i < nestedBytes.length - utf8Entry_length; i++) { + if (nestedBytes[i] == 1 && // utf8 tag + nestedBytes[i+1] == 0 && // msb of length + nestedBytes[i+2] == 4 && // lsb of length + nestedBytes[i+3] == (byte) 'H' && + nestedBytes[i+4] == (byte) 'o' && + nestedBytes[i+5] == (byte) 's' && + nestedBytes[i+6] == (byte) 't') { + + if (VERBOSE) System.out.println("Appear to have found Host utf8 entry starting at " + i); + + nestedBytes[i+3] = (byte) 'G'; + found = true; + break; + } + } + + if (!found) + throw new Error("Could not locate 'Host' name in byte array"); + + try { + RedefineClassHelper.redefineClass(nestedA, nestedBytes); + throw new Error("Retransformation to modified nested class" + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("attempted to change the class Nest")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + } + + static void checkGoodTransforms(Class<?> c, String[] dirs) throws Throwable { + for (String dir : dirs) { + dir += "/redef"; + System.out.println("Trying good retransform from " + dir); + byte[] buf = bytesForHostClass(dir); + RedefineClassHelper.redefineClass(c, buf); + + // Test redefintion worked + Host h = new Host(); + assertTrue(h.m() == 2); + if (VERBOSE) System.out.println("Redefined ID: " + Host.getID()); + assertTrue(Host.getID().startsWith(dir)); + } + } + + static void checkBadTransforms(Class<?> c, String[] dirs) throws Throwable { + for (String dir : dirs) { + dir += "/redef"; + System.out.println("Trying bad retransform from " + dir); + byte[] buf = bytesForHostClass(dir); + try { + RedefineClassHelper.redefineClass(c, buf); + throw new Error("Retransformation from directory " + dir + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("attempted to change the class Nest")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + } + } + + static byte[] bytesForHostClass(String dir) throws Throwable { + compile("/" + dir); + File clsfile = new File(DEST + "/" + dir + "/Host.class"); + if (VERBOSE) System.out.println("Reading bytes from " + clsfile); + byte[] buf = null; + try (FileInputStream str = new FileInputStream(clsfile)) { + return buf = NamedBuffer.loadBufferFromStream(str); + } + } + + static void compile(String dir) throws Throwable { + File src = new File(SRC + dir); + File dst = new File(DEST + dir); + if (VERBOSE) System.out.println("Compiling from: " + src + "\n" + + " to: " + dst); + CompilerUtils.compile(src.toPath(), + dst.toPath(), + false /* don't recurse */, + new String[0]); + } +} --- old/test/hotspot/jtreg/ProblemList.txt 2018-05-18 03:46:56.678800855 -0400 +++ new/test/hotspot/jtreg/ProblemList.txt 2018-05-18 03:46:54.994703366 -0400 @@ -71,8 +71,16 @@ ############################################################################# # :hotspot_runtime - +runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java 8199450 generic-all +runtime/appcds/redefineClass/RedefineBasicTest.java 8199450 generic-all runtime/CompressedOops/UseCompressedOops.java 8079353 generic-all +runtime/RedefineTests/RedefineFinalizer.java 8199450 generic-all +runtime/RedefineTests/RedefineRunningMethods.java 8199450 generic-all +runtime/RedefineTests/RedefinePreviousVersions.java 8199450 generic-all +runtime/RedefineTests/RedefineDoubleDelete.java 8199450 generic-all +runtime/RedefineTests/RedefineInterfaceMethods.java 8199450 generic-all +runtime/RedefineTests/RedefineInterfaceCall.java 8199450 generic-all +runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java 8199450 generic-all ############################################################################# @@ -123,4 +131,8 @@ vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l005/TestDescription.java 8068225 generic-all vmTestbase/nsk/jdi/stress/ClassPrepareEvents/ClassPrepareEvents001/ClassPrepareEvents001.java 6426321 generic-all +vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic002/TestDescription.java 8203033 generic-all + ############################################################################# + +testlibrary_tests/RedefineClassTest.java 8199450 generic-all --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/Host/Host.java 2018-05-18 03:46:59.538966423 -0400 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "Host/Host.java";} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/Host/redef/Host.java 2018-05-18 03:47:04.299241986 -0400 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "Host/redef/Host.java";} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostA/Host.java 2018-05-18 03:47:08.711497402 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostA/Host.java";} + public static class A {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostA/redef/Host.java 2018-05-18 03:47:13.135753514 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostA/redef/Host.java"; } + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAB/Host.java 2018-05-18 03:47:17.552009164 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAB/Host.java";} + public static class A {} + public static class B {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAB/redef/Host.java 2018-05-18 03:47:22.376288434 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAB/redef/Host.java"; } + public static class A {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABC/Host.java 2018-05-18 03:47:26.804544780 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABC/Host.java";} + public static class A {} + public static class B {} + public static class C {} + public int m() { + return 1; // original class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABC/redef/Host.java 2018-05-18 03:47:31.288804366 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABC/redef/Host.java"; } + public static class A {} + public static class B {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABCD/redef/Host.java 2018-05-18 03:47:36.681116523 -0400 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABCD/redef/Host.java"; } + public static class A {} + public static class B {} + public static class C {} + public static class D {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABD/redef/Host.java 2018-05-18 03:47:41.129374029 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostABD/redef/Host.java"; } + public static class A {} + public static class B {} + public static class D {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAC/redef/Host.java 2018-05-18 03:47:45.557630377 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostAC/redef/Host.java"; } + public static class A {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostACB/redef/Host.java 2018-05-18 03:47:49.985886724 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostACB/redef/Host.java"; } + public static class A {} + public static class C {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostB/redef/Host.java 2018-05-18 03:47:54.406142611 -0400 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostB/redef/Host.java"; } + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBA/redef/Host.java 2018-05-18 03:47:58.802397109 -0400 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBA/redef/Host.java"; } + public static class B {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBAC/redef/Host.java 2018-05-18 03:48:03.290656934 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBAC/redef/Host.java"; } + public static class B {} + public static class A {} + public static class C {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBCA/redef/Host.java 2018-05-18 03:48:07.930925559 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostBCA/redef/Host.java"; } + public static class B {} + public static class C {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostCAB/redef/Host.java 2018-05-18 03:48:12.339180753 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostCAB/redef/Host.java"; } + public static class C {} + public static class A {} + public static class B {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostCBA/redef/Host.java 2018-05-18 03:48:16.751436179 -0400 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, 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. + */ + +public class Host { + public static String getID() { return "HostCBA/redef/Host.java"; } + public static class C {} + public static class B {} + public static class A {} + public int m() { + return 2; // redefined class + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/NamedBuffer.java 2018-05-18 03:48:21.511711752 -0400 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2003, 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.*; + +/* + * Copyright 2003 Wily Technology, Inc. + */ + +public class NamedBuffer +{ + private final String fName; + private final byte[] fBuffer; + + public + NamedBuffer( String name, + byte[] buffer) + { + fName = name; + fBuffer = buffer; + } + + public + NamedBuffer( String name, + InputStream stream) + throws IOException + { + this( name, + loadBufferFromStream(stream)); + } + + public String + getName() + { + return fName; + } + + public byte[] + getBuffer() + { + return fBuffer; + } + + public static byte[] + loadBufferFromStream(InputStream stream) + throws IOException + { + // hack for now, just assume the stream will fit in our reasonable size buffer. + // if not, panic + int bufferLimit = 200 * 1024; + byte[] readBuffer = new byte[bufferLimit]; + int actualSize = stream.read(readBuffer); + if ( actualSize >= bufferLimit ) + { + // if there might be more bytes, just surrender + throw new IOException("too big for buffer"); + } + + byte[] resultBuffer = new byte[actualSize]; + System.arraycopy( readBuffer, + 0, + resultBuffer, + 0, + actualSize); + return resultBuffer; + } +} --- /dev/null 2018-04-28 00:26:07.190086997 -0400 +++ new/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java 2018-05-18 03:48:25.927967411 -0400 @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2018, 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 8010319 + * @summary Class redefinition must preclude changes to nest attributes + * @comment This is a copy of test/jdk/java/lang/instrument/RedefineNestmateAttr/ + * @comment modified for JDI + * @library /test/lib .. + * @modules java.compiler + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @compile NamedBuffer.java + * @compile Host/Host.java + * @run main/othervm TestNestmateAttr Host + * @compile HostA/Host.java + * @run main/othervm TestNestmateAttr HostA + * @compile HostAB/Host.java + * @run main/othervm TestNestmateAttr HostAB + * @compile HostABC/Host.java + * @run main/othervm TestNestmateAttr HostABC + */ + +/* Test Description + +The basic test class is called Host and we have variants that have zero or more +nested classes named A, B, C etc. Each variant of Host is defined in source +code in its own directory i.e. + +Host/Host.java defines zero nested classes +HostA/Host.java defines one nested class A +HostAB/Host.java defines two nested classes A and B (in that order) +etc. + +Each Host class has the form: + + public class Host { + public static String getID() { return "<directory name>/Host.java"; } + + < zero or more empty nested classes> + + public int m() { + return 1; // original class + } + } + +Under each directory is a directory "redef" with a modified version of the Host +class that changes the ID to e.g. Host/redef/Host.java, and the method m() +returns 2. This allows us to check we have the redefined class loaded. + +Using Host' to represent the redefined version we test redefinition +combinations as follows: + +Host: + Host -> Host' - succeeds m() returns 2 + Host -> HostA' - fails - added a nest member + +HostA: + HostA -> HostA' - succeeds m() returns 2 + HostA -> Host' - fails - removed a nest member + HostA -> HostAB' - fails - added a nest member + HostA -> HostB' - fails - replaced a nest member + +HostAB: + HostAB -> HostAB' - succeeds m() returns 2 + HostAB -> HostBA' - succeeds m() returns 2 + HostAB -> HostA' - fails - removed a nest member + HostAB -> HostABC' - fails - added a nest member + HostAB -> HostAC' - fails - replaced a nest member + +HostABC: + HostABC -> HostABC' - succeeds m() returns 2 + HostABC -> HostACB' - succeeds m() returns 2 + HostABC -> HostBAC' - succeeds m() returns 2 + HostABC -> HostBCA' - succeeds m() returns 2 + HostABC -> HostCAB' - succeeds m() returns 2 + HostABC -> HostCBA' - succeeds m() returns 2 + HostABC -> HostAB' - fails - removed a nest member + HostABC -> HostABCD' - fails - added a nest member + HostABC -> HostABD' - fails - replaced a nest member + +More than three nested classes doesn't add to the code coverage so +we stop here. + +Note that we always try to load the redefined version even when we expect it +to fail. + +We can only directly load one class Host per classloader, so to run all the +groups we either need to use new classloaders, or we reinvoke the test +requesting a different primary directory. We chose the latter using +multiple @run tags. So we proceed as follows: + + @compile Host/Host.java + @run TestNestmateAttr Host + @compile HostA/Host.java - replaces previous Host.class + @run TestNestmateAttr HostA + @compile HostAB/Host.java - replaces previous Host.class + @run TestNestmateAttr HostAB +etc. + +Within the test we directly compile redefined versions of the classes, +using CompilerUtil, and then read the .class file directly as a byte[]. + +Finally we test redefinition of the NestHost attribute - which is +conceptually simple, but in fact very tricky to do. We do that +when testing HostA so we can reuse the Host$A class. + +*/ + +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.test.lib.ByteCodeLoader; +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.compiler.InMemoryJavaCompiler; +import static jdk.test.lib.Asserts.assertTrue; + +/* For JDI the test is split across two VMs and so split into + two main classes. This is the class we will run under the debugger. + Package access so we can define in the same source file for ease of + reference. +*/ +class Target { + // We have to load all of the variants of the classes that we will + // attempt to redefine. This requires some in-memory compilation + // and use of additional classloaders. + public static void main(String[] args) throws Throwable { + String origin = args[0]; + System.out.println("Target: Testing original Host class from " + origin); + + // Make sure the Host class loaded directly is an original version + // and from the expected location + Host h = new Host(); + assertTrue(h.m() == 1); + assertTrue(Host.getID().startsWith(origin + "/")); + + // The rest of this setup is only needed for the case + // when we perform the checkNestHostChanges() test. + if (origin.equals("HostA")) { + String name = "Host$A"; + + // Have to do this reflectively as there is no Host$A + // when compiling the "Host/" case. + Class<?> nestedA = Class.forName(name); // triggers initialization + + // This is compiled as a top-level class: the $ in the name is not + // significant to the compiler. + String hostA = "public class " + name + " {}"; + byte[] bytes = InMemoryJavaCompiler.compile(name, hostA); + // And we have to load this into a new classloader + Class<?> topLevelHostA = ByteCodeLoader.load(name, bytes); + // The loaded class has not been linked (as per ClassLoader.resolveClass) + // and so will be filtered out by VirtualMachine.allClasses(). There are + // a number of ways to force linking - this is the simplest. + Object o = topLevelHostA.newInstance(); + + // sanity check + assertTrue(nestedA.getClassLoader() != topLevelHostA.getClassLoader()); + + } + + allowRedefine(); // debugger stops us here to attempt redefinitions + + System.out.println("Target executed okay"); + } + + public static void allowRedefine() { } +} + +public class TestNestmateAttr extends TestScaffold { + + static final String SRC = System.getProperty("test.src"); + static final String DEST = System.getProperty("test.classes"); + static final boolean VERBOSE = Boolean.getBoolean("verbose"); + + static String origin; + + // override this to correct a bug so arguments can be passed to + // the Target class + protected void startUp(String targetName) { + List<String> argList = new ArrayList<>(Arrays.asList(args)); + argList.add(0, targetName); // pre-pend so it becomes the first "app" arg + println("run args: " + argList); + connect((String[]) argList.toArray(args)); + waitForVMStart(); + } + + TestNestmateAttr (String[] args) { + super(args); + } + + public static void main(String[] args) throws Throwable { + origin = args[0]; + new TestNestmateAttr(args).startTests(); + } + + public void runTests() throws Exception { + // Get Target into debuggable state + BreakpointEvent bpe = startToMain("Target"); + EventRequestManager erm = vm().eventRequestManager(); + MethodEntryRequest mee = erm.createMethodEntryRequest(); + mee.addClassFilter("Target"); + mee.enable(); + + // Allow application to complete and shut down + listenUntilVMDisconnect(); + + if (getExceptionCaught()) { + throw new Exception("TestNestmateAttr: failed due to unexpected exception - check logs for details"); + } + else if (!testFailed) { + println("TestNestmateAttr: passed"); + } else { + throw new Exception("TestNestmateAttr: failure reported - check log for details"); + } + } + + // All the actual work is done from here once we see we've entered Target.allowRedefine() + public void methodEntered(MethodEntryEvent event) { + Method meth = event.location().method(); + + if (!meth.name().equals("allowRedefine")) { + return; + } + + System.out.println("TestNestmateAttr: Testing original Host class from " + origin); + + String[] badTransforms; // directories of bad classes + String[] goodTransforms; // directories of good classes + + boolean testNestHostChanges = false; + + switch (origin) { + case "Host": + badTransforms = new String[] { + "HostA" // add member + }; + goodTransforms = new String[] { + origin + }; + break; + + case "HostA": + badTransforms = new String[] { + "Host", // remove member + "HostAB", // add member + "HostB" // change member + }; + goodTransforms = new String[] { + origin + }; + testNestHostChanges = true; + break; + + case "HostAB": + badTransforms = new String[] { + "HostA", // remove member + "HostABC", // add member + "HostAC" // change member + }; + goodTransforms = new String[] { + origin, + "HostBA" // reorder members + }; + break; + + case "HostABC": + badTransforms = new String[] { + "HostAB", // remove member + "HostABCD", // add member + "HostABD" // change member + }; + goodTransforms = new String[] { + origin, + "HostACB", // reorder members + "HostBAC", // reorder members + "HostBCA", // reorder members + "HostCAB", // reorder members + "HostCBA" // reorder members + }; + break; + + default: throw new Error("Unknown test directory: " + origin); + } + + // Need to locate the type we will be trying to redefine in Target + findReferenceTypes(); + + try { + // Compile and check bad transformations + checkBadTransforms(_Host, badTransforms); + + // Compile and check good transformations + checkGoodTransforms(_Host, goodTransforms); + + if (testNestHostChanges) + checkNestHostChanges(); + } + catch (Throwable t) { + failure(t); + } + } + + // override to give exception details + protected void failure(Throwable t) { + super.failure(t.getMessage()); + t.printStackTrace(System.out); + } + + // These are references to the types in Target + // that we will be trying to redefine. + ReferenceType _Host; + ReferenceType _Host_A_nested; + ReferenceType _Host_A_topLevel; + + void findReferenceTypes() { + List<ReferenceType> classes = vm().allClasses(); + ClassLoaderReference cl = null; // track the main loader + ReferenceType a1 = null; + ReferenceType a2 = null; + for (ReferenceType c : classes) { + String name = c.name(); + if (name.equals("Host")) { + _Host = c; + cl = c.classLoader(); + } + else if (name.equals("Host$A")) { + if (a1 == null) { + a1 = c; + } else if (a2 == null) { + a2 = c; + } + else { + assertTrue(false); // Too many Host$A classes found! + } + } + } + assertTrue(_Host != null); + + // The rest of this setup is only needed for the case + // when we perform the checkNestHostChanges() test. + if (origin.equals("HostA")) { + assertTrue(a1 != null); + assertTrue(a2 != null); + + if (a1.classLoader() == cl) { + _Host_A_nested = a1; + assertTrue(a2.classLoader() != cl); + _Host_A_topLevel = a2; + } + else if (a2.classLoader() == cl) { + _Host_A_nested = a2; + assertTrue(a1.classLoader() != cl); + _Host_A_topLevel = a1; + } + else { + assertTrue(false); // Wrong classLoaders found + } + } + } + + void checkNestHostChanges() throws Throwable { + Map<ReferenceType, byte[]> map = new HashMap<>(); + + // case 1: remove NestHost attribute + // - try to redefine nested Host$A with a top-level + // class called Host$A + System.out.println("Trying bad retransform that removes the NestHost attribute"); + + String name = "Host$A"; + + // This is compiled as a top-level class: the $ in the name is not + // significant to the compiler. + String hostA = "public class " + name + " {}"; + byte[] bytes = InMemoryJavaCompiler.compile(name, hostA); + + map.put(_Host_A_nested, bytes); + + try { + vm().redefineClasses(map); + throw new Error("Retransformation to top-level class " + name + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("changes to class attribute not implemented")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + map.clear(); + + // case 2: add NestHost attribute + // - This is tricky because the class with no NestHost attribute + // has to have the name of a nested class! But we know how to + // do that as we already created a top-level Host$A. So now + // we try to replace with a really nested Host$A. + + System.out.println("Trying bad retransform that adds the NestHost attribute"); + + byte[] nestedBytes; + File clsfile = new File(DEST + "/" + name + ".class"); + if (VERBOSE) System.out.println("Reading bytes from " + clsfile); + try (FileInputStream str = new FileInputStream(clsfile)) { + nestedBytes = NamedBuffer.loadBufferFromStream(str); + } + + map.put(_Host_A_topLevel, nestedBytes); + + try { + vm().redefineClasses(map); + throw new Error("Retransformation to nested class " + name + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("changes to class attribute not implemented")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + map.clear(); + + // case 3: replace the NestHost attribute + // - the easiest way (perhaps only reasonable way) to do this + // is to search for the Utf8 entry used by the Constant_ClassRef, + // set in the NestHost attribute, and edit it to refer to a different + // name. We reuse nestedBytes from above. + + System.out.println("Trying bad retransform that changes the NestHost attribute"); + + int utf8Entry_length = 7; + boolean found = false; + for (int i = 0; i < nestedBytes.length - utf8Entry_length; i++) { + if (nestedBytes[i] == 1 && // utf8 tag + nestedBytes[i+1] == 0 && // msb of length + nestedBytes[i+2] == 4 && // lsb of length + nestedBytes[i+3] == (byte) 'H' && + nestedBytes[i+4] == (byte) 'o' && + nestedBytes[i+5] == (byte) 's' && + nestedBytes[i+6] == (byte) 't') { + + if (VERBOSE) System.out.println("Appear to have found Host utf8 entry starting at " + i); + + nestedBytes[i+3] = (byte) 'G'; + found = true; + break; + } + } + + if (!found) + throw new Error("Could not locate 'Host' name in byte array"); + + map.put(_Host_A_nested, nestedBytes); + + try { + vm().redefineClasses(map); + throw new Error("Retransformation to modified nested class" + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("changes to class attribute not implemented")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + + } + + void checkGoodTransforms(ReferenceType c, String[] dirs) throws Throwable { + // To verify the redefinition actually took place we will invoke the + // Host.getID method and check the result. To do that we need to find the + // main thread in the target VM. We don't check that "(new Host()).m()" + // returns 2 due to the complexity of setting that up via JDI. + + ThreadReference main = null; + List<ThreadReference> threads = vm().allThreads(); + for (ThreadReference t : threads) { + if (t.name().equals("main")) { + main = t; + break; + } + } + + assertTrue(main != null); + + // Now find the method + Method getID = null; + List<Method> methods = _Host.methodsByName("getID"); + assertTrue(methods.size() == 1); + getID = methods.get(0); + + Map<ReferenceType, byte[]> map = new HashMap<>(); + for (String dir : dirs) { + dir += "/redef"; + System.out.println("Trying good retransform from " + dir); + byte[] buf = bytesForHostClass(dir); + map.put(c, buf); + vm().redefineClasses(map); + map.clear(); + // Test redefinition worked + Value v = ((ClassType)_Host).invokeMethod(main, getID, Collections.emptyList(), 0); + assertTrue(v instanceof StringReference); + String id = ((StringReference)v).value(); + if (VERBOSE) System.out.println("Redefined ID: " + id); + assertTrue(id.startsWith(dir)); + assertTrue(id.contains("/redef/")); + } + } + + void checkBadTransforms(ReferenceType c, String[] dirs) throws Throwable { + Map<ReferenceType, byte[]> map = new HashMap<>(); + for (String dir : dirs) { + dir += "/redef"; + System.out.println("Trying bad retransform from " + dir); + byte[] buf = bytesForHostClass(dir); + map.put(c, buf); + try { + vm().redefineClasses(map); + throw new Error("Retransformation from directory " + dir + + " succeeded unexpectedly"); + } + catch (UnsupportedOperationException uoe) { + if (uoe.getMessage().contains("changes to class attribute not implemented")) { + System.out.println("Got expected exception " + uoe); + } + else throw new Error("Wrong UnsupportedOperationException", uoe); + } + } + } + + static byte[] bytesForHostClass(String dir) throws Throwable { + compile("/" + dir); + File clsfile = new File(DEST + "/" + dir + "/Host.class"); + if (VERBOSE) System.out.println("Reading bytes from " + clsfile); + byte[] buf = null; + try (FileInputStream str = new FileInputStream(clsfile)) { + return buf = NamedBuffer.loadBufferFromStream(str); + } + } + + static void compile(String dir) throws Throwable { + File src = new File(SRC + dir); + File dst = new File(DEST + dir); + if (VERBOSE) System.out.println("Compiling from: " + src + "\n" + + " to: " + dst); + CompilerUtils.compile(src.toPath(), + dst.toPath(), + false /* don't recurse */, + new String[0]); + } +}