I am IT systems consultant, an application developer and designer specialized on backend systems, business process automation, performance engineering, SOA and grid technologies. Current development focus on: application of cloud computing in the enterprise - IaaS, SaaS, PaaS and *aaS. http://www.linkedin.com/in/panzin Alex(JAlexoid) has posted 1 posts at DZone. You can read more from them at their website. View Full User Profile

Class Loading in Java: Time to Add Dynamicity?

05.24.2008
| 14200 views |
  • submit to reddit

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:

Sample ClassLoader HierarchyThough, 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.
But these 2 points are not mutually exclusive.

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.

Unload class?

Is it time we had a new method in ClassLoader that would unload a class(ClassLoader.undefineClass)? Well if that would be too hard...

Reload class?

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?
References
AttachmentSize
20080525_cla_loaders.png15.82 KB
Published at DZone with permission of its author, Alex(JAlexoid) Panzin. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Jeff Anderson replied on Sun, 2008/05/25 - 10:25am

Imagine a world...

Where all you do is copy your jar, and the application server determines witch class changed and reloads ONLY it. 

Where only one class changed (only a method signature was changed) and so only that class was reloaded and only the other classes that call the changed method of the changed class crash the JVM.  

 Dynamic languages pay a huge performance hit for the ability to update classes dynamically.  I'd rather have my application run fast and have to do a full restart when I make code changes than run slow with better dynamic class loading.

cowwoc replied on Sun, 2008/05/25 - 11:39am

At the very least we need to revisit the ClassLoader design. Last time I looked it was a pain in the a** to do anything with it. It's very hairy code. So yes, I'm in favor of some Java7 time being invested in this direction.

Eduard Korenschi replied on Sun, 2008/05/25 - 2:14pm

Ok, jeff, I totally understand your point, and I'm sure nobody would trade orders of production performance for some development comodity, but try to imagine the world where you could change between these two behaviors through a simple parameter.

What if jvm could run in production and development mode, just as there's a server and a client mode? (at least the sun's jvm).

 

Roland Carlsson replied on Sun, 2008/05/25 - 3:30pm in response to: Jeff Anderson

.Net can do this. My current assignment are about 50% developing a .Net-site and the only thing I have to restart is the whole system to keep it stable (no fun with Windows). But I never restart the webapplication I develop.. It compiles and reload classes almost at the same insyant I press save in Visual Studio. 

 What did Microsoft do right here? 

Mike P(Okidoky) replied on Sun, 2008/05/25 - 10:30pm

Java's hotswap allows the reloading of classes, with restrictions.  There is this Java agent by this one company, forget which one, that offers the ability to do just about anything, making Java seem a lot more like a dynamically programmable language.

One thing's for sure about Sun: they way underestimate the importance of the ability to redefine classes at runtime without having to restart. An astronomical ton of productivity is lost because Java normally is so darn stiff.

As for .net.  Dot what?  Whatever... 

Aidos Morg replied on Sun, 2008/05/25 - 10:40pm

As I was reading this article I started thinking about the Classworlds classloader framework. I don't know if it is already supported, but it definately sounds like this topic would be worth raising with those guys as they're already doing some pretty impressive stuff with java ClassLoaders and ClassRealms (turning the classloader heirarchy into a directed graph to make it easier to have multiple versions of the same library at runtime).

http://classworlds.codehaus.org/

 

 

Pedro Furlanetto replied on Sun, 2008/05/25 - 11:59pm

Alex,

I think you are a forgetting a little detail about PHP languange and web request life cycle.

For every request the PHP page is reloaded and until the release of PHP5 there wasn't the concept of Web Application as there is in JEE. The better that could be done was to do little low level unportable tricks like using memory sharing APIs. And even compiled PHP had to be reloaded every time.

If you think it's proper I can give more details on how it used to work.

 

 

Alex(JAlexoid) ... replied on Mon, 2008/05/26 - 1:40am in response to: Pedro Furlanetto

> Pedro Furlanetto:

Had a lot of work with PHP and therfore I am talking about the idea, that you don't need to redeploy all files, just the changed ones:
"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."

Jevgeni Kabanov replied on Mon, 2008/05/26 - 1:31am

