Resetting all fields/consecutive starts of a program

I

Icarus

The idea is the following:
I have a program that, after is has run, restarts itself right from
the beginning. The problem is that many fields still have values from
the last go, especially in Singleton classes, and aren't properly
resetted. But I want to have the exact same situation as if the
program has just started. Resetting the fields manually is a truckload
of work and prone to errors.

So, the question is: is there a way for a Java program to exit and
restart itself, thus creating the same situation as on the first
start?


A small example:

public class SomeClass{

private String someField = "Just initialized";

public static void main(String args){

// Start the usual work of the program
this.start();

// Restart the program in a way that all fields are initialized
like they were on startup,
// WITHOUT manually setting all fields to their old values
this.restart();
}

private void start(){
System.out.println(this.someField );
this.someField = "Changed!";
}
}

How would the restart()-method have to look?
 
S

Stefan Ram

Icarus said:
and aren't properly resetted

»reset (...) past and past participle reset«

http://encarta.msn.com/encnet/features/dictionary/DictionaryResults.aspx?refid=1861700842

SCNR.
So, the question is: is there a way for a Java program to exit
and restart itself, thus creating the same situation as on the
first start?

It seems as if this is not a proper application for
singletons. You do not want singletons, but POJOs
(plain old Java objects), were each one is created
at the start of a main run and released at the end.

Otherwise, you could try to use a custom classloader
and create a new custom classloader for each main run,
then there would be a new copy of each singleton
(one per classloader). But this seems ugly.
 
L

Lew

If the singletons take significant memory, that may be the easiest way
of making sure the memory for the originals can be reclaimed.

But not as good or as easy as abandoning the singleton addiction and
just creating a new instance for each run.
 
T

Tom Anderson

The final possibility I can think of would be to launch a brand-new
JVM to run SomeClass, and let the original JVM exit after it launches
the child.

This is the right solution: simple and reliable. I'd drive the whole
process from a shell script.

tom
 
W

Wojtek

Lew wrote :
But not as good or as easy as abandoning the singleton addiction and
just creating a new instance for each run.

There are valid reasons for using singletons.

Any class which is expensive to setup, yet who's information does not
change should be a singleton.

Within a Web application, the Application class. Initialized on
startup, then used by every servlet

Statistics keeping classes.
 
D

Daniel Pitts

Icarus said:
The idea is the following:
I have a program that, after is has run, restarts itself right from
the beginning. The problem is that many fields still have values from
the last go, especially in Singleton classes, and aren't properly
resetted. But I want to have the exact same situation as if the
program has just started. Resetting the fields manually is a truckload
of work and prone to errors.

So, the question is: is there a way for a Java program to exit and
restart itself, thus creating the same situation as on the first
start?


A small example:

public class SomeClass{

private String someField = "Just initialized";

public static void main(String args){

// Start the usual work of the program
this.start();

// Restart the program in a way that all fields are initialized
like they were on startup,
// WITHOUT manually setting all fields to their old values
this.restart();
}

private void start(){
System.out.println(this.someField );
this.someField = "Changed!";
}
}

How would the restart()-method have to look?

That is one of the reasons Singletons are "a bad thing" in a lot of
situations. They have there uses, but more often abuses.

The quickest solution is probably to integrate with a Shell Script
(windows BAT file, or .sh file on Linux/Unix, not sure on Macs). Just
have a special return value that means "restart the process".
 
O

Owen Jacobson

Lew wrote :

There are valid reasons for using singletons.

Any class which is expensive to setup, yet who's information does not
change should be a singleton.

No. Any class which is expensive to set up and whose information
doesn't change should only be instantiated once.

Well-written code can't tell the difference between singletons and
objects you create once, because creation (whether via 'new' or via
'getInstance()') is managed in one or a small number of places, rather
than throughout the app. The biggest pitfall in using singletons to
ensure a class is instantiated once is that people tend to blindly
replace 'new' with 'getInstance()', which just turns the singleton into
a global variable. All the problems with inline object creation still
apply: it's hard to test, it's brittle, switching implementations of
the servicing class is difficult, the entire object graph can be
created at a surprising time, and so on, but now there's global state
to worry about, too.

Some examples to illustrate my point are in order.

Bad:

public class SingletonClient {
public void foo() {
SingletonService instance = SingletonService.getInstance();
instance.doSomethingWorthwhile();
}
}

Good:

public class SingletonClient {
/* bean prop vs constructor is a matter of style */
public void setService(SingletonService service) { this.service = service; }
private SingletonService service;

public void foo() {
service.doSomethingWorthwhile();
}
}

Acceptable, in small quantities:

