...
>I heard about ClassLoader and its caching functionnality ... ?

Signature
Andrew Thompson
http://www.athompson.info/andrew/
> ...
>> I have a standalone Java application which has to be started and then
[quoted text clipped - 4 lines]
>
> Not that I know of, but happy to be surpised.
Then be happy. It's possible using the debugger hooks. There was an article
by Daniel Savarese in JavaPro about it, probably still findable.
You can also play ClassLoader games to load the new version, letting the old
one die and get garbage collected, but getting client classes to recognize the
switch is hard, from what I hear. I tend to avoid such complications.

Signature
Lew
Piotr Kobzda - 27 Jul 2007 00:55 GMT
>> Not that I know of, but happy to be surpised.
>
> Then be happy. It's possible using the debugger hooks. There was an
> article by Daniel Savarese in JavaPro about it, probably still findable.
I didn't found it. But now (since 1.5) the instrumentation allows it also:
<http://java.sun.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#
redefineClasses(java.lang.instrument.ClassDefinition...)>
The only JVM I know, which fully supports it (including "schema change"
HotSwap) is the J9VM (from IBM).
Fortunately, most of major JVMs allows for redefining executable code of
a class, which usually is enough. If not enough...
> You can also play ClassLoader games to load the new version, letting the
> old one die and get garbage collected, but getting client classes to
> recognize the switch is hard, from what I hear. I tend to avoid such
> complications.
It depends on what is expected. Sometimes it's also desired to have the
old clients still using old versions of the classes, and a new classes
available for the new clients only (see "Hot Code Changes" section at
Java Glossary page linked by Roedy). Otherwise, you may reference all
objects non-directly, e.g. via the map (or cache). But, of course,
using instrumentation (or JPDA) is easier in such a case.
piotr
O.L. - 27 Jul 2007 12:38 GMT
Piotr Kobzda a formulé la demande :
> Fortunately, most of major JVMs allows for redefining executable code of a
> class, which usually is enough.
How ?

Signature
Olivier Ligny
www.virgal.net (Monde persistant)
Piotr Kobzda - 27 Jul 2007 13:27 GMT
> Piotr Kobzda a formulé la demande :
>> Fortunately, most of major JVMs allows for redefining executable code
>> of a class, which usually is enough.
>
> How ?
As I said -- using Java instrumentation.
With that, you will not have to care about class loading and references
to them, you will need simply replace already running classes with
theirs new bytes (loaded or generated at runtime).
For details refer to:
<http://java.sun.com/javase/6/docs/technotes/guides/instrumentation/index.html>
In particular, read the java.lang.instrument package description. Usage
is explained there clearly.
piotr
Twisted - 27 Jul 2007 11:36 GMT
> > ...
> >> I have a standalone Java application which has to be started and then
[quoted text clipped - 11 lines]
> one die and get garbage collected, but getting client classes to recognize the
> switch is hard, from what I hear.
If you only want newly created objects to use the new version of the
class, you could create these objects via a Factory that uses
reflection to dynamically load the latest class version if newer than
what it's currently using, and then to generate an instance of the
current version (whether that was just updated or not), when invoked.
O.L. - 27 Jul 2007 12:41 GMT
Il se trouve que Twisted a formulé :
>>> ...
>>>> I have a standalone Java application which has to be started and then
[quoted text clipped - 17 lines]
> what it's currently using, and then to generate an instance of the
> current version (whether that was just updated or not), when invoked.
Thank you :)
I suppose this will cause problems with 'instanceof' and old/new
instances, but I think this is the best (and only) solution.

Signature
Olivier Ligny
www.virgal.net (Monde persistant)
Twisted - 27 Jul 2007 13:58 GMT
> I suppose this will cause problems with 'instanceof' and old/new
> instances, but I think this is the best (and only) solution.
Use instanceof on a common supertype, e.g. have WhateverBase and make
WhateverDerived1, WhateverDerived2, etc. be your versions. If they
adhere to a common contract checking for being "instanceof
WhateverBase" should suffice where you are forced somehow to use
instanceof and not polymorphism.
Maybe equals()? Define that in WhateverBase in terms of contract
methods if possible. If you must do special stuff depending on exact
implementation, make WhateverBase have a getVersion method and write:
(in WhateverBase)
public final boolean equals (Object o) {
if (this == o) return true;
if (o == null || !(o instanceof WhateverBase)) return false;
WhateverBase wb = (WhateverBase)o;
if (wb.getVersion() > getVersion()) return wb.equalsImpl(this);
return equalsImpl(wb);
}
protected abstract int getVersion ();
protected abstract boolean equalsImpl (WhateverBase wb);
(in WhateverDerived1)
protected int getVersion () { return 1; }
protected boolean equalsImpl (WhateverBase wb) {
WhateverDerived1 wd = (WhateverDerived1)wb;
// Whatever to compare two WhateverDerived1s
return something;
}
(in WhateverDerived2)
protected int getVersion () { return 2; }
protected boolean equalsImpl (WhateverBase wb) {
if (wb instanceof WhateverDerived1) return
equalsImpl2((WhateverDerived1)wb);
WhateverDerived2 wd = (WhateverDerived2)wb;
// Whatever to compare two WhateverDerived2s
return something;
}
private boolean equalsImpl2 (WhateverDerived1 wd) {
// Whatever to compare a WD2 and a WD1
return something;
}
I trust you see the pattern here. The key thing is to assign version
numbers sequentially. Each class needs to know how to compare itself
to each previous version, and needs its equalsImpl to be the one that
gets called. If you do otherwise the code will break -- it will
sometimes call an old version equalsImpl with a newer version
parameter and consequently throw a ClassCastException on the last cast
in the called equalsImpl method.
This is assuming all the WDs extend WB directly, never each other,
which I'll also recommend to ensure the CCE is thrown instead of
subtler broken behavior occurring instead, such as simply wrong return
values from some calls to equals().
This can be generalized to anything else that needs to effectively
dispatch on two run-time types and not just one. It won't be nearly as
easy or tidy however if you end up with two different serially-
versioned types and a binary operation between them...