@Roland

AFAIK .NET does not reload code, it does full redeploy juts like Java, just application start usually will take less.

@Mike P

The product is called JavaRebel and Sun doesn't underestimate the productivity gain. It's just expensive to develop and hard to commercilize for them. There should be a Java tax or something :)

Eduard Korenschi replied on Mon, 2008/05/26 - 3:15am

Guys ... this point about productivity and stuff applies in general to the enterprise sector, where honestly, we do make lots of $$$. So personally I wouldn't mind paying some money for a feature that promises such a huge return on investment.

About JavaRebel ... it's nice, I also try their nightly builds, even considering buying it ... but we're using hibernate and sometimes reflection and JavaRebel sometimes breaks them with their proxies.

 Eduard

Jevgeni Kabanov replied on Mon, 2008/05/26 - 4:00am

@edykory

Have you reported your issue to the ZeroTurnaround? In many cases if you have problems with proxies adding "-Drebel.forbid_bypass=true" will help.

Jan Hlavatý replied on Mon, 2008/05/26 - 4:43am

...and what exactly is wrong with having to kill all instances of old classes to kill the ClassLoader? You want to translate the instances automatically to a new class? That sounds like a bad idea. It would only work in trivial cases and will break everything else with impossible to debug consequences... Even if the fields remain the same, some class invariants may be invalidated. Not to mention the hell with static fields, active locks...sounds like a world of trouble.

And give me a break with the ".NET Has It" argument, if they do, they just give you enough rope you want to hang yourself.

 

Here are however some ideas for ClassLoader changes:

 

- We would maybe use a way to define class one part at time instead of having to give whole byte[] of the classfile at once. Like, split the class definition to components like class header (describing the structure of the class static data and instance fields), individual methods code, attributes... Provide a callback mechanism that will request bytecode for a given method signature. That would open up some interesting possibilities, like on-demand method creation (maybe even new methods that didnt exist in the class?), and allow more fine-grained approach to storing class information, not having to load whole class at once. It would enable more funny things like faster startup by having a shared image with only the really used parts of the classes.

- Provide a persistent, shared code cache that could:

1) store results of bytecode verification so that class bytecode does not have to be validated again until its really changed

2) store HotSpot measurements history of the class so that the HotSpot has some memory about the class and does not have to start from scratch each time the same class is loaded. Might be as simple as "HOT" flag on method that lets HotSpot always compile the method because it has already determined it is hot. That is something that depends on application though, not just the class.

3) Enable a persistent way to install packages / libraries for the system wide use, with multiple versions installed, and a way for applications to request certain versions of shared packages it needs. That is actually one thing that .NET has better, with the assembies. Solve the damn dependency hell.

4) Store a precompiled image of class methods.

5) Allow faster applicaction cold startup by creating cached, precompiled images of needed parts of classes for individual applications in the similar way the "class data sharing" is done on client VM, but storing only needed parts of classes, not whole classes.  That would also require a standardized way of launching applications and mechainsm of creating these snapshots, but could be entirely automatic. Yes, there would be redundancy.

 

Florent Guillaume replied on Mon, 2008/05/26 - 5:15am

Regarding dynamic class loading of partial interface implementations, this is being considered, see John Rose's blog: Interface injection in the VM.

 

cowwoc replied on Mon, 2008/05/26 - 9:33am in response to: Jan Hlavatý

Jan,

 

I don't believe Java performance is an issue (any more). Frankly, if enterprise customers would upgrade from Java 1.3 to 1.6 they would notice a huge performance increase. Couple that with faster hardware and I think only specific APIs need to be optimized, not the entire JVM.

Mike P(Okidoky) replied on Mon, 2008/05/26 - 10:04am

Is there a way to integrate JavaRebel into Eclipse in such a way that all you have to do is save a changed Java file in the editor and the changes are picked up even when running, say, JBoss?

I think that's the development performance gain the php people think they have, and I think Java can do this just as well.

Jevgeni Kabanov replied on Mon, 2008/05/26 - 10:09am

@Mike P

That is exactly what JavaRebel does. It's a JVM-level plugin so it works with all applications servers, it monitors the class files for changes and reloads the classes as soon as you save them from Eclipse. No special integration with IDEis necessary.

