consumption

B

Ben Wilson

Hi, everyone,

I've google'd all around for an answer to this, but I'm not satisfied with
what I've found. Hope someone can help.

I've got a conceptual problem of consumption. I'm making instances of
complicated objects, and whenever I need a new one, I just make a new one
with the new keyword. All the initialisation is put nice & where it belongs
in the initializers and the constructors. If I have an old object but want a
new one, it's handy that I've got everything in the initializers and
constructors. I just forget about the old one, let garbage collection take
care of it, and create my new object by passing parameters to the
constructors and maybe tweaking a few fields. This is comsumption and it's
great.

Now, what if I want to do this with the entire class? And reinitialise all
of the static data? By using all of the initializers, instead of going in
and manually resetting everything to its original state?

The only things I've been able to find are pooh-poohing "you should never
have to unload a class" and recommendations that "unloading classes should
never reset static data". But what if that is exactly what I want? If we're
talking about instances, what I certainly DON'T do would be to take an
existing instance, invoke some method that does everything my constructor
does and reset the values of fields to whatever they were originally.

From a design perspective, it feels wrong to have to re-code all of the
class-level initialization logic in some method with an arbitrary name. This
is just duplicate code. What can you do in Java to make this happen for
static?

Thanks in advance,

Ben.
 
A

Adam

Ben Wilson said:
Hi, everyone,

I've google'd all around for an answer to this, but I'm not satisfied with
what I've found. Hope someone can help.

I've got a conceptual problem of consumption. I'm making instances of
complicated objects, and whenever I need a new one, I just make a new one
with the new keyword. All the initialisation is put nice & where it belongs
in the initializers and the constructors. If I have an old object but want a
new one, it's handy that I've got everything in the initializers and
constructors. I just forget about the old one, let garbage collection take
care of it, and create my new object by passing parameters to the
constructors and maybe tweaking a few fields. This is comsumption and it's
great.

Now, what if I want to do this with the entire class? And reinitialise all
of the static data? By using all of the initializers, instead of going in
and manually resetting everything to its original state?

The only things I've been able to find are pooh-poohing "you should never
have to unload a class" and recommendations that "unloading classes should
never reset static data". But what if that is exactly what I want? If we're
talking about instances, what I certainly DON'T do would be to take an
existing instance, invoke some method that does everything my constructor
does and reset the values of fields to whatever they were originally.

From a design perspective, it feels wrong to have to re-code all of the
class-level initialization logic in some method with an arbitrary name. This
is just duplicate code. What can you do in Java to make this happen for
static?

Thanks in advance,

Ben.

Not sure if i'm understanding what you want, but you could create a static
method which initialises all the static variables, and call this from
static{}:

class MyClass{
static{
//gets called when class is loaded
initStatic();
}

static void initStatic(){
//initialization stuff
}
}

That way you can reset everything by calling initStatic, and you don't need
to duplicate any code.

adam
 
B

Ben Wilson

Adam said:
Not sure if i'm understanding what you want, but you could create a static
method which initialises all the static variables, and call this from
static{}:

class MyClass{
static{
//gets called when class is loaded
initStatic();
}

static void initStatic(){
//initialization stuff
}
}

That way you can reset everything by calling initStatic, and you don't need
to duplicate any code.

adam


Thanks for the idea, Adam,

Unfortunately, the objects of my class make use of finalize() and in this
code they fiddle with the static elements. I want to get rid of everything,
(classes, instances) and set it all to the way it was in the very beginning.
If I do it the way you suggested, I'll still run the risk that instances
left over from before my static "reinitialization" would be gc'd after
calling the initStatic(). I could of course keep track of all of the
instances in a static ArrayList or so, but that would prevent the normal gc
from working so I don't see the solution there.

What I really want to do is to [ctr][alt][del] the whole shabang and let the
class initialization run its normal course. I honestly am not sure whether
Java allows you to do that in a predictable way.

B.
 
D

David Hilsee

Ben Wilson said:
Unfortunately, the objects of my class make use of finalize() and in this
code they fiddle with the static elements. I want to get rid of everything,
(classes, instances) and set it all to the way it was in the very beginning.
If I do it the way you suggested, I'll still run the risk that instances
left over from before my static "reinitialization" would be gc'd after
calling the initStatic(). I could of course keep track of all of the
instances in a static ArrayList or so, but that would prevent the normal gc
from working so I don't see the solution there.

What I really want to do is to [ctr][alt][del] the whole shabang and let the
class initialization run its normal course. I honestly am not sure whether
Java allows you to do that in a predictable way.

It sounds like you do not merely want to eliminate some code duplication.
Now, it sounds like you are trying to do something much harder than that,
like implement an object cache where you can clear all of the objects from
the cache. That was just a guess. If you explained what your code is doing
and what you are trying to accomplish, people may be able to help you. Of
course, the suggested implementations may require you to rewrite some of the
code.
 
B

Ben Wilson

