Java 如何在运行时查找堆/堆栈中对象的强引用数

Java 如何在运行时查找堆/堆栈中对象的强引用数,java,c,garbage-collection,heap-memory,Java,C,Garbage Collection,Heap Memory,团队 在java中,是否有可能知道一个对象当前有多少活动/强引用 例如在下面的代码中;类的对象可以由项目中的许多类持有。但我想在监视器线程中打印它 public class A { public static A a = new A(); public static A getInstance() { return a; } private A() { new Monitor(this).start(); } class Monitor exte

团队

在java中,是否有可能知道一个对象当前有多少活动/强引用

例如在下面的代码中;类的对象可以由项目中的许多类持有。但我想在监视器线程中打印它

public class A {
  public static A a = new A();
  public static A getInstance() {
     return a;
  }

  private A() {
     new Monitor(this).start();
  }


  class Monitor extends Thread {
      A refA;
      public Monitor(A ref) {
         this.refA = ref;
      }
      public void run () {

      //TODO Print how many references currently available for Object A referenced by refA;
      //Sure It will be minimum one. (which is "a" in this class A)   
      } 

   }
}
请不要太重视这个示例程序。我的问题是如何找到堆/堆栈中一个对象有多少强引用?唯一的好处是,我们手头有一个关于这个对象的强有力的参考

如果在java中不可能;我可以把这个强引用传递给C语言吗;从C语言我能做到这一点吗

我只是想知道探查器/工具是如何做到这一点的?
请提供帮助。

不,如果不更改虚拟机上的类或分支工具,您将无法获得准确的计数。由于对性能的影响,虚拟机上的类或分支工具很难在生产中生成


使用,您可以在对象即将被丢弃并在此时执行操作时收到通知,但没有可用的计数,也不总是由虚拟机处理。

不,如果不更改虚拟机上的类或分支工具,您将无法获得准确的计数,因为这会影响性能


使用,您可以在对象即将被丢弃并在此时执行操作时收到通知,但没有可用的计数,也不总是由VM处理。

您可以执行堆转储并对其进行分析,以找到对任何对象的引用数

您对此有什么要求,以及您将如何处理这些信息,因为我认为有一种更容易/更好的方法来实现您的目标

基于WeakHashMap

/**
 * Reference queue for cleared WeakEntries
 */
private final ReferenceQueue<Connection> queue = new ReferenceQueue<>();

List<WeakReference<Connection>> usedConnections = ....

// when you have a new connection

Connection connection = ....
usedConnections.add(new WeakReference(connection, queue));

// checking the queue for discarded objects.

    // remove null references from usedConnections

    for (Connection x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
           x.close();
        }
     }

您可以执行堆转储并对其进行分析,以找到对任何对象的引用数

您对此有什么要求,以及您将如何处理这些信息,因为我认为有一种更容易/更好的方法来实现您的目标

基于WeakHashMap

/**
 * Reference queue for cleared WeakEntries
 */
private final ReferenceQueue<Connection> queue = new ReferenceQueue<>();

List<WeakReference<Connection>> usedConnections = ....

// when you have a new connection

Connection connection = ....
usedConnections.add(new WeakReference(connection, queue));

// checking the queue for discarded objects.

    // remove null references from usedConnections

    for (Connection x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
           x.close();
        }
     }

你可以试试这样的东西

Class A
{
   static int instanceCount = 0;
   public A()
   {
      instanceCount++;
   }

   protected finalize()
   {
      instanceCount--;
   }

   public static int getInstanceCount()
   {
       return instanceCount;
   }
}

我相信这是使用代码最接近于包含类引用的方法。希望对你有所帮助……

你可以试试这样的东西

Class A
{
   static int instanceCount = 0;
   public A()
   {
      instanceCount++;
   }

   protected finalize()
   {
      instanceCount--;
   }

   public static int getInstanceCount()
   {
       return instanceCount;
   }
}


我相信这是使用代码最接近于包含类引用的方法。希望对您有所帮助…