Johan Zahri replied on Tue, 2008/05/27 - 12:01pm in response to: Jan Hlavatý

Jan,

When I run multiple java instances of the same app, say 2 instances of Eclipse it feels like i'm having duplication of jars in memory!! When you run something like eclipse these days (the distro is about 1,4G) you can definitely start to feel the load when you run more than 1 instance. What's more is that most of the time I run many other servers like derby, tomcat, etc. sometimes each of them more than one instance themselves.

So if we could only have a jvm-server that could integrate all types of similar jar in the memory. Then we could have jvm-client to run the different instances of the apps and illiminate the possibilities of jar duplication in-memory. We could probably do this by making only soft references to the already available in-memory jars.

I think, this scenario could actually save up memory space usage. We could even implement in the jvm-server  

>java-server &

>java foo.AppServer 1 &

>java foo.AppServer 2 &

We could go further do farming type of things to the jvm-server to increase robustness and speed (since in some os somehow one os-level-process might not have the same processing time slice compared to the other)

>java-manager -max-concurrent-os-process 9

If we feel that the java server is loaded with too much unused jars we could ask the manager to garbage collect the unused in-memory jars! Or we could set an auto-garbage-collect scheme. 

> java-manager -garbage-collect now

If we need to introduce new jni libraries(drivers etc) we could do:

>java-manager -jni-load C:/drivers/packedDll.jar 

If we need to invalidate a dll we could :

>java-manager -jni-unload C:/drivers/packedDll.jar

 We could have different versions of dll by loading the jar from different path.

>java-manager -jni-unload C:/drivers/newversion/packedDll.jar 

the client would then refer to the new loaded jni as follow:

>java -cp C:/drivers/newversion/packedDll.jar foo.App

 

And many things more, I think, that we could do..  

 

This will probably pave a way to an evolutionary step towards javaos.. >:)

 

Regards,

Johan

 

mike replied on Tue, 2008/05/27 - 1:00pm

When I hear this, I immediately think of how is the class loader supposed to handle changes to member variables? To have truly dynamic class loading, there must be some way to define how to convert from the old version to the new version.

Example: while fixing a bug, you realize that a boolean member variable really needs to be a tri-state enum. How does the class loader handle this? Remember: my application's data integrity is paramount. I don't want all new instances to be set to the same thing. And it's not as simple as true = MyEnum.Yes and false = MyEnum.No. I've introduced a new third state. This new state has to be determined by some new code included with the update -- please, not some new xml "language" as the new state may be complicated; requiring complex algorithms to determine the new value. In addition, the class with the new variable may just be holding some data. It possibly isn't even the one that knows what the new state should be. This is why Sun doesn't allow dynamic updates that change a class' member variables.

My example is simple. Often my changes are massively complex involving several classes. In addition to providing a way to 'upgrade' a class instance in memory, a comparison feature is required to tell the developer what the differences are, so that he/she can create an appropriate upgrade mechanism.

The technical hurdles of loading new versions of classes have already been solved by others. Now you have to solve the data-integrity issues.

Will Hartung replied on Tue, 2008/05/27 - 1:23pm

The problems are legion with dynamic class loading. The various implementations do their best working within the constraints of the JVM, but Java simply isn't designed to handle dynamic class reloading. (It can load classes dynamically all day long, it's the reloading that's the nut).

The primary problem isn't the class. Classes are easy.

The problem is the instances of the class.

Current class reloading (notably hot swap) works fine for method changes, because the structure of the object doesn't change.

Add in an instance variable change, and all hell breaks lose.

First, there's no protocol within Java to manage instance change. First, there's no access to the OLD object (how do you access the field of an instance variable you're deleting?), next there's no method callback to change from Class Instance v1 to Class Instance v2. (say your original object has just "name" and you now wanted "firstName" and "lastName", with a proper instance change protocol, you could write a little function to split a 'name' in to their firstName and lastName components, otherwise you new objects will have null firstName and lastName, and no 'name' at all -- not very useful objects I think most would say.)

Next, there's memory management issues. All of the instance pointers to a class will need to be updated (you can't just necessarily change the instance "in place", the new instance may well be too big to fit in the old space). So, effectively you need to leverage the GC to update all of your new objects and their references. But the GC, currently, has no "concept" of what class an object is. It really doesn't care. It's all memory blocks and pointers.

