< prev index next >
src/share/vm/oops/method.cpp
Print this page
@@ -1473,11 +1473,11 @@
bool sig_is_loaded = true;
Handle class_loader(THREAD, m->method_holder()->class_loader());
Handle protection_domain(THREAD, m->method_holder()->protection_domain());
ResourceMark rm(THREAD);
Symbol* signature = m->signature();
- for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
+ for (SignatureStream ss(signature); !ss.is_done(); ss.next()) {
if (ss.is_object()) {
Symbol* sym = ss.as_symbol(CHECK_(false));
Symbol* name = sym;
Klass* klass = SystemDictionary::resolve_or_null(name, class_loader,
protection_domain, THREAD);
@@ -1500,16 +1500,54 @@
bool Method::has_unloaded_classes_in_signature(methodHandle m, TRAPS) {
Handle class_loader(THREAD, m->method_holder()->class_loader());
Handle protection_domain(THREAD, m->method_holder()->protection_domain());
ResourceMark rm(THREAD);
Symbol* signature = m->signature();
- for(SignatureStream ss(signature); !ss.is_done(); ss.next()) {
+ for (SignatureStream ss(signature); !ss.is_done(); ss.next()) {
if (ss.type() == T_OBJECT) {
Symbol* name = ss.as_symbol_or_null();
if (name == NULL) return true;
Klass* klass = SystemDictionary::find(name, class_loader, protection_domain, THREAD);
- if (klass == NULL) return true;
+ if (klass == NULL) {
+ if (IgnoreUnloadedAccessConstructorTags &&
+ ss.is_last_arg() && m->is_synthetic() &&
+ m->name() == vmSymbols::object_initializer_name()) {
+ // Check for the "accessConstructorTag" that javac generates merely for
+ // overload resolution purpose. Ignore it even if it's not loaded, because
+ // the only value that's going to be passed in is null - thus the class
+ // never needs to be loaded.
+ //
+ // e.g. For java.util.ArrayList.iterator(),
+ // return new Itr();
+ // actually desugars to:
+ // return new ArrayList$Itr(this, /*accessConstructorTag*/ null);
+ // This is because Itr is a private inner class of ArrayList without
+ // an explicit constructor, so javac synthesizes a default constructor
+ // for it:
+ // private java.util.ArrayList$Itr(java.util.ArrayList);
+ // But this one follows the accessibility of the class so it's private.
+ // In order to allow the enclosing class to have access to Itr's
+ // constructor, javac synthesizes yet another bridge constructor with
+ // the right accessibility:
+ // java.util.ArrayList$Itr(java.util.ArrayList, java.util.ArrayList$1);
+ // These two constructors would have exactly the same name (<init>),
+ // the same argument list (the enclosing 'this'), and the same return
+ // type (void). So, javac introduces a marker argument at the end of
+ // the bridge constructor's argument list, so that the two constructors
+ // can be well-formed overloads, and always pass a null to that argument.
+ // Thus, even when the class of this argument isn't loaded, it's still
+ // safe to compile/inline this bridge constructor.
+ //
+ // javac forms the name of the type 'accessConstructorTag' by appending
+ // "$1" to the name fo the top-level class. Using a simple heuristic
+ // here should be good enough.
+ if (name->ends_with("$1")) continue; // skip this marker arg
+ } else {
+ // this is a normal argument whose class isn't loaded
+ return true;
+ }
+ }
}
}
return false;
}
< prev index next >