AnonymousClassLoader in JRuby

Charles Oliver Nutter charles.nutter at sun.com
Sat Apr 26 14:30:10 PDT 2008


Ok, reading back over some notes and anonk.txt I think I understand a 
bit better. Tell me if I'm understanding things right.

java.dyn.AnonymousClassLoader is not a java.lang.ClassLoader itself. It 
bypasses the normal classloading chain by calling the new Unsafe method 
that allocates and loads a class directly. Given a byte[] and a host 
class, you can use AnonymousClassLoader to simply load a class; you can 
also use it to produce patched versions of a class, reducing the 
metadata necessary for each new class loaded by only altering the 
constant pool.

The classes are not associated with a classloader, and so the normal 
overhead we face of having a classloader-per-class (aggravated by a 
class-per-method in JRuby) is reduced.

 From an API perspective, we've largely achieved the "GCable class 
loading" concept in JRuby out of necessity. But on JDK6 and lower we pay 
the cost of having all those classes holding on to a clasloader in memory.

I have been unable to see an improved memory cost, but it's possible the 
actual cost of those classloaders in this test is outweighed by other 
JRuby runtime metadata associated with a given JITed method. Perhaps a 
simple Java test that loads 10_000 really simple classes via a 
OneShotClassLoader and via AnonymousClassLoader would be a better way to 
measure this?

It's also possible that the ClassCache concept would be useful/important 
to include or publish along with AnonymousClassLoader, since I would 
expect that most people loading classes anonymously will want a way to 
cache and retrieve already-loaded versions of code they're trying to 
load. This also sees like it might be necessary since anonymous classes 
will be otherwise impossible to look up, forcing even the same code in 
different places to instantiate a new class. Any thoughts on this? 
ClassCache (unpatched) in its entirety is here:

http://svn.codehaus.org/jruby/trunk/jruby/src/org/jruby/util/ClassCache.java

FYI, in JRuby, the key we use is generated by rendering the Ruby AST 
into a string containing a sexp representation of the code. This allows 
multiple instances of JRuby using the same class cache to share each 
others anonymously-loaded method bodies.

- Charlie

Charles Oliver Nutter wrote:
> I've managed to wire the AnonymousClassLoader into JRuby. A patch is 
> attached, that will probably be rather confusing to anyone unfamiliar 
> with JRuby.
> 
> ClassCache is basically a smart class-loading utility that can be used 
> to share loaded classes across JRuby instances without keeping hard 
> references to them and preventing them from unloading.
> 
> AnonymousClassLoader is an all-static utility class that wraps the logic 
> of instantiating "one-shot" classloaders for loading bodies of code. In 
> this case, it either uses java.dyn.AnonymousClassLoader or our own 
> "OneShotClassLoader" which is not anonymous but which is used for only a 
> single class.
> 
> The code generally appears to work about the same with 
> java.dyn.AnonymousClassLoader available, which is good. But I'm having 
> trouble quantifying the benefit to JRuby. I'd like to be able to show 
> how it helps, but memory profiles look practically the same between the 
> version using an OneShotClassLoader per method body and the version 
> using AnonymousClassLoader per method body. I have not done a lot of 
> work to isolate the cost of loading, but it seems to be unnoticeable in 
> my simple benchmark which defines 100_000 Ruby methods and forces them 
> to JIT.
> 
> So the runtime benefits may not be so great. The practical benefits, 
> such as being able to chuck byte[] into AnonymousClassLoader without 
> decorating class names and ensuring uniqueness, I have not yet utilized 
> in this code. Those benefits may show how writing class caches like the 
> one in JRuby are made a lot easier. For the moment, in order to allow 
> JRuby to support both MLVM work and pre-JDK7 JVMs, this patch still does 
> name-mangling to ensure methods are unique.
> 
> I think part of my confusion is that originally I desired a class loader 
> for which I could have a single instance I would throw *many* byte[] at, 
> and they'd all be loaded using that classloader but without hard 
> references and without the overhead of a classloader-per-method. But the 
> AnonymousClassLoader interface appears to one exactly one byte[] per 
> instance, though it does have considerably reduced in-memory cost per 
> AnonymousClassLoader instance.
> 
> Basically, what I've been looking for to make my life easier and memory 
> costs lower is:
> 
> ClassLoader cl = someClassLoader....;
> Class first = cl.defineClass(firstClass);
> Class second = cl.defineClass(secondClass);
> first = null; // and at some point I would expect the class to GC
> 
> Is this the purpose of AnonymousClassLoader? Am I doing it wrong? I'll 
> be poking around for example code now.
> 
> - Charlie
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev




More information about the mlvm-dev mailing list