Finally, there's all of the compiled code against the classes. They're all compiled with offsets, not labels. When you say "getTitle", the JVM knows the offset within the object structure to the "title" instance variable (if you had, say, 3 instance variables, title being the 3rd slot, all class references (vs, say, char or int), on a 32 bit machine, the slot would be "+8" from the object root, skipping the first 2 instance variables which are 4 bytes each in size). So, when an object changes, all of that code needs to be invalidated (actually it needs to be recompiled, since the compiler does the work, not the JVM).

Dynamic languages don't have this problem because they can handle missing slots or empty slots easily, since they're constantly looking stuff up. When you ask for the "title" slot, the runtime goes to the object, says "where is 'title'", the offset is looked up, and the reference made. All modern languages use aggressive caching, but in effect, at run time, these searches are constantly done over and over and over. Java does much of this at compile time.

Most dynamic languages written on top of the JVM, for example, don't use Java Classes at all for their instances, because they're so rigid.

All of these issues combine to making class reloading very problematic based on how the JVM and Java language are implemented.

 

Jevgeni Kabanov replied on Tue, 2008/05/27 - 4:18pm

@Will Hartung

All of the problems you described are solvable. You are forgetting that from the JIT point of view it is statically known, what existed originally and what was added later. Therefore the compiler can make informed decisions on direct v/s indirect lookups without compromising performance.

Mark Thornton replied on Tue, 2008/05/27 - 4:39pm

Suppose you change the internal representation of a point from cartesian (x,y) to polar (radius, angle) form. You need to provide a 'constructor' that will create the new version of a such an object from the old version. Java doesn't currently have a way of expressing this.

Will Hartung replied on Tue, 2008/05/27 - 4:47pm in response to: Jevgeni Kabanov

Of course they're solvable. But the effort required is quite large, and require fundamental changes to the JVM, and, perhaps, the compiler.

And all of the work needs to be contrasted with the actual value of the work. Now, there CAN be value in having dynamically reloadable classes, outside of simply fast development turnaround. Patching a "live" server for example.

But it turns out that in truth, and in practice, while the feature may be a "nice to have", it's hardly a necessity. Change "reloadable class" to "reloadable server" in the context of a server farm, and you get pretty much the same functionality while still being able to maintain an SLA. When sites get large enough to need to service large traffic "24x7", they inevitably end up with this kind of architecture anyway.

And for small sites, restarts simply aren't that crippling.

If the feature were there, I'd use it. But at this juncture, I frankly don't think it's worth the engineering to enable it. Dynamic languages won't leverage the internal JVM class structure simply because the power of a dynamic language happens to come from their own internal world view of how artifacts like classes should be structured, and many of them simply don't map on to the view of the JVMs.

Now, you could perhaps re-engineer the JVM to be a better "dynamic class" style VM, of which Java is a simple subclass, and maybe as dynamic languages become more popular, the JVM will drift that way to better support these other languages. Even then though, that doesn't necessarily mean the Java will actually gain that capability, as the underlying object model will have to be exported in to "java" terms, which implies some language design, and all of those ramifications.

So, yea, it's doable. It's a LOT of work. And most likely, not worth the effort in the end beyond bullet point compliance.

 

Alex(JAlexoid) ... replied on Tue, 2008/05/27 - 5:53pm in response to: Will Hartung

Are you aware of the thing called serialization?
We have been succesfully managing changes in classes while using serialization. (Ask Jevgeni Kabanov how JavaRebel manages it)
The problem is not That we can't, it's that we are afraid.

Though I don't claim to be JVM specialist, your arguments about the low level stuff sound ill informed....
FYI: If I remember correctly getting a fields value in bytecode actually requires you to supply the field name.

And BTW was I imagineing it, or did the guys at Sun say something along the lines: "No more 'Java VM' it going to be just 'VM'"?

Will Hartung replied on Tue, 2008/05/27 - 7:15pm in response to: Alex(JAlexoid) Panzin

