Tiered compilation leads to "unloaded signature class" inlining failures in JRuby

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Sep 2 08:07:59 UTC 2020


>> As I can see with the test case, target method is loaded in a separate
>> instance of OneShotClassLoader (and, moreover, I see j.l.String loaded
>> there!). So, it doesn't mattter whether a class is loaded in a "parent"
>> (?) script at all since they are loaded by separate class loaders.
> 
> Ok this might be the clue I needed!
> 
> Some years ago, in order to avoid conflicting libraries when running
> JRuby inside a web container, one of our contributors (with a focus on
> JRuby's embedding use cases) modified JRuby's classloading to use a
> "self-first" classloader, which always tries to load the classes from
> itself *before* trying the parent classloaders.
> 
> As it so happens, this also ends up being an ancestor classloader of
> the OneShotClassLoader we use to load compiled code.
> 
> So, I patched our logic to not use the self-first loader... and the
> original reported example now appears to inline properly!
> 
> I will need to do more exploration but I think I now have some idea
> why this isn't working. Our self-first classloader is likely
> "re-homing" some of the core JDK classes, making them appear like
> they're the wrong ones, or not properly resolved, or something. That
> in turn prevents inlining because the lifecycle and lineage of those
> classes doesn't look right.

Only bootstrap class loader is allowed to define classes under 
java.lang. (And it was the case long before modules were introduced.) 
There's simply no way for successully load java.lang.String class unless 
the request is delegated to bootstrap class loader.

There may be other reasons why the problem doesn't show up after the 
change: e.g., when scheduling a method for compilation by C2, all 
classes mentioned in its signature are eagerly loaded, or more code is 
loaded inside the class loader and java.lang.String is loaded there 
before compilation kicks in.

But the root cause stays the same: java.lang.String is absent (hasn't 
been resolved yet) in the context class loader used for inline.rb 
script. (If it were resolved, it'll point to the java.lang.String from 
bootstrap CL.)

So, the only solution I see (w/o touching JVM) is to force 
java.lang.String class resolution for OneShotClassLoader instances 
eargerly. (Or, alternatively, drop String argument.)

> We will investigate how to do a safer job of self-first classloading
> *only* for resources shipped with JRuby, and avoid using it for JDK
> libraries that must always come from the system classloaders.

>> It's hard to draw a line here. My feeling is JVM can do a better job
>> here (but I haven't worked out all the consequences yet). But if you
>> want to get rid of this quirk running on 8u, you definitely better fix
>> your app (JRuby).
> 
> I am also interested to see if there's a way to improve this at the
> JVM level... but on my end I will continue to explore how our unusual
> classloading can be adjusted to avoid the issue (and perhaps, to get a
> more complete understanding of why the current logic breaks inlining
> so badly.)

After thinking more about it, I still don't see any compelling reason to 
forbid inlining of a method solely by the presence of not-yet-loaded 
classes in its signature. I'll experiment with disabling the problematic 
logic in C2.

Best regards,
Vladimir Ivanov


More information about the hotspot-compiler-dev mailing list