Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Development/Dynamic/def1"
(→Mechanism in Java7) |
|||
Line 52: | Line 52: | ||
It is thus incumbent upon the designer to ensure that the correct loader is used throughout the lifecycle of the application. | It is thus incumbent upon the designer to ensure that the correct loader is used throughout the lifecycle of the application. | ||
− | ===== Mechanism in Java7 ===== | + | ===== Mechanism in Java7/MLVM ([http://jcp.org/en/jsr/detail?id=292 JSR-292]) ===== |
<i>Future</i><br />JSR-292 (Supporting Dynamically Typed Languages on the Java ™ Platform) introduces a new type of classloader, | <i>Future</i><br />JSR-292 (Supporting Dynamically Typed Languages on the Java ™ Platform) introduces a new type of classloader, | ||
<code>java.dyn.AnonymousClassLoader</code>. The <code>AnonymousClassLoader</code> class is designed to solve two problems: | <code>java.dyn.AnonymousClassLoader</code>. The <code>AnonymousClassLoader</code> class is designed to solve two problems: |
Revision as of 10:45, 3 September 2009
Dynamic Persistence
Dynamic Persistence is defined as the ability to create a persistent entity class and use it within an application without a-priori the Java class existing (no .class file on the classpath or in the relevant .jar/.war archive).
Mechanism in Java5/Java6
In order to create a Java class at runtime without Java source code, the use of a custom ClassLoader is required, along with a bytecode manipulation framework (such as ASM or some other library framework).
Java classloaders form an instance-hierarchy at run-time, with the system (Bootstrap, Extension and System) class loaders
strictly controlled by the JVM. Once an application is launched (via an Application loader), a new loader MyCustomClassLoader
can
be added to the chain.
The basic implementation pattern is as follows - in the constructor, the new instance of MyCustomClassLoader
is added to the
runtime instance-hierarchy by calling super
with the parent loader.
public class MyCustomClassLoader extends ClassLoader { public MyCustomClassLoader (ClassLoader parent) { super(parent); } @Override protected Class<?> findClass(String className) throws ClassNotFoundException { if (some_condition) { try { byte[] bytes = use_framework_to_generate_bytecode(); return defineClass(className, bytes, 0, bytes.length); } catch (ClassFormatError cfe) { throw new ClassNotFoundException(className, cfe); } } return super.findClass(className); } }
The findClass
method is overridden so that if some condition is met, the bytecode for the Class className
is
generated; otherwise, the call is delegated up the instance-hierarchy to search for the class. The implementation hierarchy is responsible
for maintaining a cache of classes, as well as any resources that have been loaded (XML descriptor files, image files, etc). Thus, an instance
of MyCustomClassLoader
behaves as a 'proper' class loader in all cases, with the additional capability that non-existent
classes can be built/found without their corresponding .class files being on the JVM's classpath.
NB: it is important to note that two separate instances of MyCustomClassLoader
can generate two classes
for className
. Even though the bytecode is identical, the classes are distinct. When running under a Java EE™ container
(or an OSGi environment), the class loader hierarchy may be much more complicated, but the point remains - a custom classloader is
required to build classes at runtime; the custom classloader is part of a chain of loaders and each dynamic class is distinct.
It is thus incumbent upon the designer to ensure that the correct loader is used throughout the lifecycle of the application.
Mechanism in Java7/MLVM (JSR-292)
Future
JSR-292 (Supporting Dynamically Typed Languages on the Java ™ Platform) introduces a new type of classloader,
java.dyn.AnonymousClassLoader
. The AnonymousClassLoader
class is designed to solve two problems:
- Generating many classes with similar bytecode and only minor changes is very inefficient, wasting a lot of precious memory.
- Generated bytecode must be contained in a class, which must be contained in a ClassLoader, which keeps a hard reference to the class; as a result, to make even one byte of bytecode garbage-collectable, it must be wrapped in its own class and its own classloader.
First, classes loaded by AnonymousClassLoader
are not given full-fledged symbolic names in the global symbol tables; they're given rough numeric identifiers. They are effectively anonymized, allowing much more freedom to generate them at will, since naming conflicts essentially do not happen.
Second, the classes are loaded without a parent ClassLoader, so there's no overprotective mother keeping them on a short leash. When the last normal references to the class disappear, it's eligible for garbage collection like any other object.
Third, it provides a mechanism whereby an existing class can be loaded and slightly modified, producing a new class with those modifications but sharing the rest of its structure and data.