开发者

Can I tell if I am out of scope?

Is there any way I can tell, from the inside of the object, whether I am out of scope?

I have an object that must be closed. If it is not closed then a leak is guaranteed. I would like to try to auto-close if possible.

One开发者_开发技巧 of my private instance variables is a thread that must be shut down during the close. I am guessing the existence of the thread will cause unclosed objects to never be gc'd.

Paul


There is no notion of 'out of scope scope' in java, because all objects are on the heap. Once you say 'new', the only thing that will ever clean up for you will be the gc. You can use try/finally, and you can have a finalizer, etc, but that's that.

You need to read about the finalize method, and then perhaps also about phantom references.

http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html


Java has no destructors.

If an object requires explicit cleanup beyond Java's automatic garbage collection of memory, then you can offer an explicit method -- e.g., close(), terminate() or dispose().

If your thread is preventing garbage collection of an object by holding a reference to it, it could instead hold a weak reference, which does not prevent garbage collection.

With a weak reference, you can tell whether the referenced object has been garbage-collected. However, you can't tell whether it is eligible for garbage collection.


No, there is no such mechanism in Java.

You can, however, put emergency cleanup in a shutdown hook. See http://download.oracle.com/javase/1,5.0/docs/guide/lang/hook-design.html for details.

Note that this should only be considered a last resort.


If you mean similar to how RAII is done in C++, the answer is no - Java insists you know when you no longer need something if you need to do something to clean it up. The usual way to do this is:

Something s = new Something();
try 
{
  // do things
} 
finally 
{ 
  s.close();
}

C# has a using keyword that tidies it up a bit.


While researching this I did come up with a near-solution. Essentially, when your Runnable is created, grab a copy of the thread that created you and occasionally check it's stacktrace. If it ever becomes empty you can safely assume they are finished ... or can you?

private void testThreads() throws InterruptedException {

  class ThreadTest implements Runnable {

    final Thread maker;

    private ThreadTest() {
      // Grab the maker's thread.
      maker = Thread.currentThread();
    }

    private boolean makerIsAlive() {
      // If maker's stack trace hits empty it is fair to assume they are done.
      return maker.getStackTrace().length != 0;
    }

    public void run() {
      // Keep checking the stack using a stacktrace.
      while (makerIsAlive()) {
        try {
          // Get out of here if maker has finished.
          // Wait one second.
          Thread.sleep(1000);
        } catch (InterruptedException ex) {
          break;
        }
      }
      System.out.println("====== Maker has finished! Exiting. ======");
    }
  }

  Thread thread = new Thread(new ThreadTest());
  thread.start();
  // Wait for 10 seconds.
  long finishTime = System.currentTimeMillis() + 10 * 1000;
  while (System.currentTimeMillis() < finishTime) {
    Thread.sleep(500);
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