Possible class loader related optimization

Karen Kinnear karen.kinnear at oracle.com
Fri Aug 3 11:48:03 PDT 2012


Eric,

I'm sorry, we can't put in an optimization that changes the behavior, even if 90% of the time it would not make a difference.

Today JVM_LatestUserDefinedLoader can return null if there are no classes loaded by a user application on that specific thread
stack. You can't prove that we never hit this case. And this is in sun.misc, so the JDK doesn't control all of the callers. 
Class.forName() called with a user loader vs. called with the boot loader gives very different results e.g. when calling CheckPackageAccess 
and calling out to a security manager.

thanks,
Karen

On Aug 1, 2012, at 3:17 PM, Eric Caspole wrote:

> 
> On Aug 1, 2012, at 2:13 PM, Karen Kinnear wrote:
> 
>> Eric,
>> 
>> First, I wanted to thank you for doing this investigation, and for sending both a webrev and test cases. We really appreciate it.
>> 
>> In looking over your changes, it is not obvious to me that this change would always return the same information from
>> JVM_LatestUserDefinedLoader that you would get today. I did not write any additional test cases, but walking through
>> the source code, it appears to me that there are a couple of possible cases in which the cached system loader might
>> be returned when the current code would return a different loader, such as an extension class loader or the null
>> boot loader (what those of us in the vm would call the "primordial" loader :-) if there were no application loaders on
>> that particular thread's stack.  It is not obvious to me that it is possible to match the exact current behavior in all cases
>> without actually walking the current stack. Did I read that correctly?
> 
> Hi Karen,
> 
> As I understand it, JVM_LatestUserDefinedLoader will not return the null loader, since the JDK will never use this path except on behalf of a user application. I am not sure what the ext loader is used for besides crypto, such that it might ever arrive to call JVM_LatestUserDefinedLoader. Definitely that seems like it might complicate the situation, hopefully not so as to make this change impractical.
> 
> So the overall idea is if the vast majority of the user app is running in just 1 loader, can it be cached? In my webrev, I special cased the ext loader and the reflection loader since they did not affect the correctness in our case. But there is probably a better way to do it.
> 
> Otherwise, I think this will basically work for other 'real' user loaders that are explicitly created and used in the application code. In my tests I have a non-delegating URL loader that gets used in addition to the sun.misc.Launcher$AppClassLoader and it works to shut off the cache and fall back to the regular path when the URL loader gets used for the first time.
> 
> My special case hacks aside, which are due to the JDK internal operation, and probably needs more thought, can you think of a more complicated scenario to test? I am trying to think of something with static initializer blocks that use object streaming or something like that would cause a weird situation.
> 
> Thanks for looking this over.
> Eric
> 
> 
> 
>> 
>> If I misunderstood something, then I did have some more detailed comments about the implementation, but let's work
>> through ensuring we believe this type of approach is possible first.
>> 
>> thanks,
>> Karen
>> 
>> On Jul 20, 2012, at 3:32 PM, Eric Caspole wrote:
>> 
>>> Hello JVM team,
>>> 
>>> While running a customer app that frequently uses ObjectInputStream, we noticed a lot of time spent in JVM_LatestUserDefinedLoader and some related methods like vframeStreamCommon::skip_reflection_related_frames. When doing ObjectInputStream.read(), it needs to find the class loader that goes with the user application call site to get the class of the freshly read object. This operation walks down the stack on the thread looking at the nmethod's classes to find the owner class's loader.
>>> 
>>> But it appears this application, like probably a great many real world applications out there, uses only one class loader, the primordial sun.misc.Launcher$AppClassLoader.
>>> 
>>> I think if there is only one user class loader in play, we should be able to cache it and avoid the stack walk. More complicated cases like web app servers, where often each web app is run in its own loader, might still require the stack walk lookup.
>>> 
>>> I have made a webrev where I cache a ref to the primordial sun.misc.Launcher$AppClassLoader and use the cached value for these JVM_LatestUserDefinedLoader lookups, and flush the cache and force a normal stack walk lookup if a new user class loader comes into play.
>>> Since our application only uses the primordial loader, this optimization was effective and sped it up a few percent.
>>> 
>>> My webrev is at: http://cr.openjdk.java.net/~ecaspole/latestloader/webrev/
>>> 
>>> I attached here a small test case using ObjectInputStream that shows this use case.
>>> 
>>> Please let me know your comments. I know there are a lot of special purpose class loaders used internally in the JDK but I think most of them never run code that will arrive at ObjectInputStream.read().
>>> 
>>> Regards,
>>> Eric
>>> <StreamChicken.java><Chicken.java>
>> 
>> 
> 
> 



More information about the hotspot-runtime-dev mailing list