Reputation: 5307
I recently saw an online presentation of JRebel in which they explain what their product does, in one of the slides they mention they don't use class loaders (see screenshot below).
I have some projects in which I use class loaders for dynamically loading classes at runtime, for example for dependency injection (like in the Maker Factory framework that I developed). I thought the only way to load a class in Java was by using a class loader.
Upvotes: 5
Views: 2192
Reputation: 160191
They don't use any new classloaders; they extend the default ones.
https://www.jrebel.com/learn/how-does-jrebel-work
Upvotes: 6
Reputation: 39536
For completeness, I would like to mention a new method Lookup.defineClass() which was introduced in Java 9. It allows dynamically defining new classes without all that class loader pain. The usage of the method is very easy: you just pass a byte array and you immediately get a Class<?>
object. It has a limitation though: the class must be in the same package as the caller class.
Upvotes: 0
Reputation: 6591
Disclaimer: I'm involved with JRebel development
Technically, it is possible to bypass the classloader with some Unsafe magic, and JVM leverages that with lambdas when creating the runtime anonymous classes (in Java 8).
However, JRebel actually integrates with the existing classloaders and doesn't create new ones - that's what the slide mean. JRebel doesn't drop the existing classloader when it has to reload a class. Instead, it loads and versions the classes within the existing classloaders.
Upvotes: 3
Reputation: 5307
So the answer to this question may be: There is no way to dynamically load a Java class without using a class loader for the first time. But it is possible to reload a class partially by instrumenting the class loader.
Based on Dave Newton's answer link, extracting the important things from the JRebel faq:
They use the Instrumentation API to instrument the Container/Server class loaders, that way they can dynamically monitor and control the loading process. They will scan the class-path in search of the .class file that corresponds to the loaded class and use the file timestamp to detect changes on it. When a change is detected they will propagate that change through the instrumented class loader. It will preserve the existing instances of the class but won't re-run the constructor, which means that new added fields won't be initialized.
Upvotes: 3
Reputation: 533530
they mention they don't use class loaders.
Every class uses a ClassLoader (except primitives). However, a library doesn't have to create additional ClassLoader.
Even a "Hello World" program will have two class loaders (one for boostrapping)
I thought the only way to load a class in Java was by using a class loader.
It is, but you can force the existing classloader to load your class which is hack but might be simpler to use.
(Correction) If you use null
as a ClassLoader, Unsafe.defineClass() will default to the ClassLoader of the caller.
Upvotes: 3
Reputation: 70564
Indeed, the only way to load a class is through a class loader.
The JRebel folks probably meant to say that the don't use class loaders to redefine classes. Redefining a class is possible through other means, for instance through JVMTI.
Upvotes: 1
Reputation: 3413
You can of course read the class file into memory yourself. But to make the class available in your code, you still need to use ClassLoader#defineClass.
In general, any class that is used in a program must have been defined by a class loader, otherwise what should getClass().getClassLoader()
return?
Upvotes: 0