public class SingletonClient {
/* bean prop vs constructor is a matter of style */
public void setService(SingletonService service) { this.service = service; }
private SingletonService service = SingletonService.getInstance();

public void foo() {
service.doSomethingWorthwhile();
}
}

Clients of SingletonClient's foo() method can't tell the difference
between these implementations.

I normally don't link Steve Yegge, because he's even more opinionated
and hard-line than I am, but
<http://steve.yegge.googlepages.com/singleton-considered-stupid> is a
good read. Try to ignore the provocative URL.

Cheers,

-o
 
I

Icarus

I will think about other ways than Singletons on my next application.
This one however, is already fully implemented, operational and quite
big, so I don't want to change the whole structure.

You have made a few suggestions:

- Regarding .bat or .sh files: using these would make the program
platform-dependent, wouldn't it? I would need such files for every
possible OS there is.
- Regarding a custom classloader: this sounds a bit heavy for me. And
how would you use this to reset Singletons and static fields?
- And how do I launch a new JVM from within an existing one?


Thank you for the suggestions already.


- Icarus
 
L

Lew

Icarus said:
I will think about other ways than Singletons on my next application.
This one however, is already fully implemented, operational and quite
big, so I don't want to change the whole structure.

If it should be that the design is wrong, er, suboptimal, then unwillingness
to change it because it's "big" is foolish. You say it's "operational", yet
you have this problem that seems to indicate that being a singleton may be the
problem. (Natch, we don't know as much as you about it, so take that grain of
salt now.) If true, then you pretty much must redesign and re-implement.
That it's a lot of work is only a factor, and not the determining one at that.

Google "technical debt".
 
T

Tom Anderson

I will think about other ways than Singletons on my next application.
This one however, is already fully implemented, operational and quite
big, so I don't want to change the whole structure.

You have made a few suggestions:

- Regarding .bat or .sh files: using these would make the program
platform-dependent, wouldn't it? I would need such files for every
possible OS there is.

Well, you need one for every OS you deploy on. You'd need a batch file for
Windows. You'd need a shell script for unix, and that could easily be
written to cover all known forms of unix - linux, BSD, Solaris, MacOS X,
AIX, whatever. Those two scripts cover 99.9% of desktop machines, and a
very large chunk of servers.

If you're deploying on more exotic platforms, like OS/400, VMS, etc, you'd
need scripts in the native languages for those - unless they also had a
unix-like command interpreter available, and i bet some do.

Alternatively, write the reloader as an ant script. Ant should run
everywhere java does.

You could even write the reloader as a java program, using Runtime.exec.
- Regarding a custom classloader: this sounds a bit heavy for me. And
how would you use this to reset Singletons and static fields?

The point would be that you'd load fresh copies of the classes - as far as
the VM was concerned, the second run would be with completely different
code, so there would be no reuse of static fields.
- And how do I launch a new JVM from within an existing one?

I don't know of any way to do it without writing native code. With native
code, i'd write a stub program that used the JNI invocation interface to
start and stop JVMs. Not a lot of fun.

tom
 
A

Arne Vajhøj

Owen said:
No. Any class which is expensive to set up and whose information doesn't
change should only be instantiated once.

Well-written code can't tell the difference between singletons and
objects you create once, because creation (whether via 'new' or via
'getInstance()') is managed in one or a small number of places, rather
than throughout the app.

There are not much point in arguing best practice assuming well-written
code. If the code is well-written then there are no problems. The
purpose of best practices is to prevent lousy code. Even the most
incompetent programmer can not instantiate a singleton more than once.
The biggest pitfall in using singletons to
ensure a class is instantiated once is that people tend to blindly
replace 'new' with 'getInstance()', which just turns the singleton into
a global variable. All the problems with inline object creation still
apply: it's hard to test, it's brittle, switching implementations of the
servicing class is difficult, the entire object graph can be created at
a surprising time, and so on, but now there's global state to worry
about, too.

Some examples to illustrate my point are in order.

Bad:

public class SingletonClient {
public void foo() {
SingletonService instance = SingletonService.getInstance();
instance.doSomethingWorthwhile();
}
}

Good:

public class SingletonClient {
/* bean prop vs constructor is a matter of style */
public void setService(SingletonService service) { this.service =
service; }
private SingletonService service;

public void foo() {
service.doSomethingWorthwhile();
}
}

The last one is more testable, but it is really a SingletonClient
issue not a SingletonService issue.
Acceptable, in small quantities:

public class SingletonClient {
/* bean prop vs constructor is a matter of style */
public void setService(SingletonService service) { this.service =
service; }
private SingletonService service = SingletonService.getInstance();

public void foo() {
service.doSomethingWorthwhile();
}
}

