Class loading. The essential part of the Java world, but why is it so rigid and cumbersome?
Where are we now.
Every time we start Java, the ClassLoader is the essential part that drives the startup process.
Every single piece of code that you have ever written for Java is handled by some ClassLoader.
Your usual ClassLoader hierarchy looks like in the sample diagram:
Though, if your application is basic enough, you will not have any application class loaders and their derivatives.
When you deploy your Java EE or WEB application to a Application Server, your code usually runs having several ClassLoaders over it..
The ClassLoader is essential in defining a Class. Basically, a class lives attached to a ClassLoader. That is both a good and a limiting feature:
- The main positive thing is that we can have multiple versions of the same class without conflicts
- The main negative thing is that we need to remove the whole ClassLoader (along with all loaded classes) to reload our changes.
It's been with us for a very long time. We are actually used to it in it's current state.
Intermediate solutions available to us.
That is where tools like ZeroTurnaround's JavaRebel get "on stage". Reloading of classes while the VM is running is a nice feature. But not everything can be reloaded by JavaRebel: No reloads with class hierarchy change are possible.In Java 5 Instrumentation API was added for developers to use. Instrumentation API is great, but it does have a little problem: no schema changes are allowed. That means that most of your changes will need the «old» process.
Where can we source our ideas from?
Our «irritating little» friend Ruby has this idea of open classes: you may change a class at runtime by adding new methods. This proves that it's possible to do ad-hoc changes.
PHP deployment is much less hassle than Java deployment. Though the model is not directly applicable to Java, the idea that you only need to change 1 file in an application and your changes are picked up instantly.
What would be useful?
Java(and Java EE) deployment lifecycle is criticized a lot. It's long. Very long. And the compile time is not the main factor here, it's the deployment itself. With the current need to trash the whole ClassLoader hierarchy we are definitely taking too much time and memory consumption(resource usage) does suffer.
Every single (re-)deploy goes through the same procedure on the lowest level:
- Application specific unload operations
- Remove any references to the ClassLoader(s) of the application
- Create a new ClassLoader
- Link the ClassLoader to the deployed code
- Application specific load operations
And this is an example where I just added a new logging method and a few statements to a class. As you look at it you might think what a sad state we are in. And if you have a thread there, guess you will have to restart the JVM to get rid of the old code from the memory.
Is it time we had a new method in ClassLoader that would unload a class(ClassLoader.undefineClass)? Well if that would be too hard...
At least, I say. I mean, the dynamic languages had that forever. PHP is a language that has a lot of inexperienced developers, and they still rarely manage to shoot themselves with that "feature". Does everyone consider everyone in Java land an idiot that has to be constricted in every possible way?
Imagine a world....
- Where you don't do lengthy deployments
- Where all you do is copy your jar, and the application server determines witch class changed and reloads ONLY it.
- Where HotFix is easy, and is not a sales feature
I am NOT an expert in JVM internals, but how hard is it to change the piece of data in memory? Java classes are just data in the memory, like everything else. (JVM Spec)
So what do you think? Is it time we have an ability to change the bytecode more dynamically? To have the classes reloaded through ClassLoader? Or, at least, the Instrumentation API would have the restriction on schema changes removed? What are your opinions and thoughts?