Serialization is used to get objects in and out of the JVM, it's not an in JVM object mutation protcol. It can be made version aware, but, again, that's not the same thing as an intra-jvm mutation process. Specifically, serialization is taking data from outside the JVM and injecting it in to the JVM. When that happens, the serialization code has some certain assumptions about what it's doing, and how it's doing it.

If you, say, implement Externalizable, then the external representation can be pretty much anything. While, naievely, you can think it might be usable for converting objects, it's simply not safe to assume it will work. Plus, by default, the Java Serialization protocol tends to go quite deep (i.e. beyond the individual class being mutated) and can be quite expensive.

I have no idea how JavaRebel manages this problem and I don't see any documentation on their site addressing the issue, so I can't comment on what or how they do whatever they do. But, as the other example cited here of changing a class Point from being a cartesian representation to a polar one, I don't see how that would be accomplished with JavaRebel.

The JVM addresses instance variables via offset, they use a simple slot index for each variable, all of which are the same size (unlike, say, C). That is a char == an int == a long == an object pointer in terms of actual storage within the JVM when stored as an instance variable (in most JVMs, that's 32 bits -- obviously this would be different in a 64-bit JVM).  Mind, I'm only repeating what I said before, so you can choose not to believe me now as you did then.

While Sun may well want to move the JVM to simply "the VM", and that's fine, there is still a harsh reality that dynamic languages face in order to be implemented on top of the JVM (on top of anything, in fact). They are making strides to facilitate dynamic language development on the JVM, and make it a more friendly place. However, none of those changes are as dramatic as what's necessary to implement the dynamic reloading capabilities discussed here, with full support at the JVM level, much less within the actual Java language implementation built on top of the JVM.

The work is not trivial. It's a lot of work that affects not just the base JVM, it class structure, its byte code, etc., but also has a ripple effect with all of the optimizers and JIT compilers within the system. They have a world view that they leverage. Change the fundamentals, and there's a lot of work to be redone even to get back to state that we are now in terms of performance and functionality (which happens to be VERY good).

So, yea, maybe "they" are "afraid" to persue this. I don't think that's the case, nothing to "fear" here, but they may well have considered the cost and gain of such a endeavor and decided it's not worth it to them.

If you disagree, feel free to head over to OpenJDK and fix it.

 

Alex(JAlexoid) ... replied on Wed, 2008/05/28 - 6:05am in response to: Will Hartung

[quote]Serialization is used to get objects in and out of the JVM, it's not an in JVM object mutation protcol.[/quote]

 But serialization does manage differences in versions, to some extent. 

[quote]The work is not trivial. It's a lot of work that affects not just the
base JVM, it class structure, its byte code, etc., but also has a
ripple effect with all of the optimizers and JIT compilers within the
system. They have a world view that they leverage. Change the
fundamentals, and there's a lot of work to be redone even to get back
to state that we are now in terms of performance and functionality
(which happens to be VERY good).[/quote]

I don't know are you talking about adding dynamic elements to JVM or class reloading.
In case of dynamic class reloading - remember that with Instrumentation API we already have  the ability to redefine methods' contents, so I bet the groundwork is already there. Without lost performance.

Will Hartung replied on Wed, 2008/05/28 - 12:00pm in response to: Alex(JAlexoid) Panzin

[quote]But serialization does manage differences in versions, to some extent.[/quote]

Yes, it can, serialiazation of an object in and out of the JVM is a completely different problem from tranmuting a class instance structure within the JVM. The environment is different, the assumptions are different, and the use case is different.

Just as a trivial example, someone creating serialization code may very well want to reduce the volume of the data being read and written, and will make compromises and decisions based up that aspect of the process. Someone transmuting an instance for a dynamic class reload obviously doens't have that restraint. However, they DO have the restraint of trying to maintain the integrity of the identity of not just the object be transmuted, but of any related objects as well.

So while Serialization certainly needs to be version aware, the role of the process is completely different from something designed to transmute existing instances.

[quote]In case of dynamic class reloading - remember that with Instrumentation API we already have the ability to redefine methods' contents, so I bet the groundwork is already there. Without lost performance. [/quote]

Changing method implementations are not the problem. That's trivial, as evidenced by the fact we do that already. It's trivial because all it affects is the implementation of a method, of which there is only one in the entire system, and it's referenced via a lone pointer in a lone table. Write a new method, update a pointer, shazam, instant new method.

The problem is changing the structure of the class. Adding and removing instance variables to the class, changing the interpretation of the state of existing variables without actually updating the state (the cartesion vs polar Point representation for example), changing method signatures, etc. That's the crux of the issue.

Java is not a dynamic language, and makes assumptions about class layout because it "knows" that the class layout is static! It makes assumptions about the return types, and calling stack frames, again, because they're static.

When the class changes in a dramatic way, code needs to be recompiled.

All of that needs to be taken in to account to facilitate the reloading of arbitrary Java classes within the JVM. That's what makes the problem difficult.

 

Honey Monster replied on Wed, 2008/05/28 - 5:30pm in response to: Jevgeni Kabanov

AFAIK .NET does not reload code, it does full redeploy juts like Java, just application start usually will take less.

Actually .NET use a measured approach. It is true that the server "observes" directories for changes. If it sees certain changes it will spin up a new appdomain (roughly comparable to a process) for handling new requests, however it will retain the JITed versions of the unchanged assemblies and only JIT the changed assemblies. The "old" appdomain will be drained, i.e. it will receive no more requests. Once it has completed all of its running requests it will be unloaded.

You can also just copy source code directly to designated directories and the server will automatically compile those into assemblies. Pages and other "handlers" (servlets) can be deployed this way. These "top-level" assemblies can change without the appdomain being recycled. The server will allow a certain amount of these to change and merely load the new assemblies. The old assemblies will remain loaded but unused (assemblies can only be unloaded with the termination of the appdomain).

All in all this stuff actually works. You can code ASP.NET just like PHP: Use notepad to edit files and simply upload them to the server. No restart, no compilation (that you are aware of) is nessecary. This goes even for C#/VB.NET code and configuration changes: Change a setting and it will look like the app/site picked it up right away.

There's one drawback: Anything in the session is lost when the appdomain recycles, if you use the in-process session store. If that's a concern you would typically use the special "session state server" (a daemon) or store session state in the database.

It seems to me that this is a much simpler and above all guaranteed approach. There's no need to mutate objects already in memory. Objects stored in the session can be retained, but will already be "serialization aware" and can thus cater for version changes. It will not affect global optimizations or inlining. It will deal with all types of changes, including changes to class hierarchy, public interfaces, field layout, static contexts etc. The real challenge is really only to get the new process to spin up fast enough.

mike replied on Wed, 2008/05/28 - 8:13pm

It sounds like what you're saying is that as long as you only change classes in .net that are frequently disposed of, then you're OK. You're saying it maintains the old versions along with the new versions (not mixing the two) until the old ones are no longer used. Then when nothing is using the old class, it permanantly unloads it. Correct? So, if you change several classes including one for an object that lives for the life of the server; then essentially, no classes get reloaded in practice. The eternal class will always be the old version and if all of it's objects are spawned from it, it must hold onto the old versions. Correct?

Mark Thornton replied on Thu, 2008/05/29 - 2:40am in response to: Honey Monster

[quote=honeymonster]

Actually .NET use a measured approach. It is true that the server "observes" directories for changes. If it sees certain changes it will spin up a new appdomain (roughly comparable to a process) for handling new requests, however it will retain the JITed versions of the unchanged assemblies and only JIT the changed assemblies.[/quote]

Retaining the existing compiled versions may be easier for .NET as I believe its optimisations are far less aggressive than those used in the Java server VM.

Paul Keeble replied on Thu, 2008/05/29 - 7:06am

Why not embed an interpreter that works directly on the Java source code? Then the structure is parsed as its run and the objects associated with the source code are already known to be completely dynamic and held in a different way.

This suggests a more dynamic structure to hold the objects themselves. By removing some of the restrictions on how its represented it should be possible to come up with a reasonable set of rules on what to do with old code. You no longer have to produce valid byte code so old objects passed into new code can simply bomb with a version conflict. Its not like it'll cover 100% of all conditions perfectly, but at least if it hits 95% it'll be a lot better than it is today.

 

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.