我可以判断我是否超出范围吗?

时间:2011-06-30 15:59:46

标签: java

有什么方法可以从对象内部判断出我是否超出范围?

我有一个必须关闭的对象。如果没有关闭,则保证泄漏。如果可能,我想尝试自动关闭。

我的一个私有实例变量是一个必须在关闭期间关闭的线程。我猜测线程的存在会导致unclosed对象永远不会被gc'd。

5 个答案:

答案 0 :(得分:2)

java中没有“超出范围范围”的概念,因为所有对象都在堆上。一旦你说'新',唯一能为你清理的就是gc。你可以使用try / finally,你可以使用终结器等,但就是这样。

你需要阅读有关finalize方法的内容,然后还有关于幻像引用的内容。

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

答案 1 :(得分:2)

Java没有析构函数。

如果一个对象需要在Java的内存自动垃圾收集之外进行显式清理,那么你可以提供一个显式方法 - 例如close(),terminate()或dispose()。

如果你的线程通过保持对它的引用来阻止对象的垃圾收集,它可以改为保存weak reference,这不会阻止垃圾收集。

使用弱引用,您可以判断引用的对象是否已被垃圾回收。但是,您无法判断垃圾回收是否符合条件

答案 2 :(得分:1)

不,Java中没有这样的机制。

但是,您可以在关机挂钩中进行紧急清理。有关详细信息,请参阅http://download.oracle.com/javase/1,5.0/docs/guide/lang/hook-design.html

请注意,这只应被视为最后的手段。

答案 3 :(得分:0)

如果你的意思类似于在C ++中完成RAII的方式,答案是否定的 - 如果你需要做些什么来清理它,Java会坚持你知道什么时候你不再需要它。通常的做法是:

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

C#有一个using关键字可以整理一下。

答案 4 :(得分:0)

在研究这个问题时,我确实提出了一个近乎解决方案。基本上,当您创建Runnable时,请获取创建您的线程的副本,并偶尔检查它的堆栈跟踪。如果它变空了你可以安全地假设它们已经完成......或者你可以吗?

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);
  }
}