为什么要在运行时查找java中一个对象的引用数?我想在调用getInstance后只有一个活动引用时执行一些操作。表示getInstance的调用方方法在堆栈中结束。因此,我们只有一个活动引用是“a”。看起来您更需要某种方面的功能,请尝试AspectJ或Spring AOP。您只需要上侧面还是两者都需要?我的意思是,当计数从0变为1时,你需要做一次1,每次计数从0变为1,每次计数从X变为3=1对1?为什么要在运行时查找java中一个对象的引用数?我想在调用getInstance后只有一个活动引用时执行一些操作。表示getInstance的调用方方法在堆栈中结束。因此,我们只有一个活动引用是“a”。看起来您更需要某种方面的功能,请尝试AspectJ或Spring AOP。您只需要上侧面还是两者都需要?我的意思是,当计数从0变为1时,你需要做一次1,每次计数从0变为1,每次计数从X变为3=1到1?池中请求的代码数据库连接对象中约700个位置;但他们从未关门。这是不可见的,因为最大无连接大小为75。仅在负载测试期间发现。我只想要解决方案,而不是对所有文件进行代码更改;我怎样才能关闭它池边本身?听起来你有内存泄漏。我会使用内存分析器来查看它们被保留在哪里。您是否像PreparedStatements一样关闭JDBC资源?该代码从未关闭过连接,甚至连一个地方都没有。所以现在很难换到这700个地方。那么,有什么建议可以纠正这个问题吗?可以通过不使用连接清理资源来保持连接的开放性。真正的修复方法是修复代码。任何变通方法都不可能像您认为的那样有效,因为仅仅关闭连接是不够的。所有这些地方都正确关闭了语句和结果集。但连接未关闭或未返回到池。有一件事我可以说,一旦事务块结束,引用可能会结束,但不会被释放。因此,在GC之前,我从max conn到达的池中获得异常。因此,如果没有对这个conn对象的活动引用,我想通过监视器线程关闭/返回池。但如何从池中请求的代码数据库连接对象中约700个位置;但他们从未关门。这是不可见的,因为最大无连接大小为75。仅在负载测试期间发现。我只是想要解决方案,而不是进行代码更改

在所有档案上;我怎样才能关闭它池边本身?听起来你有内存泄漏。我会使用内存分析器来查看它们被保留在哪里。您是否像PreparedStatements一样关闭JDBC资源?该代码从未关闭过连接,甚至连一个地方都没有。所以现在很难换到这700个地方。那么,有什么建议可以纠正这个问题吗?可以通过不使用连接清理资源来保持连接的开放性。真正的修复方法是修复代码。任何变通方法都不可能像您认为的那样有效,因为仅仅关闭连接是不够的。所有这些地方都正确关闭了语句和结果集。但连接未关闭或未返回到池。有一件事我可以说,一旦事务块结束,引用可能会结束,但不会被释放。因此,在GC之前,我从max conn到达的池中获得异常。因此,如果没有对这个conn对象的活动引用,我想通过监视器线程关闭/返回池。但如何希望您知道一旦getInstance调用方方法代码块结束,引用就会结束。它永远不会与运行时调用的getInstance数量相同。此外,我们也无法从finalize获得帮助,因为我们正在讨论活动对象的引用。在上面的示例中,一个类加载器的实例计数始终为1。现在在JVM中,即使是由不同类加载器加载的相同类也被视为不同的类。因此,在您的例子中,实例数=加载类A的类加载器数。希望您知道一旦getInstance调用方方法代码块结束,引用将结束。它永远不会与运行时调用的getInstance数量相同。此外,我们也无法从finalize获得帮助,因为我们正在讨论活动对象的引用。在上面的示例中,一个类加载器的实例计数始终为1。现在在JVM中,即使是由不同类加载器加载的相同类也被视为不同的类。因此,在您的例子中,实例的数量=加载类A的类装入器的数量。您能告诉我探查器/工具的功能吗?用C语言可以吗?那个么我可以使用本机调用吗?在不严重影响性能的情况下,您无法做到这一点,因为现代JVM甚至不记录实例数。谢谢。你能为我和彼得·劳瑞的转换提供一些建议吗?好的。您能告诉我探查器/工具的功能吗?用C语言可以吗?那个么我可以使用本机调用吗?在不严重影响性能的情况下,您无法做到这一点,因为现代JVM甚至不记录实例数。谢谢。你能为我和彼得·劳瑞的转换提供一些建议吗?