Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Unloading/Reloading classes  (Read 2725 times)
0 Members and 1 Guest are viewing this topic.
Offline crazyc94

Senior Newbie




I like cheese


« Posted 2007-09-19 14:34:10 »

Ok, I know this is an odd question, but does anyone know if it's possible to unload one version of a class instance, and load a different version of the same class instance?

I've been reading the JLS, and it mentions Class Unloading, however as the JVM gives no guarantees about garbage collection, I'm a little hesitant to try and write code that depends explicitly on it.  This still doesn't get past if it's possible to eventually load 2 different versions of the same class.

Naturally, all instances of the inital version would be de-referenced before attempting to unload the class/classloader (I'd gladly write a custom one to do this Grin).

I'm more worried if the JVM prevents actions like this then the actual version details.


And no, restarting the process isn't an option here  Tongue  Wink

Quack!  I'm a duck!

"Or make your own RationalNumber class (unless you need irrational numbers, then you're screwed )." - shmoove
Offline princec

JGO Kernel


Medals: 284
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2007-09-19 14:46:52 »

Basically you need to create a custom classloader and load the class with that. That effectively gives you an entirely different version of the class; however, only subsequent code loaded by that customer classloader will be able to see it. The old class will only be unloaded by the VM when it can be garbage collected.

Cas Smiley

Offline crazyc94

Senior Newbie




I like cheese


« Reply #2 - Posted 2007-09-20 01:47:11 »

So the JVM won't error out at me, I just won't be able to see it with classes loaded by another classloader...

Hrm, that puts a kink in things  Undecided

Thanks for the fast reply princec  Smiley

Quack!  I'm a duck!

"Or make your own RationalNumber class (unless you need irrational numbers, then you're screwed )." - shmoove
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 284
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #3 - Posted 2007-09-20 13:19:28 »

What are you doing this for anyway?

Cas Smiley

Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #4 - Posted 2007-09-20 13:51:50 »

So the JVM won't error out at me, I just won't be able to see it with classes loaded by another classloader...

Hrm, that puts a kink in things  Undecided

Thanks for the fast reply princec  Smiley

No, that doesn't put a kink in anything, surely?

1. The OBJECTS created from different classes can all still interact without problems. In fact, the only problems you will see are that newly instantiated objects will fail the "instanceof" check, and that typecasts to the class will typecast to the new version even if the instance is of the old version.

NB: this is one of my suspicions about autoboxing - surely inserting typecasts in code is not a good idea, generally speaking, in a language where typecasts themselves refer to something dynamic?

2. Just make sure all the classes that you AREN'T changing are visible in both classloaders. This is actually *trivial* because java's default behaviour is to have a chain of classlaoders so that you implement the custom loading for one class and you automaticallly inherit the loading of all other classes without having to write any code for it.


Or ... I think, maybe (not sure here): you can create a custom classloader that returns a different class object at different times. This requires some mangling of the classloader chain as well, from memory - you need to make sure that the new class you're sending doesn't get cached when you want to replace it with a newer one.

(he says, from distant memories of how he did this last time).

I've certainly done it before, I just can't 100% remember how right now.

malloc will be first against the wall when the revolution comes...
Offline cylab

JGO Knight


Medals: 34



« Reply #5 - Posted 2007-09-20 14:03:37 »

1. The OBJECTS created from different classes can all still interact without problems. In fact, the only problems you will see are that newly instantiated objects will fail the "instanceof" check, and that typecasts to the class will typecast to the new version even if the instance is of the old version.
Actually this bombs out with a ClassCastException

2. Just make sure all the classes that you AREN'T changing are visible in both classloaders. This is actually *trivial* because java's default behaviour is to have a chain of classlaoders so that you implement the custom loading for one class and you automaticallly inherit the loading of all other classes without having to write any code for it.
The problem is, that Java returns the class loaded by the parent classloader by default, so you have to override this behaviour, which causes other problem with dynamic classloading via Class.forName() and getClassloader().getClass().

Or ... I think, maybe (not sure here): you can create a custom classloader that returns a different class object at different times. This requires some mangling of the classloader chain as well, from memory - you need to make sure that the new class you're sending doesn't get cached when you want to replace it with a newer one.
Hmm, I consider this advice the direct road to infinite pain Wink

Just avoid custom classloading whereever possible Wink

Mathias - I Know What [you] Did Last Summer!
Offline crazyc94

Senior Newbie




I like cheese


« Reply #6 - Posted 2007-09-20 14:56:38 »

No, that doesn't put a kink in anything, surely?

1. The OBJECTS created from different classes can all still interact without problems. In fact, the only problems you will see are that newly instantiated objects will fail the "instanceof" check, and that typecasts to the class will typecast to the new version even if the instance is of the old version.

Ok, that they can interact is a relief. 
Now to ask for some clarification (taking part of this from cylab's post as well):
I'm going to be using this system (assuming I can get it to work  Wink) as a way to load different versions of plugins.  All plugins implement one interface, and depending on what functionality they provide, they implement one or more sub-interfaces (that extend the base plugin interface).
Assuming I load the interfaces with the bootstrap classloader, would different instances of the plugin class (loaded by custom classloaders, different instances for each version) still be castable to the plugin interface (and the relevant sub interfaces)?  Or would that cause a ClassCastException?

NB: this is one of my suspicions about autoboxing - surely inserting typecasts in code is not a good idea, generally speaking, in a language where typecasts themselves refer to something dynamic?

2. Just make sure all the classes that you AREN'T changing are visible in both classloaders. This is actually *trivial* because java's default behaviour is to have a chain of classlaoders so that you implement the custom loading for one class and you automaticallly inherit the loading of all other classes without having to write any code for it.

Yes, I was already planning on a custom classloader, so I don't see this being hard to implement.

Or ... I think, maybe (not sure here): you can create a custom classloader that returns a different class object at different times. This requires some mangling of the classloader chain as well, from memory - you need to make sure that the new class you're sending doesn't get cached when you want to replace it with a newer one.

(he says, from distant memories of how he did this last time).

I've certainly done it before, I just can't 100% remember how right now.

Well, if I understand the article correctly, when I want to unload a class, I need to de-reference all instances of classes loaded by a specific classloader, then de-reference the class loader itself.

Then (assuming the JVM actually unloads the classes and doesn't cache), I need wait for the class loader to be GC'd (to prevent caching of the classes), then create a new instance of the class loader and load up a different version of the class file.

At princec:

This is for a chat automaton I'm writing, it's going to be serving as a raid control "bot", so it needs maximum up-time.  I'd rather take the time to implement a complex solution like this, than listen to people whine at me for hours on end for a new version of a plugin crashing the bot and it not being able to work right, rather then being able to revert to an older plugin version  Roll Eyes Grin

:edit: fixed some abysmal spelling :/edit:

Quack!  I'm a duck!

"Or make your own RationalNumber class (unless you need irrational numbers, then you're screwed )." - shmoove
Offline cylab

JGO Knight


Medals: 34



« Reply #7 - Posted 2007-09-20 15:03:16 »

Then (assuming the JVM actually unloads the classes and doesn't cache), I need wait for the class loader to be GC'd (to prevent caching of the classes), then create a new instance of the class loader and load up a different version of the class file.

At princec:

This is for a chat automaton I'm writing, it's going to be serving as a raid control "bot", so it needs maximum up-time.  I'd rather take the time to implement a complex solution like this, than listen to people whine at me for hours on end for a new version of a plugin crashing the bot and it not being able to work right, rather then being able to revert to an older plugin version  Roll Eyes Grin

There is no need for a class being unloaded, as long as you make sure, only the new class is used to instanciate an object. There is also no problem regarding casts, if the interfaces are defined in a parent classloader - this does not even have to be the system or bootstrap classloader.

But don't take this easy. Classloaders are a pain in complex situation and are often the cause for memory-leaks. Actually all J2EE application servers discourage hot deployment in production environments because of this. Chances are high, that a classloader is never GCed. Google for classloader and memoryleak.

Edit: typos

Mathias - I Know What [you] Did Last Summer!
Offline princec

JGO Kernel


Medals: 284
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #8 - Posted 2007-09-20 17:49:08 »

I'm not so sure they leak as such but one problem is that once any other class is linked against that class it can't be GC'ed either. Meaning it's quite difficult to get rid of classes once they're loaded.

Cacs Smiley

Offline cylab

JGO Knight


Medals: 34



« Reply #9 - Posted 2007-09-20 18:04:52 »

You are right. There are several other problematic aspects with dynamic class loading like static members, thread locals, inherent parent class references in non-static inner classes etc., that result in dynamic loaded classes and the loading classloader not being GCed.

Mathias - I Know What [you] Did Last Summer!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Linuxhippy

Senior Member


Medals: 1


Java games rock!


« Reply #10 - Posted 2007-09-21 00:14:01 »

Its better to work with interfaces, and replacing one class with another but both share the same interface.
This way you don't rely on some implementation specific details, and thats the old-fashioned way how java-language-designers thought that this should be done Wink

lg Clemens
Offline blahblahblahh

JGO Coder


Medals: 1


http://t-machine.org


« Reply #11 - Posted 2007-09-21 13:34:07 »

Actually this bombs out with a ClassCastException

Ah, excellent - it didn't used to, and I filed a bug against the behaviour a long time ago Smiley. Glad to hear they made it an exception rather than a silent fail.

malloc will be first against the wall when the revolution comes...
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (55 views)
2014-04-15 18:08:23

BurntPizza (53 views)
2014-04-15 03:46:01

UprightPath (66 views)
2014-04-14 17:39:50

UprightPath (49 views)
2014-04-14 17:35:47

Porlus (66 views)
2014-04-14 15:48:38

tom_mai78101 (90 views)
2014-04-10 04:04:31

BurntPizza (151 views)
2014-04-08 23:06:04

tom_mai78101 (247 views)
2014-04-05 13:34:39

trollwarrior1 (204 views)
2014-04-04 12:06:45

CJLetsGame (211 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!