RFR (S) JDK-8008962: NPG: Memory regression: One extra Monitor per ConstantPool

Ioi Lam ioi.lam at oracle.com
Mon Mar 18 09:32:23 PDT 2013


On 03/17/2013 12:43 AM, David Holmes wrote:
>
>> There are various places such as ConstantPool::klass_at_impl that need
>> to make atomic modifications of an CP entry and its corresponding tag.
>> These can be called well after the class has finished initialization.
>
> The question is more, can they be called before or during class 
> initialization?
>

Klass::init_lock is initialized in ClassFileParser::parseClassFile(). 
However, the CP is created before this. So there's a chance that the CP 
may try to lock on ConstantPool::lock() before Klass::init_lock() is 
initialized (or even before ConstantPool::_pool_holder is initialized).

Nevertheless, I have not (yet) seen this happening with a fair amount of 
stress tests.

Also, up to the initialization of Klass::init_lock(), only the 
ClassFileParser has a reference to the InstanceKlass and the 
ConstantPool, so everything is single threaded. I will change the code 
to be something like this (similar to what was done in InstanceKlass 
with the init_lock):

      oop cplock = lock();
      ObjectLocker ol(cplock, THREAD, cplock != NULL);

> - if we don't need to inflate (do we have any stats on this?) then we 
> don't get any overhead beyond the int[0] 

I don't have any stats. How would one go about collecting the locking 
stats on specific objects?

Looking at the code, most use of the lock would be in 
ConstantPool::klass_at_impl(), and only if the slot is still an 
unresolved class. Also, the lock is usually held for a very short period 
of time, unless you hit an exception, or hit a GC at this block

       MonitorLockerEx ml(this_oop->lock());
       // Only updated constant pool - if it is resolved.
       do_resolve = this_oop->tag_at(which).is_unresolved_klass();
       if (do_resolve) {
         ClassLoaderData* this_key = 
this_oop->pool_holder()->class_loader_data();
         this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM  
<<<<<< GC may happen here
         this_oop->klass_at_put(which, k());
       }

So my wild guess is you rarely would get a contention on the lock.

>>> Is there a possibility of a self-deadlock if during class
>>> initialization we have to lock the constant-pool ourselves?
>> The locking is done using ObjectLocker with an oop, so it is self
>> reentrant, just like a regular Java monitor entry. Unlike mutexes, there
>> won't be self deadlocks.
>
> Okay. But recursive locking can also be problematic if you don't fully 
> understand the circumstances under which it can occur - because you 
> effectively lose atomicity relative to actions in the current thread.

Sorry I don't quote understand this. Could you explain more?

Thanks a lot!

- Ioi


More information about the hotspot-runtime-dev mailing list