That one I don't like. I prefer either or over both. It is much
clearer what the class does.

Arne
 
I

Icarus

If it should be that the design is wrong, er, suboptimal, then unwillingness
to change it because it's "big" is foolish. You say it's "operational", yet
you have this problem that seems to indicate that being a singleton may be the
problem. (Natch, we don't know as much as you about it, so take that grain of
salt now.) If true, then you pretty much must redesign and re-implement.
That it's a lot of work is only a factor, and not the determining one at that.

Google "technical debt".

I know what you mean, however, time is _the_ critical factor when it
comes to work. If I am given a task, I am expected to work on the
problem that is most important. So if I have something critical to
implement, I won't stop midway to deal with an issue of an optional
functionality that's hardly ever used. I don't want to leave something
half-finished, but I'll absolutely not reimplement a whole project to
cater for a rather unimportant issue, while a critical task is at
hand. I do want to understand the issue to avoid it in the future,
though.

Regarding the suggested solutions: I'm afraid I have never used any of
those, so it's hard to understand the solutions and their possible
side effects on the system. I have found the ProcessBuilder and
Classloader classes in the API, but don't know how I should modify it
in a way that helps me with my problem (I would have to close the old
processes and kill the old objects as well, or the program would pile
up garbage on each new run).
 
T

Tom Anderson

Or use a ProcessBuilder to run the "java" command.

I was thinking of running the new JVM in a way which would replace the old
one, rather than as a subprocess. But yes, that's easy and works.

tom
 
J

John B. Matthews

Icarus said:
Regarding the suggested solutions: I'm afraid I have never used any
of those, so it's hard to understand the solutions and their possible
side effects on the system. I have found the ProcessBuilder and
Classloader classes in the API, but don't know how I should modify it
in a way that helps me with my problem (I would have to close the old
processes and kill the old objects as well, or the program would pile
up garbage on each new run).

Program exit is described here:

<http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.8>

Here is a simple example of starting a new Process. You can use
ProcessBuilder to manage the attributes of a Process that will be run
repeatedly:

import java.io.*;

/** @author John B. Matthews */
class ExecTest {

public static void main (String[] args) {
String s;
try {
Process p = Runtime.getRuntime().exec("java MyProgram");
// read from the process's stdout
BufferedReader stdout = new BufferedReader (
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null) {
System.out.println(s);
}
// read from the process's stderr
BufferedReader stderr = new BufferedReader (
new InputStreamReader(p.getErrorStream()));
while ((s = stderr.readLine()) != null) {
System.err.println(s);
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
p.waitFor();
System.err.println("Exit value: " + p.exitValue());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
 
I

Icarus

Here is a simple example of starting a new Process. You can use
ProcessBuilder to manage the attributes of a Process that will be run
repeatedly:

import java.io.*;

/** @author John B. Matthews */
class ExecTest {

    public static void main (String[] args) {
        String s;
        try {
            Process p = Runtime.getRuntime().exec("java MyProgram");
            // read from the process's stdout
            BufferedReader stdout = new BufferedReader (
                new InputStreamReader(p.getInputStream()));
            while ((s = stdout.readLine()) != null) {
                System.out.println(s);
            }
            // read from the process's stderr
            BufferedReader stderr = new BufferedReader (
                new InputStreamReader(p.getErrorStream()));
            while ((s = stderr.readLine()) != null) {
                System.err.println(s);
            }
            p.getInputStream().close();
            p.getOutputStream().close();
            p.getErrorStream().close();
            p.waitFor();
            System.err.println("Exit value: " + p.exitValue());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

}


What is that process actually doing? Mine is supposed to run a
platform with a GUI.

I have tried to implement another example (given below). How do I
implement the new process starting and running? If working correctly,
the code should create an infinite loop where the attributes start off
with their original values.

And wouldn't this approach force me to pile up garbage in the former
processes?


public class InitialisierungenKlassen {

public static void main(String[] args) {

// Print the initial values
System.out.println("Initialization of the Singleton attribute: " +
Singleton.getInstance().getString());
System.out.println("Initialization of the static attribute: " +
Statisch.staticString);

// Change the values and print them
Singleton.getInstance().setString("Changed!");
Statisch.staticString = "Changed!";

System.out.println("Value of the Singleton attribute: " +
Singleton.getInstance().getString());
System.out.println("Value of the static attribute: " +
Statisch.staticString);

// // Reload
// InitialisierungenKlassen.main(args);

// Reload
try {
Process p = Runtime.getRuntime().exec("java
InitialisierungenKlassen");

} catch (Exception e) {
e.printStackTrace();
}
}

}

class Singleton{

private static Singleton instance = new Singleton();

private String string = "Initialized.";

private Singleton(){

}

protected static Singleton getInstance(){
return Singleton.instance;
}
protected String getString(){
return this.string;
}
protected void setString(String string){
this.string = string;
}
}

class Statisch{

protected static String staticString = "Initialized.";
}
 
J

John B. Matthews

[...]
What is that process actually doing? Mine is supposed to run a
platform with a GUI.

GUI? News to me. Does it matter?
I have tried to implement another example (given below). How do I
implement the new process starting and running? If working correctly,
the code should create an infinite loop where the attributes start
off with their original values.

Infinite loop? It sounds like you want to launch a new JVM from Java,
leaving nothing behind. I don't know how to detach a Java Process, i.e.
launch a child process, while exiting the parent. Alternatively, you
might look at the Java Service Wrapper:

And wouldn't this approach force me to pile up garbage in the former
processes?

Yes, your example would create a recursive chain of parent-child
processes until the system's resources were exhausted.

If you just want to launch a fresh JVM and return to the parent,
something like the example below might do. You could use ProcessBuilder
and SwingWorker to manage multiple children:

<code>
package gui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
* @author John B. Matthews
*/
public class Launcher {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new Launcher().createGUI();
}
});
}

private void createGUI() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton launch = new JButton("Launch");
launch.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String s;
try {
Process p = Runtime.getRuntime().exec("java"
+ " -cp build/classes"
+ " gui.InitialisierungenKlassen");
// read from the process's stdout
BufferedReader stdout = new BufferedReader (
new InputStreamReader(p.getInputStream()));
while ((s = stdout.readLine()) != null) {
System.out.println(s);
}
// read from the process's stderr
BufferedReader stderr = new BufferedReader (
new InputStreamReader(p.getErrorStream()));
while ((s = stderr.readLine()) != null) {
System.err.println(s);
}
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
System.err.println("Exit value: " + p.waitFor());
}
catch (Exception ex) {
ex.printStackTrace();
}
}
});
frame.add(launch);
frame.pack();
frame.setVisible(true);
}
}

