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 Java5/Java6) |
|||
Line 4: | Line 4: | ||
===== Mechanism in Java5/Java6 ===== | ===== Mechanism in Java5/Java6 ===== | ||
− | In order to create a Java class at runtime without Java source code, the use of a custom | + | 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 [http://asm.objectweb.org ASM] or some other library [http://www.java-source.net/open-source/bytecode-libraries framework]). | manipulation framework (such as [http://asm.objectweb.org ASM] or some other library [http://www.java-source.net/open-source/bytecode-libraries framework]). | ||
− | Java classloaders form an | + | Java classloaders form an instance-chain at run-time, with the system (<b>Bootstrap</b>, <b>Extension</b> and <b>System</b>) class loaders |
strictly controlled by the JVM. Once an application is launched (via an Application loader), a new loader <code>MyCustomClassLoader</code> can | strictly controlled by the JVM. Once an application is launched (via an Application loader), a new loader <code>MyCustomClassLoader</code> can | ||
be added to the chain. | be added to the chain. | ||
Line 15: | Line 15: | ||
<br /> | <br /> | ||
The basic implementation pattern is as follows - in the constructor, the new instance of <code>MyCustomClassLoader</code> is added to the | The basic implementation pattern is as follows - in the constructor, the new instance of <code>MyCustomClassLoader</code> is added to the | ||
− | runtime | + | runtime instance-chain by calling <code>super</code> with the parent loader. |
<source lang=java5> | <source lang=java5> | ||
public class MyCustomClassLoader extends ClassLoader { | public class MyCustomClassLoader extends ClassLoader { | ||
Line 27: | Line 27: | ||
if (some_condition) { | if (some_condition) { | ||
try { | try { | ||
− | byte[] bytes = | + | byte[] bytes = use_framework_to_generate_bytecode(); |
return defineClass(className, bytes, 0, bytes.length); | return defineClass(className, bytes, 0, bytes.length); | ||
} | } | ||
Line 40: | Line 40: | ||
</source> | </source> | ||
− | The <code>findClass</code> method is overridden so that if some condition is met, the | + | The <code>findClass</code> method is overridden so that if some condition is met, the bytecode for the Class <code>className</code> is |
generated; otherwise, the call is delegated up the implementation hierarchy which at runtime searches for the class up the instance | generated; otherwise, the call is delegated up the implementation hierarchy which at runtime searches for the class up the instance | ||
− | hierarchy. | + | hierarchy. The implementation hierarchy is responsible for maintaining a cache of both found and generated classes, as well as any |
+ | resources that have been loaded (XML descriptor files, image files, etc). | ||
===== Mechanism in Java7 ===== | ===== Mechanism in Java7 ===== |
Revision as of 15:53, 31 August 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-chain 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-chain 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 implementation hierarchy which at runtime searches for the class up the instance
hierarchy. The implementation hierarchy is responsible for maintaining a cache of both found and generated classes, as well as any
resources that have been loaded (XML descriptor files, image files, etc).
Mechanism in Java7
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.