One pain point in dynamic language implementation is managing
code dynamically. While implementor’s focus is on
the body of a method, and the linkage of that body to some desired
calling sequence, there is a host of surrounding
details required by the JVM to properly place that code.
These details include:
These details add noise to the implementor’s task,
and often enough they cause various execution overheads.
Because class of a given name (and class loader) must be defined exactly once,
and must afterwards be recoverable only from its name (via
the JVM must connect each newly-defined class to its defining
class loader and to a data structure called the system dictionary,
which will handle later linkage requests. These connections
take time to make, especially since they must grab various
system locks. They also make it much harder for the GC to
collect unused code.
Anonymous classes can partially address these problems,
and we are prototyping this feature in the Da Vinci Machine
(which is the fancy name for the OpenJDK Multi-Language VM project).
Desired features of anonymous classes:
The key motivation is that we want to cut ClassLoaders and the system dictionary
out of the loop.
This means there will be fewer locks and no GC entanglements.
Drop the last object, and the class goes away too, just as it should.
Why the patching stuff? There are a few corner cases where,
because we are dealing with anonymous entities, an essentially
symbolic constant pool is not up to the task. Since the standard
class file format is specified as a byte stream, there is no way
to introduce live objects or classes to the newly-loaded class,
unless they first are given names. Therefore, there must be
some sort of substitution mechanism for replacing constants
(classes, at least) into the loading classfile. Given that
requirement, it is an easy step to generalize this substitution
mechanism to other types of constant pool entries.
The resulting facility is powerful in interesting ways.
You can often build a template classfile by passing Java code
through the javac compiler, and then use constant substitution
to customize the code.
Generated code often needs to get to complex constants
(e.g., lists or tables) and this provides a hook to introduce
them directly via the CP. The string-type constant pool entry
is extended to support arbitrary objects, if they are substituted
into the loaded anonymous class. This need not scare the
verifier; it just treats non-strings as general objects.
General objects, of course, are not a problem for dynamic languages.
Here is a toy example,
which actually works in a current prototype. Note that the anonymous classes are defined in a chain, with each new one
a subclass of a previously loaded one.
The API is a single static method
defineAnonymousClass, which is privileged.
In the current prototype it is in
sun.misc.Unsafe, which is a non-standard class.
If it is standardized, it will be given a suitable name. (And suitable security checks!)
This method takes an array of bytecodes, a host class, and an optional array of constant pool patches.
It returns the newly created anonymous class.
Unlike all other class queries, it can never return the same class twice.
As you can see from the sample output in the test code, an anonymous class has a name (via
getName) which consists of the original name of template class, followed by a slash (which never otherwise appears in a class name) and the identity hash code of the anonymous class.
This prototype will help provide the basis of further experimentation with other constructs,
notably anonymous methods and method handles.