class InitialisierungenKlassen {

public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new InitialisierungenKlassen().createGUI();
}
});
print();
Singleton.getInstance().setString("Changed!");
Statisch.staticString = "Changed!";
print();
}

private static void print() {
System.out.println("Singleton attribute: "
+ Singleton.getInstance().getString());
System.out.println("Static attribute: "
+ Statisch.staticString);
}

private void createGUI() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton exit = new JButton("Exit");
exit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(42);
}
});
frame.add(exit);
frame.pack();
frame.setVisible(true);
}
}
class Singleton{

private static Singleton instance = new Singleton();

private String string = "Initialized.";

private Singleton(){

}

protected static Singleton getInstance(){
return Singleton.instance;
}
protected String getString(){
return this.string;
}
protected void setString(String string){
this.string = string;
}
}

class Statisch{

protected static String staticString = "Initialized.";
}
</code>
 
I

Icarus

[...]
What is that process actually doing? Mine is supposed to run a
platform with a GUI.

GUI? News to me. Does it matter?
I have tried to implement another example (given below). How do I
implement the new process starting and running? If working correctly,
the code should create an infinite loop where the attributes start
off with their original values.

Infinite loop? It sounds like you want to launch a new JVM from Java,
leaving nothing behind. I don't know how to detach a Java Process, i.e.
launch a child process, while exiting the parent. Alternatively, you
might look at the Java Service Wrapper:

And wouldn't this approach force me to pile up garbage in the former
processes?

Yes, your example would create a recursive chain of parent-child
processes until the system's resources were exhausted.

If you just want to launch a fresh JVM and return to the parent,
something like the example below might do. You could use ProcessBuilder
and SwingWorker to manage multiple children:

<code>
package gui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.swing.JButton;
import javax.swing.JFrame;

/**
 * @author John B. Matthews
 */
public class Launcher {

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        new Launcher().createGUI();
      }
    });
  }

  private void createGUI() {
    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final JButton launch = new JButton("Launch");
    launch.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        String s;
        try {
          Process p = Runtime.getRuntime().exec("java"
            + " -cp build/classes"
            + " gui.InitialisierungenKlassen");
          // read from the process's stdout
          BufferedReader stdout = new BufferedReader (
            new InputStreamReader(p.getInputStream()));
          while ((s = stdout.readLine()) != null) {
            System.out.println(s);
          }
          // read from the process's stderr
          BufferedReader stderr = new BufferedReader (
            new InputStreamReader(p.getErrorStream()));
          while ((s = stderr.readLine()) != null) {
            System.err.println(s);
          }
          p.getInputStream().close();
          p.getOutputStream().close();
          p.getErrorStream().close();
          System.err.println("Exit value: " + p.waitFor());
        }
        catch (Exception ex) {
          ex.printStackTrace();
        }
      }
    });
    frame.add(launch);
    frame.pack();
    frame.setVisible(true);
  }

}

