raspacorp
raspacorp

Reputation: 5307

How to dynamically load a Java class without using a class loader?

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.

enter image description here

Upvotes: 5

Views: 2192

Answers (7)

Dave Newton
Dave Newton

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

ZhekaKozlov
ZhekaKozlov

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

Anton Arhipov
Anton Arhipov

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

raspacorp
raspacorp

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

Peter Lawrey
Peter Lawrey

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

meriton
meriton

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

Tobias Brandt
Tobias Brandt

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

Related Questions