G1 garbage collection Ext Root Scanning time increases due to Class.forName (Problem, Solution, and Patch)

Thomas Schatzl thomas.schatzl at oracle.com
Thu Jul 11 01:53:35 PDT 2013


On Thu, 2013-07-11 at 09:41 +0200, Thomas Schatzl wrote:
> Hi,
> 
>  first, let me say that I have not been involved in Ashley's discussion
> with John, so these are only observations. Maybe other gc people know
> more.
> 
> On Thu, 2013-07-11 at 16:42 +1000, David Holmes wrote:
> > Hi Ashley,
> > 
> > Is this Dictionary the systemDictionary in the VM or something to do 
> 
> In this test program, the number of entries in the system dictionary
> (SystemDictionary::number_of_classes()) grows steadily when using
> Class.forName() when looking up "java.util.HashMap" in a loop; when
> using the URLClassLoader instance to look up the same class, the size of

i.e. the loadClass() method.

> the system dictionary stays constant.

Fyi, maybe it helps: adding some code to
SystemDictionary::resolve_instance_class_or_null() indicates that when
using Class.forName() the loader_data (ClassLoaderData) is different
every time the code is executed, changing the hash code for the class.

Here are my changes:

Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
  Handle class_loader, Handle protection_domain, TRAPS) {
  assert(name != NULL && !FieldType::is_array(name) &&
         !FieldType::is_obj(name), "invalid class name");

  TracingTime class_load_start_time = Tracing::time();

  { ResourceMark rm;
gclog_or_tty->print("1 cl %s name %s\n", class_loader() != NULL ?
class_loader()->klass()->external_name() : "n/a", name->as_C_string());
   }
  // UseNewReflection
  // Fix for 4474172; see evaluation for more details
  class_loader = Handle(THREAD,
java_lang_ClassLoader::non_reflection_class_loader(class_loader()));
  ClassLoaderData *loader_data = register_loader(class_loader,
CHECK_NULL);
  { ResourceMark rm;
gclog_or_tty->print("2 cl %s "PTR_FORMAT" name %s\n", class_loader() !=
NULL ? class_loader()->klass()->external_name() : "n/a", loader_data,
name->as_C_string());
   }

prints

1 cl java.net.URLClassLoader name java/util/HashMap
2 cl java.net.URLClassLoader 0x00007f6851a5f200 name java/util/HashMap
1 cl n/a name java/util/HashMap
2 cl n/a 0x00007f6850221a60 name java/util/HashMap
adding java.util.HashMap class_loader java.net.URLClassLoader (index
520, hash 2143411148)

(the last line is some code that prints d_index and d_hash just before
dictionary()->add_klass() in SystemDictionary::update_dictionary())

for the Class.forName() path, and only

1 cl n/a name java/util/HashMap
2 cl n/a 0x00007f8ba8221a60 name java/util/HashMap

when using .loadClass().

Not sure if it helps, or there is a problem at all.

> Only a full gc "fixes" the problem.
> 
> > with G1? If there is an issue with the VM's use of the systemDictionary 
> > then it needs to be fixed in the VM. If there is an issue in G1 then it 
> > needs to be fixed in G1. A change to the Java-level behaviour of 
> > Class.forName needs to pass extreme scrutiny and as Ioi points out it is 
> > not appropriate for forName to assume how a ClassLoader will load a 
> > class - it must defer to the classloader to do it. So the patch is not 
> > acceptable.
> > 
> > What exactly is G1 reporting and why do you think it is wrong? (I have 
> > no idea what "Ext root scanning" means.)
> 
> Ext root scanning = "External root scanning" (I think :) time, i.e. an
> estimate for the time finding the roots and determining whether they
> should be changed take.

... whether further processing is needed.

Thomas




More information about the hotspot-runtime-dev mailing list