class InitialisierungenKlassen {

  public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        new InitialisierungenKlassen().createGUI();
      }
    });
    print();
    Singleton.getInstance().setString("Changed!");
    Statisch.staticString = "Changed!";
    print();
  }

  private static void print() {
    System.out.println("Singleton attribute: "
      + Singleton.getInstance().getString());
    System.out.println("Static attribute: "
      + Statisch.staticString);
  }

  private void createGUI() {
    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final JButton exit = new JButton("Exit");
    exit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(42);
      }
    });
    frame.add(exit);
    frame.pack();
    frame.setVisible(true);
  }}

class Singleton{

  private static Singleton instance = new Singleton();

  private String string = "Initialized.";

  private Singleton(){

  }

  protected static Singleton getInstance(){
    return Singleton.instance;
  }
  protected String getString(){
    return this.string;
  }
  protected void setString(String string){
    this.string = string;
  }

}

class Statisch{

  protected static String staticString = "Initialized.";}

</code>

What is the process trying to do? After I start the Launcher and press
Launch, I can type in texts in the console, but that's all.
 
J

John B. Matthews

Icarus said:
 Icarus said:
What is that process actually doing? Mine is supposed to run a
platform with a GUI.

GUI? News to me. Does it matter?
I have tried to implement another example (given below). How do I
implement the new process starting and running? If working correctly,
the code should create an infinite loop where the attributes start
off with their original values.

Infinite loop? It sounds like you want to launch a new JVM from Java,
leaving nothing behind. I don't know how to detach a Java Process, i.e.
launch a child process, while exiting the parent. Alternatively, you
might look at the Java Service Wrapper:

And wouldn't this approach force me to pile up garbage in the former
processes?

Yes, your example would create a recursive chain of parent-child
processes until the system's resources were exhausted.

If you just want to launch a fresh JVM and return to the parent,
something like the example below might do. You could use ProcessBuilder
and SwingWorker to manage multiple children:

<code> [...]
</code>

What is the process trying to do? After I start the Launcher and press
Launch, I can type in texts in the console, but that's all.

I run gui.Launcher. [begin-loop] I click the "Launch" button. I see
Singleton mutate on stdout. I click the "Exit" button. I see
InitialisierungenKlassen exit with result 42 on stderr. The Launch
button appears. [repeat-ad-libitum] I close the Launcher window, exiting
the program.

I see no opportunity to type in text in the console.

You may find it instructive to watch the process externally using top,
DTrace, or your favorite profiler.
 
R

Roedy Green

The idea is the following:
I have a program that, after is has run, restarts itself right from
the beginning. The problem is that many fields still have values from
the last go, especially in Singleton classes, and aren't properly
resetted. But I want to have the exact same situation as if the
program has just started. Resetting the fields manually is a truckload
of work and prone to errors.

If you avoided ever doing any initialization except in methods or
constructors, I think it should be possible to guarantee a clean
restart without having to manually maintain lists of fields to wipe.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Here is a point of no return after which warming becomes unstoppable
and we are probably going to sail right through it.
It is the point at which anthropogenic (human-caused) warming triggers
huge releases of carbon dioxide from warming oceans, or similar releases
of both carbon dioxide and methane from melting permafrost, or both.
Most climate scientists think that point lies not far beyond 2°C (4°F) C hotter."
~ Gwynne Dyer
 
I

Icarus

I run gui.Launcher. [begin-loop] I click the "Launch" button. I see
Singleton mutate on stdout. I click the "Exit" button. I see
InitialisierungenKlassen exit with result 42 on stderr. The Launch
button appears. [repeat-ad-libitum] I close the Launcher window, exiting
the program.

I see no opportunity to type in text in the console.

You may find it instructive to watch the process externally using top,
DTrace, or your favorite profiler.

According to the Eclipse debugging tool, the program runs up to the
line

while ((s = stdout.readLine()) != null) {
System.out.println(s);
}
and then stalls. This was also what happened when I tried to get the
code piece with the "exec" command to work.


If you avoided ever doing any initialization except in methods or
constructors, I think it should be possible to guarantee a clean
restart without having to manually maintain lists of fields to wipe.

I am using Singletons and static fields which hold some of the values.
These aren't properly reset, sadly.
 

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,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top