David Hilsee said:
It sounds like you do not merely want to eliminate some code duplication.
Now, it sounds like you are trying to do something much harder than that,
like implement an object cache where you can clear all of the objects from
the cache. That was just a guess. If you explained what your code is doing
and what you are trying to accomplish, people may be able to help you. Of
course, the suggested implementations may require you to rewrite some of the
code.

Hi, David:

I might be overcomplicating the situation with textal explanations. The
issue is deceptively simple. I'll condense it to a sample that (I hope)
illustrates it better:


class myClass
{
static int instanceCounter = 0;

myClass()
{
instanceCounter++;
}

protected void finalize()
{
instanceCounter--;
}

}

There you go - I've got this class, and at runtime I create a couple of
instances by saying "new myClass()". For argument's sake let's say this was
part of Process#1 and as a part of Process#1 I want to monitor
instanceCounter. Later, what I want to do is to start Process#2, #3, #4,
etc. I want a separate space where the instanceCounter starts off at zero
and I can create new objects, without any interference from whatever I
constructed as part of Process#1. Once Process#2 starts I don't care about
anything that was created in Process#1. Process#1 is over. Forgotten.

Sure I could manually say "myClass.instanceCounter = 0" however the garbage
collection of the objects created in the previous Process will interfere
with this. The old objects of Process#1 will get cleaned up and the
instanceCounter will go down during Process#2, which is unacceptable.

Any ideas?

B.
 
D

David Hilsee

Ben Wilson said:
Hi, David:

I might be overcomplicating the situation with textal explanations. The
issue is deceptively simple. I'll condense it to a sample that (I hope)
illustrates it better:


class myClass
{
static int instanceCounter = 0;

myClass()
{
instanceCounter++;
}

protected void finalize()
{
instanceCounter--;
}

}

There you go - I've got this class, and at runtime I create a couple of
instances by saying "new myClass()". For argument's sake let's say this was
part of Process#1 and as a part of Process#1 I want to monitor
instanceCounter. Later, what I want to do is to start Process#2, #3, #4,
etc. I want a separate space where the instanceCounter starts off at zero
and I can create new objects, without any interference from whatever I
constructed as part of Process#1. Once Process#2 starts I don't care about
anything that was created in Process#1. Process#1 is over. Forgotten.

Sure I could manually say "myClass.instanceCounter = 0" however the garbage
collection of the objects created in the previous Process will interfere
with this. The old objects of Process#1 will get cleaned up and the
instanceCounter will go down during Process#2, which is unacceptable.

Any ideas?

How about an extra level of indirection?

private static class Counter {
public int instances = 0;
}

private static Counter globalCounter = new Counter();
private Counter myCounter = globalCounter;

public myClass() {
myCounter.instances++;
}

protected void finalize() {
myCounter.instances--;
}

To reset the global counter, just set the global counter (globalCounter =
new Counter();). Those instances that were created before the counter was
reset will be referencing the discarded counter and therefore will not
affect the new counter. If ths will not work, let me know.
 
M

Michael Borgwardt

Ben said:
From a design perspective, it feels wrong to have to re-code all of the
class-level initialization logic

From a design perspective, it feels wrong to HAVE a significant amount
of class-level initializaton logic and use finalize(). To me, anyway.

Still, I think it might be possible to achieve the behaviour you desire
if you load all the classes through a custom classloader and when you
want to "reset" it, you change to a new classloader instance.
 
S

Stefan Schulz

Ben said:
class myClass
{
static int instanceCounter = 0;

myClass()
{
instanceCounter++;
}

protected void finalize()
{
instanceCounter--;
}

}

There you go - I've got this class, and at runtime I create a couple of
instances by saying "new myClass()". For argument's sake let's say this was
part of Process#1 and as a part of Process#1 I want to monitor
instanceCounter. Later, what I want to do is to start Process#2, #3, #4,
etc. I want a separate space where the instanceCounter starts off at zero
and I can create new objects, without any interference from whatever I
constructed as part of Process#1. Once Process#2 starts I don't care about
anything that was created in Process#1. Process#1 is over. Forgotten.

Hmm, i would do so by adding an explicit dispose() method to your
Objects. This method signifies that these Objects are no longer "valid".
Whenever you make a new Object, it leaves one of its References (a
WeakReference?) in some static collection of the class. Once you call
initialize, you just dispose all preexisting instances.

Something like this:

class myClass {
static int instances = 0;
static Collection instance =
Collections.synchronizedList(new ArrayList);

boolean disposed = false;

myClass() {
instances++;
instance.add(new WeakReference(this));
}

public void finalize(){
dispose();
}

public void dispose(){
if (!disposed)
instances--;
disposed = true;
}

static {
init();
}

private static void init() {
for (Iterator i = instance.iterator; i.hasNext();){
WeakReference wr = (WeakReference) i.next();
myClass mc = (myClass) wr.get();
if (mc != null)
mc.dispose();
}
}
}
 
C

Chris Uppal

Ben said:
There you go - I've got this class, and at runtime I create a couple of
instances by saying "new myClass()". For argument's sake let's say this
was part of Process#1 and as a part of Process#1 I want to monitor
instanceCounter. Later, what I want to do is to start Process#2, #3, #4,
etc. I want a separate space where the instanceCounter starts off at zero
and I can create new objects, without any interference from whatever I
constructed as part of Process#1. Once Process#2 starts I don't care about
anything that was created in Process#1. Process#1 is over. Forgotten.

