Mon, 19 Mar 2018 13:23:53 -0700
Merge
.hgtags | file | annotate | diff | comparison | revisions | |
src/share/vm/oops/klass.cpp | file | annotate | diff | comparison | revisions | |
test/runtime/RedefineFinalizer/RedefineFinalizer.java | file | annotate | diff | comparison | revisions |
1.1 --- a/.hgtags Mon Mar 19 12:12:48 2018 -0700 1.2 +++ b/.hgtags Mon Mar 19 13:23:53 2018 -0700 1.3 @@ -1131,6 +1131,11 @@ 1.4 39e2895b795aded8b584626fb019d35f12e9d1e7 jdk8u162-b11 1.5 69aec2ca5d905dde1d0f29a89076d02a531808a3 jdk8u162-b12 1.6 caac74fe3cfa9a8c859c28c97d1046a58252af27 jdk8u162-b31 1.7 +c9b7abadf150328d2187de05b9e8a9cba2486e47 jdk8u162-b32 1.8 +e8041f2ec96eb6a41307732e6cf6ed90901438ae jdk8u162-b33 1.9 +bf2e8b1e8e8e6bc1f9b9475de54ba0329a6b24b1 jdk8u162-b34 1.10 +9b3f207379cf6ecfb8603640269e31ff4e064294 jdk8u162-b35 1.11 +d2ebd6530396b0afc700cd1a8eaf1f7a7f9fce8d jdk8u162-b36 1.12 a17bab9405474602b18cd62e060a09b17d6413ac jdk8u171-b00 1.13 ebfd57cc21e6b7f0c22b17c666b6b28c9340e207 jdk8u171-b01 1.14 1acd7c1b80241def8fac90f70b0df16356adad47 jdk8u171-b02
2.1 --- a/agent/src/os/linux/Makefile Mon Mar 19 12:12:48 2018 -0700 2.2 +++ b/agent/src/os/linux/Makefile Mon Mar 19 13:23:53 2018 -0700 2.3 @@ -1,5 +1,5 @@ 2.4 # 2.5 -# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. 2.6 +# Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. 2.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 # 2.9 # This code is free software; you can redistribute it and/or modify it 2.10 @@ -76,6 +76,9 @@ 2.11 endif 2.12 LFLAGS_LIBSA += $(LDFLAGS_HASH_STYLE) 2.13 2.14 +LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" 2.15 +LFLAGS_LIBSA += $(LDFLAGS_NO_EXEC_STACK) 2.16 + 2.17 $(LIBSA): $(ARCH) $(OBJS) mapfile 2.18 $(GCC) -shared $(LFLAGS_LIBSA) -o $(LIBSA) $(OBJS) $(LIBS) 2.19
3.1 --- a/make/linux/makefiles/gcc.make Mon Mar 19 12:12:48 2018 -0700 3.2 +++ b/make/linux/makefiles/gcc.make Mon Mar 19 13:23:53 2018 -0700 3.3 @@ -1,5 +1,5 @@ 3.4 # 3.5 -# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 3.6 +# Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. 3.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 # 3.9 # This code is free software; you can redistribute it and/or modify it 3.10 @@ -303,6 +303,8 @@ 3.11 3.12 LFLAGS += $(LDFLAGS_HASH_STYLE) 3.13 3.14 +LDFLAGS_NO_EXEC_STACK="-Wl,-z,noexecstack" 3.15 + 3.16 # Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file. 3.17 MAPFLAG = -Xlinker --version-script=FILENAME 3.18
4.1 --- a/make/linux/makefiles/jsig.make Mon Mar 19 12:12:48 2018 -0700 4.2 +++ b/make/linux/makefiles/jsig.make Mon Mar 19 13:23:53 2018 -0700 4.3 @@ -1,5 +1,5 @@ 4.4 # 4.5 -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 4.6 +# Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. 4.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 # 4.9 # This code is free software; you can redistribute it and/or modify it 4.10 @@ -44,7 +44,7 @@ 4.11 # cause problems with interposing. See CR: 6466665 4.12 # LFLAGS_JSIG += $(MAPFLAG:FILENAME=$(LIBJSIG_MAPFILE)) 4.13 4.14 -LFLAGS_JSIG += -D_GNU_SOURCE -D_REENTRANT $(LDFLAGS_HASH_STYLE) 4.15 +LFLAGS_JSIG += -D_GNU_SOURCE -D_REENTRANT $(LDFLAGS_HASH_STYLE) $(LDFLAGS_NO_EXEC_STACK) 4.16 4.17 # DEBUG_BINARIES overrides everything, use full -g debug information 4.18 ifeq ($(DEBUG_BINARIES), true)
5.1 --- a/src/share/vm/classfile/metadataOnStackMark.cpp Mon Mar 19 12:12:48 2018 -0700 5.2 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp Mon Mar 19 13:23:53 2018 -0700 5.3 @@ -41,13 +41,13 @@ 5.4 // Walk metadata on the stack and mark it so that redefinition doesn't delete 5.5 // it. Class unloading also walks the previous versions and might try to 5.6 // delete it, so this class is used by class unloading also. 5.7 -MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) { 5.8 +MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) { 5.9 assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); 5.10 assert(_used_buffers == NULL, "sanity check"); 5.11 NOT_PRODUCT(_is_active = true;) 5.12 5.13 Threads::metadata_do(Metadata::mark_on_stack); 5.14 - if (visit_code_cache) { 5.15 + if (has_redefined_a_class) { 5.16 CodeCache::alive_nmethods_do(nmethod::mark_on_stack); 5.17 } 5.18 CompileBroker::mark_on_stack();
6.1 --- a/src/share/vm/classfile/metadataOnStackMark.hpp Mon Mar 19 12:12:48 2018 -0700 6.2 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp Mon Mar 19 13:23:53 2018 -0700 6.3 @@ -47,7 +47,7 @@ 6.4 static void retire_buffer(MetadataOnStackBuffer* buffer); 6.5 6.6 public: 6.7 - MetadataOnStackMark(bool visit_code_cache); 6.8 + MetadataOnStackMark(bool has_redefined_a_class); 6.9 ~MetadataOnStackMark(); 6.10 6.11 static void record(Metadata* m, Thread* thread);
7.1 --- a/src/share/vm/code/nmethod.cpp Mon Mar 19 12:12:48 2018 -0700 7.2 +++ b/src/share/vm/code/nmethod.cpp Mon Mar 19 13:23:53 2018 -0700 7.3 @@ -2172,7 +2172,7 @@ 7.4 "metadata must be found in exactly one place"); 7.5 if (r->metadata_is_immediate() && r->metadata_value() != NULL) { 7.6 Metadata* md = r->metadata_value(); 7.7 - f(md); 7.8 + if (md != _method) f(md); 7.9 } 7.10 } else if (iter.type() == relocInfo::virtual_call_type) { 7.11 // Check compiledIC holders associated with this nmethod 7.12 @@ -2198,7 +2198,7 @@ 7.13 f(md); 7.14 } 7.15 7.16 - // Visit metadata not embedded in the other places. 7.17 + // Call function Method*, not embedded in these other places. 7.18 if (_method != NULL) f(_method); 7.19 } 7.20
8.1 --- a/src/share/vm/oops/instanceKlass.cpp Mon Mar 19 12:12:48 2018 -0700 8.2 +++ b/src/share/vm/oops/instanceKlass.cpp Mon Mar 19 13:23:53 2018 -0700 8.3 @@ -2582,16 +2582,6 @@ 8.4 assert(breakpoints() == 0x0, "should have cleared breakpoints"); 8.5 } 8.6 8.7 - // deallocate information about previous versions 8.8 - if (_previous_versions != NULL) { 8.9 - for (int i = _previous_versions->length() - 1; i >= 0; i--) { 8.10 - PreviousVersionNode * pv_node = _previous_versions->at(i); 8.11 - delete pv_node; 8.12 - } 8.13 - delete _previous_versions; 8.14 - _previous_versions = NULL; 8.15 - } 8.16 - 8.17 // deallocate the cached class file 8.18 if (_cached_class_file != NULL) { 8.19 os::free(_cached_class_file, mtClass); 8.20 @@ -3187,16 +3177,17 @@ 8.21 st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); 8.22 { 8.23 bool have_pv = false; 8.24 - PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); 8.25 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 8.26 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 8.27 + // previous versions are linked together through the InstanceKlass 8.28 + for (InstanceKlass* pv_node = _previous_versions; 8.29 + pv_node != NULL; 8.30 + pv_node = pv_node->previous_versions()) { 8.31 if (!have_pv) 8.32 st->print(BULLET"previous version: "); 8.33 have_pv = true; 8.34 - pv_node->prev_constant_pool()->print_value_on(st); 8.35 + pv_node->constants()->print_value_on(st); 8.36 } 8.37 if (have_pv) st->cr(); 8.38 - } // pvw is cleaned up 8.39 + } 8.40 8.41 if (generic_signature() != NULL) { 8.42 st->print(BULLET"generic signature: "); 8.43 @@ -3610,205 +3601,126 @@ 8.44 // RedefineClasses() support for previous versions: 8.45 8.46 // Purge previous versions 8.47 -static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) { 8.48 +void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { 8.49 if (ik->previous_versions() != NULL) { 8.50 // This klass has previous versions so see what we can cleanup 8.51 // while it is safe to do so. 8.52 8.53 int deleted_count = 0; // leave debugging breadcrumbs 8.54 int live_count = 0; 8.55 - ClassLoaderData* loader_data = ik->class_loader_data() == NULL ? 8.56 - ClassLoaderData::the_null_class_loader_data() : 8.57 - ik->class_loader_data(); 8.58 + ClassLoaderData* loader_data = ik->class_loader_data(); 8.59 + assert(loader_data != NULL, "should never be null"); 8.60 8.61 // RC_TRACE macro has an embedded ResourceMark 8.62 - RC_TRACE(0x00000200, ("purge: %s: previous version length=%d", 8.63 - ik->external_name(), ik->previous_versions()->length())); 8.64 - 8.65 - for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) { 8.66 - // check the previous versions array 8.67 - PreviousVersionNode * pv_node = ik->previous_versions()->at(i); 8.68 - ConstantPool* cp_ref = pv_node->prev_constant_pool(); 8.69 - assert(cp_ref != NULL, "cp ref was unexpectedly cleared"); 8.70 - 8.71 - ConstantPool* pvcp = cp_ref; 8.72 + RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name())); 8.73 + 8.74 + // previous versions are linked together through the InstanceKlass 8.75 + InstanceKlass* pv_node = ik->previous_versions(); 8.76 + InstanceKlass* last = ik; 8.77 + int version = 0; 8.78 + 8.79 + // check the previous versions list 8.80 + for (; pv_node != NULL; ) { 8.81 + 8.82 + ConstantPool* pvcp = pv_node->constants(); 8.83 + assert(pvcp != NULL, "cp ref was unexpectedly cleared"); 8.84 + 8.85 + 8.86 if (!pvcp->on_stack()) { 8.87 // If the constant pool isn't on stack, none of the methods 8.88 - // are executing. Delete all the methods, the constant pool and 8.89 - // and this previous version node. 8.90 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 8.91 - if (method_refs != NULL) { 8.92 - for (int j = method_refs->length() - 1; j >= 0; j--) { 8.93 - Method* method = method_refs->at(j); 8.94 - assert(method != NULL, "method ref was unexpectedly cleared"); 8.95 - method_refs->remove_at(j); 8.96 - // method will be freed with associated class. 8.97 - } 8.98 - } 8.99 - // Remove the constant pool 8.100 - delete pv_node; 8.101 - // Since we are traversing the array backwards, we don't have to 8.102 - // do anything special with the index. 8.103 - ik->previous_versions()->remove_at(i); 8.104 + // are executing. Unlink this previous_version. 8.105 + // The previous version InstanceKlass is on the ClassLoaderData deallocate list 8.106 + // so will be deallocated during the next phase of class unloading. 8.107 + pv_node = pv_node->previous_versions(); 8.108 + last->link_previous_versions(pv_node); 8.109 deleted_count++; 8.110 + version++; 8.111 continue; 8.112 } else { 8.113 - RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i)); 8.114 + RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive", 8.115 + pv_node)); 8.116 assert(pvcp->pool_holder() != NULL, "Constant pool with no holder"); 8.117 guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack"); 8.118 live_count++; 8.119 } 8.120 8.121 - // At least one method is live in this previous version, clean out 8.122 - // the others or mark them as obsolete. 8.123 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 8.124 + // At least one method is live in this previous version so clean its MethodData. 8.125 + // Reset dead EMCP methods not to get breakpoints. 8.126 + // All methods are deallocated when all of the methods for this class are no 8.127 + // longer running. 8.128 + Array<Method*>* method_refs = pv_node->methods(); 8.129 if (method_refs != NULL) { 8.130 RC_TRACE(0x00000200, ("purge: previous methods length=%d", 8.131 method_refs->length())); 8.132 - for (int j = method_refs->length() - 1; j >= 0; j--) { 8.133 + for (int j = 0; j < method_refs->length(); j++) { 8.134 Method* method = method_refs->at(j); 8.135 - assert(method != NULL, "method ref was unexpectedly cleared"); 8.136 - 8.137 - // Remove the emcp method if it's not executing 8.138 - // If it's been made obsolete by a redefinition of a non-emcp 8.139 - // method, mark it as obsolete but leave it to clean up later. 8.140 + 8.141 if (!method->on_stack()) { 8.142 - method_refs->remove_at(j); 8.143 - } else if (emcp_method_count == 0) { 8.144 - method->set_is_obsolete(); 8.145 + // no breakpoints for non-running methods 8.146 + if (method->is_running_emcp()) { 8.147 + method->set_running_emcp(false); 8.148 + } 8.149 } else { 8.150 + assert (method->is_obsolete() || method->is_running_emcp(), 8.151 + "emcp method cannot run after emcp bit is cleared"); 8.152 // RC_TRACE macro has an embedded ResourceMark 8.153 RC_TRACE(0x00000200, 8.154 ("purge: %s(%s): prev method @%d in version @%d is alive", 8.155 method->name()->as_C_string(), 8.156 - method->signature()->as_C_string(), j, i)); 8.157 + method->signature()->as_C_string(), j, version)); 8.158 + if (method->method_data() != NULL) { 8.159 + // Clean out any weak method links for running methods 8.160 + // (also should include not EMCP methods) 8.161 + method->method_data()->clean_weak_method_links(); 8.162 + } 8.163 } 8.164 } 8.165 } 8.166 + // next previous version 8.167 + last = pv_node; 8.168 + pv_node = pv_node->previous_versions(); 8.169 + version++; 8.170 } 8.171 - assert(ik->previous_versions()->length() == live_count, "sanity check"); 8.172 RC_TRACE(0x00000200, 8.173 ("purge: previous version stats: live=%d, deleted=%d", live_count, 8.174 deleted_count)); 8.175 } 8.176 + 8.177 + // Clean MethodData of this class's methods so they don't refer to 8.178 + // old methods that are no longer running. 8.179 + Array<Method*>* methods = ik->methods(); 8.180 + int num_methods = methods->length(); 8.181 + for (int index2 = 0; index2 < num_methods; ++index2) { 8.182 + if (methods->at(index2)->method_data() != NULL) { 8.183 + methods->at(index2)->method_data()->clean_weak_method_links(); 8.184 + } 8.185 + } 8.186 } 8.187 8.188 -// External interface for use during class unloading. 8.189 -void InstanceKlass::purge_previous_versions(InstanceKlass* ik) { 8.190 - // Call with >0 emcp methods since they are not currently being redefined. 8.191 - purge_previous_versions_internal(ik, 1); 8.192 -} 8.193 - 8.194 - 8.195 -// Potentially add an information node that contains pointers to the 8.196 -// interesting parts of the previous version of the_class. 8.197 -// This is also where we clean out any unused references. 8.198 -// Note that while we delete nodes from the _previous_versions 8.199 -// array, we never delete the array itself until the klass is 8.200 -// unloaded. The has_been_redefined() query depends on that fact. 8.201 -// 8.202 -void InstanceKlass::add_previous_version(instanceKlassHandle ikh, 8.203 - BitMap* emcp_methods, int emcp_method_count) { 8.204 - assert(Thread::current()->is_VM_thread(), 8.205 - "only VMThread can add previous versions"); 8.206 - 8.207 - if (_previous_versions == NULL) { 8.208 - // This is the first previous version so make some space. 8.209 - // Start with 2 elements under the assumption that the class 8.210 - // won't be redefined much. 8.211 - _previous_versions = new (ResourceObj::C_HEAP, mtClass) 8.212 - GrowableArray<PreviousVersionNode *>(2, true); 8.213 - } 8.214 - 8.215 - ConstantPool* cp_ref = ikh->constants(); 8.216 - 8.217 - // RC_TRACE macro has an embedded ResourceMark 8.218 - RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d " 8.219 - "on_stack=%d", 8.220 - ikh->external_name(), _previous_versions->length(), emcp_method_count, 8.221 - cp_ref->on_stack())); 8.222 - 8.223 - // If the constant pool for this previous version of the class 8.224 - // is not marked as being on the stack, then none of the methods 8.225 - // in this previous version of the class are on the stack so 8.226 - // we don't need to create a new PreviousVersionNode. However, 8.227 - // we still need to examine older previous versions below. 8.228 - Array<Method*>* old_methods = ikh->methods(); 8.229 - 8.230 - if (cp_ref->on_stack()) { 8.231 - PreviousVersionNode * pv_node = NULL; 8.232 - if (emcp_method_count == 0) { 8.233 - // non-shared ConstantPool gets a reference 8.234 - pv_node = new PreviousVersionNode(cp_ref, NULL); 8.235 - RC_TRACE(0x00000400, 8.236 - ("add: all methods are obsolete; flushing any EMCP refs")); 8.237 - } else { 8.238 - int local_count = 0; 8.239 - GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass) 8.240 - GrowableArray<Method*>(emcp_method_count, true); 8.241 - for (int i = 0; i < old_methods->length(); i++) { 8.242 - if (emcp_methods->at(i)) { 8.243 - // this old method is EMCP. Save it only if it's on the stack 8.244 - Method* old_method = old_methods->at(i); 8.245 - if (old_method->on_stack()) { 8.246 - method_refs->append(old_method); 8.247 - } 8.248 - if (++local_count >= emcp_method_count) { 8.249 - // no more EMCP methods so bail out now 8.250 - break; 8.251 - } 8.252 - } 8.253 - } 8.254 - // non-shared ConstantPool gets a reference 8.255 - pv_node = new PreviousVersionNode(cp_ref, method_refs); 8.256 - } 8.257 - // append new previous version. 8.258 - _previous_versions->append(pv_node); 8.259 - } 8.260 - 8.261 - // Since the caller is the VMThread and we are at a safepoint, this 8.262 - // is a good time to clear out unused references. 8.263 - 8.264 - RC_TRACE(0x00000400, ("add: previous version length=%d", 8.265 - _previous_versions->length())); 8.266 - 8.267 - // Purge previous versions not executing on the stack 8.268 - purge_previous_versions_internal(this, emcp_method_count); 8.269 - 8.270 +void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods, 8.271 + int emcp_method_count) { 8.272 int obsolete_method_count = old_methods->length() - emcp_method_count; 8.273 8.274 if (emcp_method_count != 0 && obsolete_method_count != 0 && 8.275 - _previous_versions->length() > 0) { 8.276 + _previous_versions != NULL) { 8.277 // We have a mix of obsolete and EMCP methods so we have to 8.278 // clear out any matching EMCP method entries the hard way. 8.279 int local_count = 0; 8.280 for (int i = 0; i < old_methods->length(); i++) { 8.281 - if (!emcp_methods->at(i)) { 8.282 + Method* old_method = old_methods->at(i); 8.283 + if (old_method->is_obsolete()) { 8.284 // only obsolete methods are interesting 8.285 - Method* old_method = old_methods->at(i); 8.286 Symbol* m_name = old_method->name(); 8.287 Symbol* m_signature = old_method->signature(); 8.288 8.289 - // we might not have added the last entry 8.290 - for (int j = _previous_versions->length() - 1; j >= 0; j--) { 8.291 - // check the previous versions array for non executing obsolete methods 8.292 - PreviousVersionNode * pv_node = _previous_versions->at(j); 8.293 - 8.294 - GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods(); 8.295 - if (method_refs == NULL) { 8.296 - // We have run into a PreviousVersion generation where 8.297 - // all methods were made obsolete during that generation's 8.298 - // RedefineClasses() operation. At the time of that 8.299 - // operation, all EMCP methods were flushed so we don't 8.300 - // have to go back any further. 8.301 - // 8.302 - // A NULL method_refs is different than an empty method_refs. 8.303 - // We cannot infer any optimizations about older generations 8.304 - // from an empty method_refs for the current generation. 8.305 - break; 8.306 - } 8.307 - 8.308 - for (int k = method_refs->length() - 1; k >= 0; k--) { 8.309 + // previous versions are linked together through the InstanceKlass 8.310 + int j = 0; 8.311 + for (InstanceKlass* prev_version = _previous_versions; 8.312 + prev_version != NULL; 8.313 + prev_version = prev_version->previous_versions(), j++) { 8.314 + 8.315 + Array<Method*>* method_refs = prev_version->methods(); 8.316 + for (int k = 0; k < method_refs->length(); k++) { 8.317 Method* method = method_refs->at(k); 8.318 8.319 if (!method->is_obsolete() && 8.320 @@ -3816,14 +3728,11 @@ 8.321 method->signature() == m_signature) { 8.322 // The current RedefineClasses() call has made all EMCP 8.323 // versions of this method obsolete so mark it as obsolete 8.324 - // and remove the reference. 8.325 RC_TRACE(0x00000400, 8.326 ("add: %s(%s): flush obsolete method @%d in version @%d", 8.327 m_name->as_C_string(), m_signature->as_C_string(), k, j)); 8.328 8.329 method->set_is_obsolete(); 8.330 - // Leave obsolete methods on the previous version list to 8.331 - // clean up later. 8.332 break; 8.333 } 8.334 } 8.335 @@ -3831,9 +3740,9 @@ 8.336 // The previous loop may not find a matching EMCP method, but 8.337 // that doesn't mean that we can optimize and not go any 8.338 // further back in the PreviousVersion generations. The EMCP 8.339 - // method for this generation could have already been deleted, 8.340 + // method for this generation could have already been made obsolete, 8.341 // but there still may be an older EMCP method that has not 8.342 - // been deleted. 8.343 + // been made obsolete. 8.344 } 8.345 8.346 if (++local_count >= obsolete_method_count) { 8.347 @@ -3843,30 +3752,67 @@ 8.348 } 8.349 } 8.350 } 8.351 -} // end add_previous_version() 8.352 - 8.353 - 8.354 -// Determine if InstanceKlass has a previous version. 8.355 -bool InstanceKlass::has_previous_version() const { 8.356 - return (_previous_versions != NULL && _previous_versions->length() > 0); 8.357 -} // end has_previous_version() 8.358 - 8.359 - 8.360 -InstanceKlass* InstanceKlass::get_klass_version(int version) { 8.361 - if (constants()->version() == version) { 8.362 - return this; 8.363 +} 8.364 + 8.365 +// Save the scratch_class as the previous version if any of the methods are running. 8.366 +// The previous_versions are used to set breakpoints in EMCP methods and they are 8.367 +// also used to clean MethodData links to redefined methods that are no longer running. 8.368 +void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class, 8.369 + int emcp_method_count) { 8.370 + assert(Thread::current()->is_VM_thread(), 8.371 + "only VMThread can add previous versions"); 8.372 + 8.373 + // RC_TRACE macro has an embedded ResourceMark 8.374 + RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d", 8.375 + scratch_class->external_name(), emcp_method_count)); 8.376 + 8.377 + // Clean out old previous versions 8.378 + purge_previous_versions(this); 8.379 + 8.380 + // Mark newly obsolete methods in remaining previous versions. An EMCP method from 8.381 + // a previous redefinition may be made obsolete by this redefinition. 8.382 + Array<Method*>* old_methods = scratch_class->methods(); 8.383 + mark_newly_obsolete_methods(old_methods, emcp_method_count); 8.384 + 8.385 + // If the constant pool for this previous version of the class 8.386 + // is not marked as being on the stack, then none of the methods 8.387 + // in this previous version of the class are on the stack so 8.388 + // we don't need to add this as a previous version. 8.389 + ConstantPool* cp_ref = scratch_class->constants(); 8.390 + if (!cp_ref->on_stack()) { 8.391 + RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running")); 8.392 + return; 8.393 } 8.394 - PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); 8.395 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 8.396 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 8.397 - ConstantPool* prev_cp = pv_node->prev_constant_pool(); 8.398 - if (prev_cp->version() == version) { 8.399 - return prev_cp->pool_holder(); 8.400 + 8.401 + if (emcp_method_count != 0) { 8.402 + // At least one method is still running, check for EMCP methods 8.403 + for (int i = 0; i < old_methods->length(); i++) { 8.404 + Method* old_method = old_methods->at(i); 8.405 + if (!old_method->is_obsolete() && old_method->on_stack()) { 8.406 + // if EMCP method (not obsolete) is on the stack, mark as EMCP so that 8.407 + // we can add breakpoints for it. 8.408 + 8.409 + // We set the method->on_stack bit during safepoints for class redefinition and 8.410 + // class unloading and use this bit to set the is_running_emcp bit. 8.411 + // After the safepoint, the on_stack bit is cleared and the running emcp 8.412 + // method may exit. If so, we would set a breakpoint in a method that 8.413 + // is never reached, but this won't be noticeable to the programmer. 8.414 + old_method->set_running_emcp(true); 8.415 + RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT, 8.416 + old_method->name_and_sig_as_C_string(), old_method)); 8.417 + } else if (!old_method->is_obsolete()) { 8.418 + RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT, 8.419 + old_method->name_and_sig_as_C_string(), old_method)); 8.420 + } 8.421 } 8.422 } 8.423 - return NULL; // None found 8.424 -} 8.425 - 8.426 + 8.427 + // Add previous version if any methods are still running. 8.428 + RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack")); 8.429 + assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version"); 8.430 + scratch_class->link_previous_versions(previous_versions()); 8.431 + link_previous_versions(scratch_class()); 8.432 +} // end add_previous_version() 8.433 8.434 Method* InstanceKlass::method_with_idnum(int idnum) { 8.435 Method* m = NULL; 8.436 @@ -3924,61 +3870,3 @@ 8.437 unsigned char * InstanceKlass::get_cached_class_file_bytes() { 8.438 return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file); 8.439 } 8.440 - 8.441 - 8.442 -// Construct a PreviousVersionNode entry for the array hung off 8.443 -// the InstanceKlass. 8.444 -PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, 8.445 - GrowableArray<Method*>* prev_EMCP_methods) { 8.446 - 8.447 - _prev_constant_pool = prev_constant_pool; 8.448 - _prev_EMCP_methods = prev_EMCP_methods; 8.449 -} 8.450 - 8.451 - 8.452 -// Destroy a PreviousVersionNode 8.453 -PreviousVersionNode::~PreviousVersionNode() { 8.454 - if (_prev_constant_pool != NULL) { 8.455 - _prev_constant_pool = NULL; 8.456 - } 8.457 - 8.458 - if (_prev_EMCP_methods != NULL) { 8.459 - delete _prev_EMCP_methods; 8.460 - } 8.461 -} 8.462 - 8.463 -// Construct a helper for walking the previous versions array 8.464 -PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { 8.465 - _thread = thread; 8.466 - _previous_versions = ik->previous_versions(); 8.467 - _current_index = 0; 8.468 - _current_p = NULL; 8.469 - _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); 8.470 -} 8.471 - 8.472 - 8.473 -// Return the interesting information for the next previous version 8.474 -// of the klass. Returns NULL if there are no more previous versions. 8.475 -PreviousVersionNode* PreviousVersionWalker::next_previous_version() { 8.476 - if (_previous_versions == NULL) { 8.477 - // no previous versions so nothing to return 8.478 - return NULL; 8.479 - } 8.480 - 8.481 - _current_p = NULL; // reset to NULL 8.482 - _current_constant_pool_handle = NULL; 8.483 - 8.484 - int length = _previous_versions->length(); 8.485 - 8.486 - while (_current_index < length) { 8.487 - PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); 8.488 - 8.489 - // Save a handle to the constant pool for this previous version, 8.490 - // which keeps all the methods from being deallocated. 8.491 - _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); 8.492 - _current_p = pv_node; 8.493 - return pv_node; 8.494 - } 8.495 - 8.496 - return NULL; 8.497 -} // end next_previous_version()
9.1 --- a/src/share/vm/oops/instanceKlass.hpp Mon Mar 19 12:12:48 2018 -0700 9.2 +++ b/src/share/vm/oops/instanceKlass.hpp Mon Mar 19 13:23:53 2018 -0700 9.3 @@ -88,7 +88,6 @@ 9.4 class fieldDescriptor; 9.5 class DepChange; 9.6 class nmethodBucket; 9.7 -class PreviousVersionNode; 9.8 class JvmtiCachedClassFieldMap; 9.9 class MemberNameTable; 9.10 9.11 @@ -235,7 +234,8 @@ 9.12 _misc_is_anonymous = 1 << 3, // has embedded _host_klass field 9.13 _misc_is_contended = 1 << 4, // marked with contended annotation 9.14 _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods 9.15 - _misc_declares_default_methods = 1 << 6 // directly declares default methods (any access) 9.16 + _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access) 9.17 + _misc_has_been_redefined = 1 << 7 // class has been redefined 9.18 }; 9.19 u2 _misc_flags; 9.20 u2 _minor_version; // minor version number of class file 9.21 @@ -250,9 +250,8 @@ 9.22 nmethodBucket* _dependencies; // list of dependent nmethods 9.23 nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class 9.24 BreakpointInfo* _breakpoints; // bpt lists, managed by Method* 9.25 - // Array of interesting part(s) of the previous version(s) of this 9.26 - // InstanceKlass. See PreviousVersionWalker below. 9.27 - GrowableArray<PreviousVersionNode *>* _previous_versions; 9.28 + // Linked instanceKlasses of previous versions 9.29 + InstanceKlass* _previous_versions; 9.30 // JVMTI fields can be moved to their own structure - see 6315920 9.31 // JVMTI: cached class file, before retransformable agent modified it in CFLH 9.32 JvmtiCachedClassFileData* _cached_class_file; 9.33 @@ -669,21 +668,31 @@ 9.34 } 9.35 9.36 // RedefineClasses() support for previous versions: 9.37 - void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods, 9.38 - int emcp_method_count); 9.39 - // If the _previous_versions array is non-NULL, then this klass 9.40 - // has been redefined at least once even if we aren't currently 9.41 - // tracking a previous version. 9.42 - bool has_been_redefined() const { return _previous_versions != NULL; } 9.43 - bool has_previous_version() const; 9.44 + void add_previous_version(instanceKlassHandle ikh, int emcp_method_count); 9.45 + 9.46 + InstanceKlass* previous_versions() const { return _previous_versions; } 9.47 + 9.48 + bool has_been_redefined() const { 9.49 + return (_misc_flags & _misc_has_been_redefined) != 0; 9.50 + } 9.51 + void set_has_been_redefined() { 9.52 + _misc_flags |= _misc_has_been_redefined; 9.53 + } 9.54 + 9.55 void init_previous_versions() { 9.56 _previous_versions = NULL; 9.57 } 9.58 - GrowableArray<PreviousVersionNode *>* previous_versions() const { 9.59 - return _previous_versions; 9.60 + 9.61 + 9.62 + InstanceKlass* get_klass_version(int version) { 9.63 + for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) { 9.64 + if (ik->constants()->version() == version) { 9.65 + return ik; 9.66 + } 9.67 + } 9.68 + return NULL; 9.69 } 9.70 9.71 - InstanceKlass* get_klass_version(int version); 9.72 static void purge_previous_versions(InstanceKlass* ik); 9.73 9.74 // JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation 9.75 @@ -1124,6 +1133,10 @@ 9.76 9.77 // Free CHeap allocated fields. 9.78 void release_C_heap_structures(); 9.79 + 9.80 + // RedefineClasses support 9.81 + void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; } 9.82 + void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count); 9.83 public: 9.84 // CDS support - remove and restore oops from metadata. Oops are not shared. 9.85 virtual void remove_unshareable_info(); 9.86 @@ -1222,62 +1235,6 @@ 9.87 }; 9.88 9.89 9.90 -// If breakpoints are more numerous than just JVMTI breakpoints, 9.91 -// consider compressing this data structure. 9.92 -// It is currently a simple linked list defined in method.hpp. 9.93 - 9.94 -class BreakpointInfo; 9.95 - 9.96 - 9.97 -// A collection point for interesting information about the previous 9.98 -// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes 9.99 -// is attached to the InstanceKlass as needed. See PreviousVersionWalker below. 9.100 -class PreviousVersionNode : public CHeapObj<mtClass> { 9.101 - private: 9.102 - ConstantPool* _prev_constant_pool; 9.103 - 9.104 - // If the previous version of the InstanceKlass doesn't have any 9.105 - // EMCP methods, then _prev_EMCP_methods will be NULL. If all the 9.106 - // EMCP methods have been collected, then _prev_EMCP_methods can 9.107 - // have a length of zero. 9.108 - GrowableArray<Method*>* _prev_EMCP_methods; 9.109 - 9.110 -public: 9.111 - PreviousVersionNode(ConstantPool* prev_constant_pool, 9.112 - GrowableArray<Method*>* prev_EMCP_methods); 9.113 - ~PreviousVersionNode(); 9.114 - ConstantPool* prev_constant_pool() const { 9.115 - return _prev_constant_pool; 9.116 - } 9.117 - GrowableArray<Method*>* prev_EMCP_methods() const { 9.118 - return _prev_EMCP_methods; 9.119 - } 9.120 -}; 9.121 - 9.122 - 9.123 -// Helper object for walking previous versions. 9.124 -class PreviousVersionWalker : public StackObj { 9.125 - private: 9.126 - Thread* _thread; 9.127 - GrowableArray<PreviousVersionNode *>* _previous_versions; 9.128 - int _current_index; 9.129 - 9.130 - // A pointer to the current node object so we can handle the deletes. 9.131 - PreviousVersionNode* _current_p; 9.132 - 9.133 - // The constant pool handle keeps all the methods in this class from being 9.134 - // deallocated from the metaspace during class unloading. 9.135 - constantPoolHandle _current_constant_pool_handle; 9.136 - 9.137 - public: 9.138 - PreviousVersionWalker(Thread* thread, InstanceKlass *ik); 9.139 - 9.140 - // Return the interesting information for the next previous version 9.141 - // of the klass. Returns NULL if there are no more previous versions. 9.142 - PreviousVersionNode* next_previous_version(); 9.143 -}; 9.144 - 9.145 - 9.146 // 9.147 // nmethodBucket is used to record dependent nmethods for 9.148 // deoptimization. nmethod dependencies are actually <klass, method>
10.1 --- a/src/share/vm/oops/klass.cpp Mon Mar 19 12:12:48 2018 -0700 10.2 +++ b/src/share/vm/oops/klass.cpp Mon Mar 19 13:23:53 2018 -0700 10.3 @@ -468,6 +468,12 @@ 10.4 if (clean_alive_klasses && current->oop_is_instance()) { 10.5 InstanceKlass* ik = InstanceKlass::cast(current); 10.6 ik->clean_weak_instanceklass_links(is_alive); 10.7 + 10.8 + // JVMTI RedefineClasses creates previous versions that are not in 10.9 + // the class hierarchy, so process them here. 10.10 + while ((ik = ik->previous_versions()) != NULL) { 10.11 + ik->clean_weak_instanceklass_links(is_alive); 10.12 + } 10.13 } 10.14 } 10.15 }
11.1 --- a/src/share/vm/oops/method.cpp Mon Mar 19 12:12:48 2018 -0700 11.2 +++ b/src/share/vm/oops/method.cpp Mon Mar 19 13:23:53 2018 -0700 11.3 @@ -91,6 +91,7 @@ 11.4 set_hidden(false); 11.5 set_dont_inline(false); 11.6 set_has_injected_profile(false); 11.7 + set_running_emcp(false); 11.8 set_method_data(NULL); 11.9 clear_method_counters(); 11.10 set_vtable_index(Method::garbage_vtable_index);
12.1 --- a/src/share/vm/oops/method.hpp Mon Mar 19 12:12:48 2018 -0700 12.2 +++ b/src/share/vm/oops/method.hpp Mon Mar 19 13:23:53 2018 -0700 12.3 @@ -111,6 +111,7 @@ 12.4 _caller_sensitive : 1, 12.5 _force_inline : 1, 12.6 _hidden : 1, 12.7 + _running_emcp : 1, 12.8 _dont_inline : 1, 12.9 _has_injected_profile : 1, 12.10 : 2; 12.11 @@ -712,6 +713,21 @@ 12.12 void set_is_obsolete() { _access_flags.set_is_obsolete(); } 12.13 bool is_deleted() const { return access_flags().is_deleted(); } 12.14 void set_is_deleted() { _access_flags.set_is_deleted(); } 12.15 + 12.16 + bool is_running_emcp() const { 12.17 + // EMCP methods are old but not obsolete or deleted. Equivalent 12.18 + // Modulo Constant Pool means the method is equivalent except 12.19 + // the constant pool and instructions that access the constant 12.20 + // pool might be different. 12.21 + // If a breakpoint is set in a redefined method, its EMCP methods that are 12.22 + // still running must have a breakpoint also. 12.23 + return _running_emcp; 12.24 + } 12.25 + 12.26 + void set_running_emcp(bool x) { 12.27 + _running_emcp = x; 12.28 + } 12.29 + 12.30 bool on_stack() const { return access_flags().on_stack(); } 12.31 void set_on_stack(const bool value); 12.32
13.1 --- a/src/share/vm/oops/methodData.cpp Mon Mar 19 12:12:48 2018 -0700 13.2 +++ b/src/share/vm/oops/methodData.cpp Mon Mar 19 13:23:53 2018 -0700 13.3 @@ -1559,9 +1559,35 @@ 13.4 } 13.5 } 13.6 13.7 -// Remove SpeculativeTrapData entries that reference an unloaded 13.8 -// method 13.9 -void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { 13.10 +class CleanExtraDataClosure : public StackObj { 13.11 +public: 13.12 + virtual bool is_live(Method* m) = 0; 13.13 +}; 13.14 + 13.15 +// Check for entries that reference an unloaded method 13.16 +class CleanExtraDataKlassClosure : public CleanExtraDataClosure { 13.17 +private: 13.18 + BoolObjectClosure* _is_alive; 13.19 +public: 13.20 + CleanExtraDataKlassClosure(BoolObjectClosure* is_alive) : _is_alive(is_alive) {} 13.21 + bool is_live(Method* m) { 13.22 + return m->method_holder()->is_loader_alive(_is_alive); 13.23 + } 13.24 +}; 13.25 + 13.26 +// Check for entries that reference a redefined method 13.27 +class CleanExtraDataMethodClosure : public CleanExtraDataClosure { 13.28 +public: 13.29 + CleanExtraDataMethodClosure() {} 13.30 + bool is_live(Method* m) { 13.31 + return m->on_stack(); 13.32 + } 13.33 +}; 13.34 + 13.35 + 13.36 +// Remove SpeculativeTrapData entries that reference an unloaded or 13.37 +// redefined method 13.38 +void MethodData::clean_extra_data(CleanExtraDataClosure* cl) { 13.39 DataLayout* dp = extra_data_base(); 13.40 DataLayout* end = extra_data_limit(); 13.41 13.42 @@ -1572,7 +1598,7 @@ 13.43 SpeculativeTrapData* data = new SpeculativeTrapData(dp); 13.44 Method* m = data->method(); 13.45 assert(m != NULL, "should have a method"); 13.46 - if (!m->method_holder()->is_loader_alive(is_alive)) { 13.47 + if (!cl->is_live(m)) { 13.48 // "shift" accumulates the number of cells for dead 13.49 // SpeculativeTrapData entries that have been seen so 13.50 // far. Following entries must be shifted left by that many 13.51 @@ -1603,9 +1629,9 @@ 13.52 } 13.53 } 13.54 13.55 -// Verify there's no unloaded method referenced by a 13.56 +// Verify there's no unloaded or redefined method referenced by a 13.57 // SpeculativeTrapData entry 13.58 -void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { 13.59 +void MethodData::verify_extra_data_clean(CleanExtraDataClosure* cl) { 13.60 #ifdef ASSERT 13.61 DataLayout* dp = extra_data_base(); 13.62 DataLayout* end = extra_data_limit(); 13.63 @@ -1615,7 +1641,7 @@ 13.64 case DataLayout::speculative_trap_data_tag: { 13.65 SpeculativeTrapData* data = new SpeculativeTrapData(dp); 13.66 Method* m = data->method(); 13.67 - assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); 13.68 + assert(m != NULL && cl->is_live(m), "Method should exist"); 13.69 break; 13.70 } 13.71 case DataLayout::bit_data_tag: 13.72 @@ -1641,6 +1667,19 @@ 13.73 parameters->clean_weak_klass_links(is_alive); 13.74 } 13.75 13.76 - clean_extra_data(is_alive); 13.77 - verify_extra_data_clean(is_alive); 13.78 + CleanExtraDataKlassClosure cl(is_alive); 13.79 + clean_extra_data(&cl); 13.80 + verify_extra_data_clean(&cl); 13.81 } 13.82 + 13.83 +void MethodData::clean_weak_method_links() { 13.84 + for (ProfileData* data = first_data(); 13.85 + is_valid(data); 13.86 + data = next_data(data)) { 13.87 + data->clean_weak_method_links(); 13.88 + } 13.89 + 13.90 + CleanExtraDataMethodClosure cl; 13.91 + clean_extra_data(&cl); 13.92 + verify_extra_data_clean(&cl); 13.93 +}
14.1 --- a/src/share/vm/oops/methodData.hpp Mon Mar 19 12:12:48 2018 -0700 14.2 +++ b/src/share/vm/oops/methodData.hpp Mon Mar 19 13:23:53 2018 -0700 14.3 @@ -251,6 +251,9 @@ 14.4 14.5 // GC support 14.6 void clean_weak_klass_links(BoolObjectClosure* cl); 14.7 + 14.8 + // Redefinition support 14.9 + void clean_weak_method_links(); 14.10 }; 14.11 14.12 14.13 @@ -508,6 +511,9 @@ 14.14 // GC support 14.15 virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {} 14.16 14.17 + // Redefinition support 14.18 + virtual void clean_weak_method_links() {} 14.19 + 14.20 // CI translation: ProfileData can represent both MethodDataOop data 14.21 // as well as CIMethodData data. This function is provided for translating 14.22 // an oop in a ProfileData to the ci equivalent. Generally speaking, 14.23 @@ -2030,6 +2036,7 @@ 14.24 // 14.25 14.26 CC_INTERP_ONLY(class BytecodeInterpreter;) 14.27 +class CleanExtraDataClosure; 14.28 14.29 class MethodData : public Metadata { 14.30 friend class VMStructs; 14.31 @@ -2183,9 +2190,9 @@ 14.32 static bool profile_parameters_jsr292_only(); 14.33 static bool profile_all_parameters(); 14.34 14.35 - void clean_extra_data(BoolObjectClosure* is_alive); 14.36 + void clean_extra_data(CleanExtraDataClosure* cl); 14.37 void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); 14.38 - void verify_extra_data_clean(BoolObjectClosure* is_alive); 14.39 + void verify_extra_data_clean(CleanExtraDataClosure* cl); 14.40 14.41 public: 14.42 static int header_size() { 14.43 @@ -2477,6 +2484,8 @@ 14.44 static bool profile_return_jsr292_only(); 14.45 14.46 void clean_method_data(BoolObjectClosure* is_alive); 14.47 + 14.48 + void clean_weak_method_links(); 14.49 }; 14.50 14.51 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
15.1 --- a/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Mon Mar 19 12:12:48 2018 -0700 15.2 +++ b/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Mon Mar 19 13:23:53 2018 -0700 15.3 @@ -1,5 +1,5 @@ 15.4 /* 15.5 - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 15.6 + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. 15.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 15.8 * 15.9 * This code is free software; you can redistribute it and/or modify it 15.10 @@ -27,6 +27,9 @@ 15.11 #include "memory/universe.inline.hpp" 15.12 #include "prims/jvmtiGetLoadedClasses.hpp" 15.13 #include "runtime/thread.hpp" 15.14 +#if INCLUDE_ALL_GCS 15.15 +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 15.16 +#endif 15.17 15.18 15.19 // The closure for GetLoadedClasses 15.20 @@ -35,6 +38,20 @@ 15.21 Stack<jclass, mtInternal> _classStack; 15.22 JvmtiEnv* _env; 15.23 15.24 +// Tell the GC to keep this klass alive 15.25 +static void ensure_klass_alive(oop o) { 15.26 + // A klass that was previously considered dead can be looked up in the 15.27 + // CLD/SD, and its _java_mirror or _class_loader can be stored in a root 15.28 + // or a reachable object making it alive again. The SATB part of G1 needs 15.29 + // to get notified about this potential resurrection, otherwise the marking 15.30 + // might not find the object. 15.31 +#if INCLUDE_ALL_GCS 15.32 + if (UseG1GC && o != NULL) { 15.33 + G1SATBCardTableModRefBS::enqueue(o); 15.34 + } 15.35 +#endif 15.36 +} 15.37 + 15.38 public: 15.39 LoadedClassesClosure(JvmtiEnv* env) { 15.40 _env = env; 15.41 @@ -43,6 +60,7 @@ 15.42 void do_klass(Klass* k) { 15.43 // Collect all jclasses 15.44 _classStack.push((jclass) _env->jni_reference(k->java_mirror())); 15.45 + ensure_klass_alive(k->java_mirror()); 15.46 } 15.47 15.48 int extract(jclass* result_list) {
16.1 --- a/src/share/vm/prims/jvmtiImpl.cpp Mon Mar 19 12:12:48 2018 -0700 16.2 +++ b/src/share/vm/prims/jvmtiImpl.cpp Mon Mar 19 13:23:53 2018 -0700 16.3 @@ -282,39 +282,22 @@ 16.4 void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { 16.5 ((Method*)_method->*meth_act)(_bci); 16.6 16.7 - // add/remove breakpoint to/from versions of the method that 16.8 - // are EMCP. Directly or transitively obsolete methods are 16.9 - // not saved in the PreviousVersionNodes. 16.10 + // add/remove breakpoint to/from versions of the method that are EMCP. 16.11 Thread *thread = Thread::current(); 16.12 instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder()); 16.13 Symbol* m_name = _method->name(); 16.14 Symbol* m_signature = _method->signature(); 16.15 16.16 // search previous versions if they exist 16.17 - PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh()); 16.18 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 16.19 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 16.20 - GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods(); 16.21 - 16.22 - if (methods == NULL) { 16.23 - // We have run into a PreviousVersion generation where 16.24 - // all methods were made obsolete during that generation's 16.25 - // RedefineClasses() operation. At the time of that 16.26 - // operation, all EMCP methods were flushed so we don't 16.27 - // have to go back any further. 16.28 - // 16.29 - // A NULL methods array is different than an empty methods 16.30 - // array. We cannot infer any optimizations about older 16.31 - // generations from an empty methods array for the current 16.32 - // generation. 16.33 - break; 16.34 - } 16.35 + for (InstanceKlass* pv_node = ikh->previous_versions(); 16.36 + pv_node != NULL; 16.37 + pv_node = pv_node->previous_versions()) { 16.38 + Array<Method*>* methods = pv_node->methods(); 16.39 16.40 for (int i = methods->length() - 1; i >= 0; i--) { 16.41 Method* method = methods->at(i); 16.42 - // obsolete methods that are running are not deleted from 16.43 - // previous version array, but they are skipped here. 16.44 - if (!method->is_obsolete() && 16.45 + // Only set breakpoints in running EMCP methods. 16.46 + if (method->is_running_emcp() && 16.47 method->name() == m_name && 16.48 method->signature() == m_signature) { 16.49 RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
17.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Mar 19 12:12:48 2018 -0700 17.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Mar 19 13:23:53 2018 -0700 17.3 @@ -3435,13 +3435,12 @@ 17.4 } 17.5 17.6 // the previous versions' constant pool caches may need adjustment 17.7 - PreviousVersionWalker pvw(_thread, ik); 17.8 - for (PreviousVersionNode * pv_node = pvw.next_previous_version(); 17.9 - pv_node != NULL; pv_node = pvw.next_previous_version()) { 17.10 - other_cp = pv_node->prev_constant_pool(); 17.11 - cp_cache = other_cp->cache(); 17.12 + for (InstanceKlass* pv_node = ik->previous_versions(); 17.13 + pv_node != NULL; 17.14 + pv_node = pv_node->previous_versions()) { 17.15 + cp_cache = pv_node->constants()->cache(); 17.16 if (cp_cache != NULL) { 17.17 - cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed); 17.18 + cp_cache->adjust_method_entries(pv_node, &trace_name_printed); 17.19 } 17.20 } 17.21 } 17.22 @@ -3461,9 +3460,8 @@ 17.23 } 17.24 } 17.25 17.26 -void VM_RedefineClasses::check_methods_and_mark_as_obsolete( 17.27 - BitMap *emcp_methods, int * emcp_method_count_p) { 17.28 - *emcp_method_count_p = 0; 17.29 +int VM_RedefineClasses::check_methods_and_mark_as_obsolete() { 17.30 + int emcp_method_count = 0; 17.31 int obsolete_count = 0; 17.32 int old_index = 0; 17.33 for (int j = 0; j < _matching_methods_length; ++j, ++old_index) { 17.34 @@ -3537,9 +3535,9 @@ 17.35 // that we get from effectively overwriting the old methods 17.36 // when the new methods are attached to the_class. 17.37 17.38 - // track which methods are EMCP for add_previous_version() call 17.39 - emcp_methods->set_bit(old_index); 17.40 - (*emcp_method_count_p)++; 17.41 + // Count number of methods that are EMCP. The method will be marked 17.42 + // old but not obsolete if it is EMCP. 17.43 + emcp_method_count++; 17.44 17.45 // An EMCP method is _not_ obsolete. An obsolete method has a 17.46 // different jmethodID than the current method. An EMCP method 17.47 @@ -3589,10 +3587,11 @@ 17.48 old_method->name()->as_C_string(), 17.49 old_method->signature()->as_C_string())); 17.50 } 17.51 - assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(), 17.52 + assert((emcp_method_count + obsolete_count) == _old_methods->length(), 17.53 "sanity check"); 17.54 - RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p, 17.55 + RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count, 17.56 obsolete_count)); 17.57 + return emcp_method_count; 17.58 } 17.59 17.60 // This internal class transfers the native function registration from old methods 17.61 @@ -3973,11 +3972,8 @@ 17.62 old_constants->set_pool_holder(scratch_class()); 17.63 #endif 17.64 17.65 - // track which methods are EMCP for add_previous_version() call below 17.66 - BitMap emcp_methods(_old_methods->length()); 17.67 - int emcp_method_count = 0; 17.68 - emcp_methods.clear(); // clears 0..(length() - 1) 17.69 - check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count); 17.70 + // track number of methods that are EMCP for add_previous_version() call below 17.71 + int emcp_method_count = check_methods_and_mark_as_obsolete(); 17.72 transfer_old_native_function_registrations(the_class); 17.73 17.74 // The class file bytes from before any retransformable agents mucked 17.75 @@ -4064,9 +4060,10 @@ 17.76 scratch_class->enclosing_method_method_index()); 17.77 scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx); 17.78 17.79 + the_class->set_has_been_redefined(); 17.80 + 17.81 // keep track of previous versions of this class 17.82 - the_class->add_previous_version(scratch_class, &emcp_methods, 17.83 - emcp_method_count); 17.84 + the_class->add_previous_version(scratch_class, emcp_method_count); 17.85 17.86 RC_TIMER_STOP(_timer_rsc_phase1); 17.87 RC_TIMER_START(_timer_rsc_phase2);
18.1 --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Mon Mar 19 12:12:48 2018 -0700 18.2 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Mon Mar 19 13:23:53 2018 -0700 18.3 @@ -403,14 +403,9 @@ 18.4 // Change jmethodIDs to point to the new methods 18.5 void update_jmethod_ids(); 18.6 18.7 - // In addition to marking methods as obsolete, this routine 18.8 - // records which methods are EMCP (Equivalent Module Constant 18.9 - // Pool) in the emcp_methods BitMap and returns the number of 18.10 - // EMCP methods via emcp_method_count_p. This information is 18.11 - // used when information about the previous version of the_class 18.12 - // is squirreled away. 18.13 - void check_methods_and_mark_as_obsolete(BitMap *emcp_methods, 18.14 - int * emcp_method_count_p); 18.15 + // In addition to marking methods as old and/or obsolete, this routine 18.16 + // counts the number of methods that are EMCP (Equivalent Module Constant Pool). 18.17 + int check_methods_and_mark_as_obsolete(); 18.18 void transfer_old_native_function_registrations(instanceKlassHandle the_class); 18.19 18.20 // Install the redefinition of a class
19.1 --- a/src/share/vm/prims/whitebox.cpp Mon Mar 19 12:12:48 2018 -0700 19.2 +++ b/src/share/vm/prims/whitebox.cpp Mon Mar 19 13:23:53 2018 -0700 19.3 @@ -1,5 +1,5 @@ 19.4 /* 19.5 - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 19.6 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 19.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 19.8 * 19.9 * This code is free software; you can redistribute it and/or modify it 19.10 @@ -158,6 +158,9 @@ 19.11 } 19.12 WB_END 19.13 19.14 +#ifdef LINUX 19.15 +#include "utilities/elfFile.hpp" 19.16 +#endif 19.17 19.18 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { 19.19 return (jlong)Arguments::max_heap_for_compressed_oops(); 19.20 @@ -1010,6 +1013,21 @@ 19.21 } 19.22 } 19.23 19.24 +// Checks that the library libfile has the noexecstack bit set. 19.25 +WB_ENTRY(jboolean, WB_CheckLibSpecifiesNoexecstack(JNIEnv* env, jobject o, jstring libfile)) 19.26 + jboolean ret = false; 19.27 +#ifdef LINUX 19.28 + // Can't be in VM when we call JNI. 19.29 + ThreadToNativeFromVM ttnfv(thread); 19.30 + const char* lf = env->GetStringUTFChars(libfile, NULL); 19.31 + CHECK_JNI_EXCEPTION_(env, 0); 19.32 + ElfFile ef(lf); 19.33 + ret = (jboolean) ef.specifies_noexecstack(); 19.34 + env->ReleaseStringUTFChars(libfile, lf); 19.35 +#endif 19.36 + return ret; 19.37 +WB_END 19.38 + 19.39 #define CC (char*) 19.40 19.41 static JNINativeMethod methods[] = { 19.42 @@ -1121,6 +1139,8 @@ 19.43 (void*)&WB_GetNMethod }, 19.44 {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, 19.45 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, 19.46 + {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z", 19.47 + (void*)&WB_CheckLibSpecifiesNoexecstack}, 19.48 }; 19.49 19.50 #undef CC
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/test/compiler/profiling/spectrapredefineclass/Agent.java Mon Mar 19 13:23:53 2018 -0700 20.3 @@ -0,0 +1,142 @@ 20.4 +/* 20.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 20.7 + * 20.8 + * This code is free software; you can redistribute it and/or modify it 20.9 + * under the terms of the GNU General Public License version 2 only, as 20.10 + * published by the Free Software Foundation. 20.11 + * 20.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 20.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 20.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20.15 + * version 2 for more details (a copy is included in the LICENSE file that 20.16 + * accompanied this code). 20.17 + * 20.18 + * You should have received a copy of the GNU General Public License version 20.19 + * 2 along with this work; if not, write to the Free Software Foundation, 20.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20.21 + * 20.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20.23 + * or visit www.oracle.com if you need additional information or have any 20.24 + * questions. 20.25 + */ 20.26 + 20.27 +import java.security.*; 20.28 +import java.lang.instrument.*; 20.29 +import java.lang.reflect.*; 20.30 +import java.lang.management.ManagementFactory; 20.31 +import com.sun.tools.attach.VirtualMachine; 20.32 + 20.33 +class A { 20.34 + void m() { 20.35 + } 20.36 +} 20.37 + 20.38 +class B extends A { 20.39 + void m() { 20.40 + } 20.41 +} 20.42 + 20.43 +class C extends A { 20.44 + void m() { 20.45 + } 20.46 +} 20.47 + 20.48 +class Test { 20.49 + 20.50 + static public void m() throws Exception { 20.51 + for (int i = 0; i < 20000; i++) { 20.52 + m1(a); 20.53 + } 20.54 + for (int i = 0; i < 4; i++) { 20.55 + m1(b); 20.56 + } 20.57 + } 20.58 + 20.59 + static boolean m1(A a) { 20.60 + boolean res = Agent.m2(a); 20.61 + return res; 20.62 + } 20.63 + 20.64 + static public A a = new A(); 20.65 + static public B b = new B(); 20.66 + static public C c = new C(); 20.67 +} 20.68 + 20.69 +public class Agent implements ClassFileTransformer { 20.70 + 20.71 + 20.72 + static class MemoryChunk { 20.73 + MemoryChunk other; 20.74 + long[] array; 20.75 + MemoryChunk(MemoryChunk other) { 20.76 + other = other; 20.77 + array = new long[1024 * 1024 * 1024]; 20.78 + } 20.79 + } 20.80 + 20.81 + static public boolean m2(A a) { 20.82 + boolean res = false; 20.83 + if (a.getClass() == B.class) { 20.84 + a.m(); 20.85 + } else { 20.86 + res = true; 20.87 + } 20.88 + return res; 20.89 + } 20.90 + 20.91 + static public void main(String[] args) throws Exception { 20.92 + // Create speculative trap entries 20.93 + Test.m(); 20.94 + 20.95 + String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName(); 20.96 + int p = nameOfRunningVM.indexOf('@'); 20.97 + String pid = nameOfRunningVM.substring(0, p); 20.98 + 20.99 + // Make the nmethod go away 20.100 + for (int i = 0; i < 10; i++) { 20.101 + System.gc(); 20.102 + } 20.103 + 20.104 + // Redefine class 20.105 + try { 20.106 + VirtualMachine vm = VirtualMachine.attach(pid); 20.107 + vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", ""); 20.108 + vm.detach(); 20.109 + } catch (Exception e) { 20.110 + throw new RuntimeException(e); 20.111 + } 20.112 + 20.113 + Test.m(); 20.114 + // GC will hit dead method pointer 20.115 + for (int i = 0; i < 10; i++) { 20.116 + System.gc(); 20.117 + } 20.118 + } 20.119 + 20.120 + public synchronized byte[] transform(final ClassLoader classLoader, 20.121 + final String className, 20.122 + Class<?> classBeingRedefined, 20.123 + ProtectionDomain protectionDomain, 20.124 + byte[] classfileBuffer) { 20.125 + System.out.println("Transforming class " + className); 20.126 + return classfileBuffer; 20.127 + } 20.128 + 20.129 + public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) { 20.130 + 20.131 + try { 20.132 + instrumentation.retransformClasses(to_redefine); 20.133 + } catch (Exception e) { 20.134 + e.printStackTrace(); 20.135 + } 20.136 + 20.137 + } 20.138 + 20.139 + public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception { 20.140 + Agent transformer = new Agent(); 20.141 + instrumentation.addTransformer(transformer, true); 20.142 + 20.143 + redefine(agentArgs, instrumentation, Test.class); 20.144 + } 20.145 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/test/compiler/profiling/spectrapredefineclass/Launcher.java Mon Mar 19 13:23:53 2018 -0700 21.3 @@ -0,0 +1,47 @@ 21.4 +/* 21.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 21.7 + * 21.8 + * This code is free software; you can redistribute it and/or modify it 21.9 + * under the terms of the GNU General Public License version 2 only, as 21.10 + * published by the Free Software Foundation. 21.11 + * 21.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 21.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 21.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 21.15 + * version 2 for more details (a copy is included in the LICENSE file that 21.16 + * accompanied this code). 21.17 + * 21.18 + * You should have received a copy of the GNU General Public License version 21.19 + * 2 along with this work; if not, write to the Free Software Foundation, 21.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21.21 + * 21.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21.23 + * or visit www.oracle.com if you need additional information or have any 21.24 + * questions. 21.25 + */ 21.26 +import java.io.PrintWriter; 21.27 +import com.oracle.java.testlibrary.*; 21.28 + 21.29 +/* 21.30 + * @test 21.31 + * @bug 8038636 21.32 + * @library /testlibrary 21.33 + * @build Agent 21.34 + * @run main ClassFileInstaller Agent 21.35 + * @run main Launcher 21.36 + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -Xmx1M -XX:ReservedCodeCacheSize=3M Agent 21.37 + */ 21.38 +public class Launcher { 21.39 + public static void main(String[] args) throws Exception { 21.40 + 21.41 + PrintWriter pw = new PrintWriter("MANIFEST.MF"); 21.42 + pw.println("Agent-Class: Agent"); 21.43 + pw.println("Can-Retransform-Classes: true"); 21.44 + pw.close(); 21.45 + 21.46 + ProcessBuilder pb = new ProcessBuilder(); 21.47 + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", System.getProperty("test.classes",".") + "/agent.jar", "Agent.class"}); 21.48 + pb.start().waitFor(); 21.49 + } 21.50 +}
22.1 --- a/test/runtime/RedefineFinalizer/RedefineFinalizer.java Mon Mar 19 12:12:48 2018 -0700 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,64 +0,0 @@ 22.4 -/* 22.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 22.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 22.7 - * 22.8 - * This code is free software; you can redistribute it and/or modify it 22.9 - * under the terms of the GNU General Public License version 2 only, as 22.10 - * published by the Free Software Foundation. 22.11 - * 22.12 - * This code is distributed in the hope that it will be useful, but WITHOUT 22.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 22.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22.15 - * version 2 for more details (a copy is included in the LICENSE file that 22.16 - * accompanied this code). 22.17 - * 22.18 - * You should have received a copy of the GNU General Public License version 22.19 - * 2 along with this work; if not, write to the Free Software Foundation, 22.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22.21 - * 22.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22.23 - * or visit www.oracle.com if you need additional information or have any 22.24 - * questions. 22.25 - */ 22.26 - 22.27 -/* 22.28 - * @test 22.29 - * @bug 6904403 22.30 - * @summary Don't assert if we redefine finalize method 22.31 - * @library /testlibrary 22.32 - * @build RedefineClassHelper 22.33 - * @run main RedefineClassHelper 22.34 - * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer 22.35 - */ 22.36 - 22.37 -/* 22.38 - * Regression test for hitting: 22.39 - * 22.40 - * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer 22.41 - * 22.42 - * when redefining finalizer method 22.43 - */ 22.44 -public class RedefineFinalizer { 22.45 - 22.46 - public static String newB = 22.47 - "class RedefineFinalizer$B {" + 22.48 - " protected void finalize() { " + 22.49 - " System.out.println(\"Finalizer called\");" + 22.50 - " }" + 22.51 - "}"; 22.52 - 22.53 - public static void main(String[] args) throws Exception { 22.54 - RedefineClassHelper.redefineClass(B.class, newB); 22.55 - 22.56 - A a = new A(); 22.57 - } 22.58 - 22.59 - static class A extends B { 22.60 - } 22.61 - 22.62 - static class B { 22.63 - protected void finalize() { 22.64 - // should be empty 22.65 - } 22.66 - } 22.67 -}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/test/runtime/RedefineTests/RedefineFinalizer.java Mon Mar 19 13:23:53 2018 -0700 23.3 @@ -0,0 +1,64 @@ 23.4 +/* 23.5 + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.7 + * 23.8 + * This code is free software; you can redistribute it and/or modify it 23.9 + * under the terms of the GNU General Public License version 2 only, as 23.10 + * published by the Free Software Foundation. 23.11 + * 23.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 23.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23.15 + * version 2 for more details (a copy is included in the LICENSE file that 23.16 + * accompanied this code). 23.17 + * 23.18 + * You should have received a copy of the GNU General Public License version 23.19 + * 2 along with this work; if not, write to the Free Software Foundation, 23.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23.21 + * 23.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23.23 + * or visit www.oracle.com if you need additional information or have any 23.24 + * questions. 23.25 + */ 23.26 + 23.27 +/* 23.28 + * @test 23.29 + * @bug 6904403 23.30 + * @summary Don't assert if we redefine finalize method 23.31 + * @library /testlibrary 23.32 + * @build RedefineClassHelper 23.33 + * @run main RedefineClassHelper 23.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer 23.35 + */ 23.36 + 23.37 +/* 23.38 + * Regression test for hitting: 23.39 + * 23.40 + * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer 23.41 + * 23.42 + * when redefining finalizer method 23.43 + */ 23.44 +public class RedefineFinalizer { 23.45 + 23.46 + public static String newB = 23.47 + "class RedefineFinalizer$B {" + 23.48 + " protected void finalize() { " + 23.49 + " System.out.println(\"Finalizer called\");" + 23.50 + " }" + 23.51 + "}"; 23.52 + 23.53 + public static void main(String[] args) throws Exception { 23.54 + RedefineClassHelper.redefineClass(B.class, newB); 23.55 + 23.56 + A a = new A(); 23.57 + } 23.58 + 23.59 + static class A extends B { 23.60 + } 23.61 + 23.62 + static class B { 23.63 + protected void finalize() { 23.64 + // should be empty 23.65 + } 23.66 + } 23.67 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/test/runtime/RedefineTests/RedefineRunningMethods.java Mon Mar 19 13:23:53 2018 -0700 24.3 @@ -0,0 +1,143 @@ 24.4 +/* 24.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 24.7 + * 24.8 + * This code is free software; you can redistribute it and/or modify it 24.9 + * under the terms of the GNU General Public License version 2 only, as 24.10 + * published by the Free Software Foundation. 24.11 + * 24.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 24.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 24.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 24.15 + * version 2 for more details (a copy is included in the LICENSE file that 24.16 + * accompanied this code). 24.17 + * 24.18 + * You should have received a copy of the GNU General Public License version 24.19 + * 2 along with this work; if not, write to the Free Software Foundation, 24.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 24.21 + * 24.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24.23 + * or visit www.oracle.com if you need additional information or have any 24.24 + * questions. 24.25 + */ 24.26 + 24.27 +/* 24.28 + * @test 24.29 + * @bug 8055008 24.30 + * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop 24.31 + * @library /testlibrary 24.32 + * @build RedefineClassHelper 24.33 + * @run main RedefineClassHelper 24.34 + * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethods 24.35 + */ 24.36 +public class RedefineRunningMethods { 24.37 + 24.38 + public static String newB = 24.39 + "class RedefineRunningMethods$B {" + 24.40 + " static int count1 = 0;" + 24.41 + " static int count2 = 0;" + 24.42 + " public static volatile boolean stop = false;" + 24.43 + " static void localSleep() { " + 24.44 + " try{ " + 24.45 + " Thread.currentThread().sleep(10);" + 24.46 + " } catch(InterruptedException ie) { " + 24.47 + " } " + 24.48 + " } " + 24.49 + " public static void infinite() { " + 24.50 + " System.out.println(\"infinite called\");" + 24.51 + " }" + 24.52 + " public static void infinite_emcp() { " + 24.53 + " while (!stop) { count2++; localSleep(); }" + 24.54 + " }" + 24.55 + "}"; 24.56 + 24.57 + public static String evenNewerB = 24.58 + "class RedefineRunningMethods$B {" + 24.59 + " static int count1 = 0;" + 24.60 + " static int count2 = 0;" + 24.61 + " public static volatile boolean stop = false;" + 24.62 + " static void localSleep() { " + 24.63 + " try{ " + 24.64 + " Thread.currentThread().sleep(1);" + 24.65 + " } catch(InterruptedException ie) { " + 24.66 + " } " + 24.67 + " } " + 24.68 + " public static void infinite() { }" + 24.69 + " public static void infinite_emcp() { " + 24.70 + " System.out.println(\"infinite_emcp now obsolete called\");" + 24.71 + " }" + 24.72 + "}"; 24.73 + 24.74 + static class B { 24.75 + static int count1 = 0; 24.76 + static int count2 = 0; 24.77 + public static volatile boolean stop = false; 24.78 + static void localSleep() { 24.79 + try{ 24.80 + Thread.currentThread().sleep(10);//sleep for 10 ms 24.81 + } catch(InterruptedException ie) { 24.82 + } 24.83 + } 24.84 + 24.85 + public static void infinite() { 24.86 + while (!stop) { count1++; localSleep(); } 24.87 + } 24.88 + public static void infinite_emcp() { 24.89 + while (!stop) { count2++; localSleep(); } 24.90 + } 24.91 + } 24.92 + 24.93 + 24.94 + public static void main(String[] args) throws Exception { 24.95 + 24.96 + new Thread() { 24.97 + public void run() { 24.98 + B.infinite(); 24.99 + } 24.100 + }.start(); 24.101 + 24.102 + new Thread() { 24.103 + public void run() { 24.104 + B.infinite_emcp(); 24.105 + } 24.106 + }.start(); 24.107 + 24.108 + RedefineClassHelper.redefineClass(B.class, newB); 24.109 + 24.110 + System.gc(); 24.111 + 24.112 + B.infinite(); 24.113 + 24.114 + // Start a thread with the second version of infinite_emcp running 24.115 + new Thread() { 24.116 + public void run() { 24.117 + B.infinite_emcp(); 24.118 + } 24.119 + }.start(); 24.120 + 24.121 + for (int i = 0; i < 20 ; i++) { 24.122 + String s = new String("some garbage"); 24.123 + System.gc(); 24.124 + } 24.125 + 24.126 + RedefineClassHelper.redefineClass(B.class, evenNewerB); 24.127 + System.gc(); 24.128 + 24.129 + for (int i = 0; i < 20 ; i++) { 24.130 + B.infinite(); 24.131 + String s = new String("some garbage"); 24.132 + System.gc(); 24.133 + } 24.134 + 24.135 + B.infinite_emcp(); 24.136 + 24.137 + // purge should clean everything up. 24.138 + B.stop = true; 24.139 + 24.140 + for (int i = 0; i < 20 ; i++) { 24.141 + B.infinite(); 24.142 + String s = new String("some garbage"); 24.143 + System.gc(); 24.144 + } 24.145 + } 24.146 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/test/runtime/execstack/TestCheckJDK.java Mon Mar 19 13:23:53 2018 -0700 25.3 @@ -0,0 +1,67 @@ 25.4 +/* 25.5 + * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. 25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 25.7 + * 25.8 + * This code is free software; you can redistribute it and/or modify it 25.9 + * under the terms of the GNU General Public License version 2 only, as 25.10 + * published by the Free Software Foundation. 25.11 + * 25.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 25.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 25.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25.15 + * version 2 for more details (a copy is included in the LICENSE file that 25.16 + * accompanied this code). 25.17 + * 25.18 + * You should have received a copy of the GNU General Public License version 25.19 + * 2 along with this work; if not, write to the Free Software Foundation, 25.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 25.21 + * 25.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 25.23 + * or visit www.oracle.com if you need additional information or have any 25.24 + * questions. 25.25 + */ 25.26 + 25.27 +/** 25.28 + * @test Testexecstack.java 25.29 + * @summary Searches for all libraries in test VM and checks that they 25.30 + * have the noexecstack bit set. 25.31 + * @requires (os.family == "linux") 25.32 + * @library /testlibrary /testlibrary/whitebox 25.33 + * @build sun.hotspot.WhiteBox 25.34 + * @run driver ClassFileInstaller sun.hotspot.WhiteBox 25.35 + * sun.hotspot.WhiteBox$WhiteBoxPermission 25.36 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 25.37 + * TestCheckJDK 25.38 + */ 25.39 + 25.40 +import com.oracle.java.testlibrary.Asserts; 25.41 +import sun.hotspot.WhiteBox; 25.42 + 25.43 +import java.nio.file.Files; 25.44 +import java.nio.file.Path; 25.45 +import java.nio.file.Paths; 25.46 + 25.47 +public class TestCheckJDK { 25.48 + static boolean testPassed = true; 25.49 + private static final WhiteBox WB = WhiteBox.getWhiteBox(); 25.50 + 25.51 + static void checkExecStack(Path file) { 25.52 + String filename = file.toString(); 25.53 + if (filename.endsWith(".so")) { 25.54 + if (!WB.checkLibSpecifiesNoexecstack(filename)) { 25.55 + System.out.println("Library does not have the noexecstack bit set: " + filename); 25.56 + testPassed = false; 25.57 + } 25.58 + } 25.59 + } 25.60 + 25.61 + public static void main(String[] args) throws Throwable { 25.62 + String vmInstallDir = System.getProperty("java.home"); 25.63 + 25.64 + Files.walk(Paths.get(vmInstallDir)).filter(Files::isRegularFile).forEach(TestCheckJDK::checkExecStack); 25.65 + 25.66 + Asserts.assertTrue(testPassed, 25.67 + "The tested VM contains libs that don't have the noexecstack " + 25.68 + "bit set. They must be linked with -z,noexecstack."); 25.69 + } 25.70 +}
26.1 --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Mon Mar 19 12:12:48 2018 -0700 26.2 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Mon Mar 19 13:23:53 2018 -0700 26.3 @@ -1,5 +1,5 @@ 26.4 /* 26.5 - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 26.6 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. 26.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.8 * 26.9 * This code is free software; you can redistribute it and/or modify it 26.10 @@ -235,4 +235,7 @@ 26.11 26.12 // Class Data Sharing 26.13 public native boolean isSharedClass(Class<?> c); 26.14 + 26.15 + // Returns true on linux if library has the noexecstack flag set. 26.16 + public native boolean checkLibSpecifiesNoexecstack(String libfilename); 26.17 }