当前位置: 首页 > 知识库问答 >
问题:

跟踪Java应用程序中每个线程的内存分配

翟默
2023-03-14

我知道Java中内存分配的基本原理——应用程序占用的大部分内存都分配在堆上,堆由所有线程共享,因此没有线程拥有对象的概念,您无法轻松计算线程使用它拥有的所有对象占用了多少内存。

但我想知道是否有任何方法可以计算和汇总从特定线程触发的分配?内存分配发生在堆上,但它总是由想要创建对象的线程触发,所以我想知道是否可以以某种方式分析这种关系?

我的想法是,一个典型的Spring Boot应用程序将引导,从主线程分配一组对象,然后启动一个Web服务器,生成处理HTTP请求的线程,每次收到请求时,都会为其分配一个线程,并在该线程中处理。Web服务器线程有一个特定点,在该点上它们接受请求,处理请求,然后发送响应。如果我们能够以某种方式在接受请求的点“重置”分配统计信息,然后在发送响应后将统计信息提交给某个收集器,那么我们可以获得关于各个endpoint的非常好的统计信息,并查看它们分配了多少内存。

我知道这并不完美,但通过这种方法,您至少可以了解每个HTTP请求分配了多少内存,并且可以看到,例如,一些请求正在将数据库的一半加载到内存中,这可能是一个问题。

共有2个答案

庄嘉
2023-03-14

以下示例代码显示了如何确定在方法调用期间分配的(堆)内存量:

import java.lang.management.ManagementFactory;
import com.sun.management.ThreadMXBean;

public class AllocationWatcher {
    public static void main(String[] args) {
        ThreadMXBean threadMxBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
        threadMxBean.setThreadAllocatedMemoryEnabled(true);

        long startAlloc = threadMxBean.getCurrentThreadAllocatedBytes();
        allocMemory();
        long endAlloc = threadMxBean.getCurrentThreadAllocatedBytes();

        System.out.printf("Thread allocated %,d bytes before the start%n", startAlloc);
        System.out.printf("Thread allocated %,d bytes within allocMemory()%n", endAlloc-startAlloc);
    }
    static void allocMemory() {
        var data = new byte[10_001];
        var data2 = new byte[10_001];
    }
}

类导入com。太阳经营ThreadMXBean是OpenJDK源代码的一部分,因此它可能适用于大多数JVM(尽管我不能提供任何保证)。

黎奇思
2023-03-14

我认为可能有一种方法可以用MXBean来做到这一点,尽管我不能给你示例代码。

有一个叫做com的接口。太阳经营jdk中的ThreadMXBean。管理模块(javadoc),其方法如下所述:

"返回在堆内存中为[线程]分配的内存总量的近似值(以字节为单位)。返回的值是近似值,因为某些Java虚拟机实现可能使用对象分配机制,这会导致分配对象的时间和记录其大小的时间之间的延迟。"

我的解释是,这是一个线程所有堆分配大小的累加器。

不过也有一些警告。首先,JVM可能不支持该机制。(有很多方法可以找到答案。)其次,需要启用它。第三,它是近似值这一事实可能意味着它对于您的目的来说不够精确。

Oracle Java教程中有一节介绍了如何使用MXBeans:

  • https://docs.oracle.com/javase/tutorial/jmx/mbeans/mxbeans.html
 类似资料:
  • 我知道Java中内存分配的基本原理-应用程序占用的大部分内存都是在堆上分配的,堆由所有线程共享,因此没有线程拥有的对象的概念,并且您无法轻松计算线程拥有的所有对象占用了多少内存。 但我想知道是否有任何方法可以计算和汇总从特定线程触发的分配?内存分配发生在堆上,但它总是由想要创建对象的线程触发,所以我想知道是否可以以某种方式分析这种关系? 我的想法是,一个典型的Spring Boot应用程序将引导,

  • 我看到了这个Python问题:应用引擎延迟:跟踪内存泄漏 ...同样,我也遇到了这个可怕的错误: 在为总共384个请求提供服务后,超过了128 MB的软专用内存限制 ... 处理此请求后,发现处理此请求的进程占用了太多内存,因此被终止。这可能会导致应用程序的下一个请求使用新进程。如果经常看到此消息,则应用程序中可能存在内存泄漏。 根据另一个问题,可能是“实例类”太小,无法运行这个应用程序,但是在增

  • 问题内容: 我看到了这个Python问题:推迟了AppEngine:跟踪内存泄漏 …同样,我遇到了这个可怕的错误: 总共为384个请求提供服务后,超出了128 MB的软私有内存限制 … 处理此请求后,发现处理此请求的进程使用了​​过多的内存并被终止。这很可能导致新流程用于您的应用程序的下一个请求。如果您经常看到此消息,则可能是应用程序内存泄漏。 根据另一个问题,可能是“实例类”太小而无法运行此应用

  • 问题内容: 我在Linux中玩ptrace。我正在尝试使用/ proc / pid / mem接口编写跟踪进程的内存。 我用来完成此任务的功能是: 但是我总是会得到错误:编写:错误的文件描述符。 是否可以使用此方法编写跟踪过程? 问题答案: 您正在以只读模式()打开文件。我建议改用: 但是,从目前尚不清楚这是否可行: memory through open(2), read(2), and lse

  • 我试图了解C程序在汇编级别上的样子,所以我运行gdb并在主get_input上使用反汇编。该程序很短,因此我可以更好地遵循它。有2行我不明白。在 main() 中的第一个是:

  • 问题内容: 有没有可用的工具来跟踪Java线程的创建和生存期?我将对以下所有内容感兴趣: 调用new Thread()的调用堆栈 调用了start()的调用栈 run()方法的生命周期 问题答案: 我已经编写并发布了一个开源工具来回答这个问题。 Java Live线程分析器 我在这里博客介绍了该工具。