Look for the objects.

You have a population of instances of myClass, and you have some housekeeping
data associated with that population. At times to be determined by you, you
wish to switch to creating a new population and maintaing the housekeeping data
for the new group of instances without interferance from the old group. Yes ?

If so, then I would say that it's obvious that you need an object with the
responsibility for maintaining the housekeeping for a /specific/ population.
Static data is simply not appropriate for this task (unless you take Gordon's
suggestion and use classloaders -- in which case you are using the "class" much
more like a real object).

So you have a Housekeeper:

class MyClass
{
static class Housekeeper
{
private int instances;
synchronized void addOne() { instances++; }
synchronized void removeOne() { instances--; }
}

static Housekeeper currentHouseKeeper;

static { resetHousekeeping(); }

static void resetHousekeeping()
{
currentHouseKeeper = new Housekeeper();
}

// the housekeeper that knows about /this/ instance
private final Houskeeper myHousekeeper = currentHouseKeeper;

MyClass()
{
myHouskeeper.addOne();
}

protected void finalize()
{
myHouskeeper.removeOne();
}
}

This is pretty much the same as David's suggestion. The big difference is that
I'm claiming that good OO design leads to this solution, rather than presenting
it as workaround for something that is otherwise needlessly difficult to
express in Java.

-- chris
 
S

Scott Ellsworth

Ben Wilson said:
Now, what if I want to do this with the entire class? And reinitialise all
of the static data? By using all of the initializers, instead of going in
and manually resetting everything to its original state?

One reason why you have seen so much pooh-poohing is the inability to
control when classes are gc'ed and to force a class to be unloaded.

As time has gone on, the Java community has pretty much concluded that
finalizers are probably not the best place to release scarce resources.
(I do wish that Sun had a gc interface or some other means to encourage
collecting scarce resources so finalizers could be used for this, but
they do not. Sigh.)

Thus, there is not a lot of push at Sun to make finalizers a good idea,
and thus they are not really pushing for class unloads. Sigh.

Short form: you need to handle static resets yourself. Given that, you
have to decide how. There are a number of ways, such as lazy init,
smart factories that track what they have made, or ignoring the issue
until usage shows what real world problems you will encounter. (For
example, if your concern is that your statics might blow out memory,
then you can use a weak hash map to hold them, and a lazy initializer to
rebuild them. Then, as long as you do not run out of RAM, you do not
unload anything. Once you do, stuff you do not need will vanish behind
the scenes.)

I usually solve this by having my statics created by lazy
initialization. This usually means that the singleton provider or
factory has that init logic. If I then want to unload, I have a second
unloader that does the evil magic, and if I need it, then I usually
create a thread that does the cleanup every ten seconds or so.

The unloader is not duplicate code, as that code does not exist anywhere
else in my class. The factory for each static item is also not
duplicated code, as it is what is used in the first place.

Scott
 
C

Chris Uppal

I said:
class MyClass
{
static class Housekeeper
{
private int instances;
synchronized void addOne() { instances++; }
synchronized void removeOne() { instances--; }
}

static Housekeeper currentHouseKeeper;

....etc...

I should add that if the housekeeping is really as simple as in this little
example -- the objects have no need to interact with the housekeeper except at
birth and death -- then a reference queue may provide a good basis for tracking
demographics without explicit code in the trackees.

-- chris
 
M

Markus Schaber

Hi, Ben,

I could of course keep track of all of the instances in a static
ArrayList or so, but that would prevent the normal gc from working so
I don't see the solution there.

Did you have a look at weak references?
What I really want to do is to [ctr][alt][del] the whole shabang and
let the class initialization run its normal course. I honestly am not
sure whether Java allows you to do that in a predictable way.

May be you could use inner classes. Rough Idea:

- Move all your instances to the inner class.

- Make all your static things to instance attributes of the outer class.

- Create instance methods at the outer class which wrap all constructors
and static factory methods of your inner class.

- Then create a single instance of the outer class that is statically
referenced by the outer class.

Now, the inner class instances can fiddle with the singleton outer
object, and foreign code can reach the singleton via the static
reference.

For your "reset", simply create a new singleton outer class instance and
assign it to the static reference.

I hope it's understandable...

Markus
 
M

Markus Schaber

Hi, Ben,

class myClass
{
static int instanceCounter = 0;

myClass()
{
instanceCounter++;
}

protected void finalize()
{
instanceCounter--;
}

}

Hmm, try the following (using inner classes):

public class InstCounter {
private static InstCounter inst;
static {
reset();
}

public static InstCounter instance() {
return inst;
}

public static void reset() {
inst = new InstCounter();
}

public myClass getMyClass() {
return new myClass();
}

int instanceCounter = 0;

class myClass {
myClass() {
instanceCounter++;
}

protected void finalize() {
instanceCounter--;
}
}
}

HTH,
Markus
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top