线程消耗的内存 [英] Memory consumed by a thread

查看:584
本文介绍了线程消耗的内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要监视应用程序生成的线程占用的内存量。如果贪婪的线程消耗太多内存,那么我们的想法就是采取纠正措施。我已经提到我的java线程需要多少内存?。关于该链接的建议之一是在 ThreadMXBean中使用 getThreadAllocatedBytes 我试验了 getThreadAllocatedBytes ,包含以下工作。

I need to monitor the amount of memory consumed by threads spawned by my application. The idea is to take corrective actions, if a greedy thread consumes too much of memory. I have referred to How much memory does my java thread take?. One of the suggestions on that link is to use getThreadAllocatedBytes in ThreadMXBean.I experimented with getThreadAllocatedBytes with the following job.

List<Long> primes = new ArrayList<Long>();
long i = 0;
while (true) {
            primes.add(++i);
            if ((i % 10) == 0) {
                primes.clear();
                System.runFinalization();
                System.gc();
            }
        }

我在四个线程上运行这个工作相当长的时间。虽然作业不会持续累积内存,但 getThreadAllocatedBytes 返回的值会不断增加,甚至不会下降一次。这意味着 getThreadAllocatedBytes 不会返回线程使用的堆上的实际内存量。它返回自启动以来线程在堆上分配的内存总量。我的平台详细信息如下:

I run this job on four threads for considerable time. Though the job does not accumulate memory continuously, the values returned by getThreadAllocatedBytes keeps increasing and does not go down even once. This implies that getThreadAllocatedBytes does not return the actual amount of memory on heap used by the thread. It returns the total amount of memory allocated on the heap for the thread since it was started. My platform details are as follows:

Linux PG85213.egi.ericsson.com 3.5.0-030500-generic#201207211835 SMP Sat Jul 21 22:35: 55 UTC 2012 x86_64 x86_64 x86_64 GNU / Linux
java版本1.7.0_45

Java(TM)SE运行时环境(版本1.7.0_45-b18)
Java HotSpot(TM) )64位服务器VM(内置24.45-b08,混合模式)

上述行为是否为 getThreadAllocatedBytes所需的行为
如果是这样,是否无法在线程使用的堆上找到有效内存。

Is the above behavior desired behavior of getThreadAllocatedBytes? If so, is there no way to find effective memory on heap used by a thread.

列出完整的程序以供参考:

Am listing the complete program for reference:

package workbench;

import java.lang.management.ManagementFactory;
import com.sun.management.ThreadMXBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AnotherWorkBench {

private static final CountDownLatch latch = new CountDownLatch(4);
static final List<Long> threadIds = Collections.synchronizedList(new ArrayList<Long>());

private void dummyJob() {
    List<Long> primes = new ArrayList<Long>();
    long i = 0;
    while (true) {
        primes.add(++i);
        if ((i % 10) == 0) {
            primes.clear();
            //introduce sleep to prevent process hogging 
            try {
                Thread.currentThread().sleep(2000);
            } catch (InterruptedException ex) {
                Logger.getLogger(AnotherWorkBench.class.getName()).log(Level.SEVERE, null, ex);
            }
            System.runFinalization();
            System.gc();
        }
    }
}

private void runDummyJobs() {

    Runnable dummyJob = new Runnable() {
        @Override
        public void run() {
            threadIds.add(Thread.currentThread().getId());
            latch.countDown();
            dummyJob();
        }
    };

    Runnable memoryMonitorJob = new Runnable() {
        @Override
        public void run() {

            System.out.println(Thread.currentThread().getName() + " : Monitor thread started");
            ThreadMXBean threadMxBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
            threadMxBean.setThreadAllocatedMemoryEnabled(true);

            while (true) {
                for (Long threadId : threadIds) {
                    System.out.println(Thread.currentThread().getName() + " : Thread ID : " + threadId + " : memory = " + threadMxBean.getThreadAllocatedBytes(threadId) + " bytes");
                }

                //wait between subsequent scans
                try {
                    System.out.println(Thread.currentThread().getName() + " : secondary sleep");
                    Thread.currentThread().sleep(5000);
                    System.out.println(Thread.currentThread().getName() + " : out of secondary sleep");
                } catch (InterruptedException ex) {
                    Logger.getLogger(WorkBench.class.getName()).log(Level.SEVERE, null, ex);
                }
            }


        }
    };

    Executors.newSingleThreadExecutor().submit(dummyJob);
    Executors.newSingleThreadExecutor().submit(dummyJob);
    Executors.newSingleThreadExecutor().submit(dummyJob);
    Executors.newSingleThreadExecutor().submit(dummyJob);

    try {
        latch.await();
    } catch (InterruptedException ex) {
        Logger.getLogger(AnotherWorkBench.class.getName()).log(Level.SEVERE, null, ex);
    }
    Executors.newSingleThreadExecutor().submit(memoryMonitorJob);
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    new AnotherWorkBench().runDummyJobs();
}
}


推荐答案

到据我所知,在运行时没有可靠的方法来做到这一点。正如源问题所指出的,堆是共享资源,因此单个线程的堆大小没有意义,因为它将与来自其他线程的对象引用重叠。

To my knowledge, there is no reliable way to do this at runtime. And as pointed out in the source question, the heap is a shared resource and thus the heap size of a single thread does not make sense as it will overlap with objects references from other threads.

那就是说,当我想知道保留大小,并且保留大小是与您要求的大小不同但相似的度量,然后我通过进行堆转储然后使用MAT( http://www.eclipse.org/mat/ )。

That said, when I do want to know the 'retained' size of a single thread, and yes retained size is a different but similar metric to the one that you asked for, then I do it by taking a heap dump and then using MAT (http://www.eclipse.org/mat/).

我认识的人使用 Java代理来监控分配对象然后使用弱引用来监视它何时获得GC。然而,这样做对性能的影响很大。很高。

I have known people to use Java Agents to instrument the allocation of objects and then to use a weak reference to monitor when it gets GC'd. However the performance impact of doing this is high. Very high.

你可能最好在运行时使用启发式和单元测试以确保内存保持在界限内。例如,您可以使用JMX来监控堆大小,当您看到旧的增长时,您可以发出警报。使用getThreadAllocatedBytes来计算分配率也很有用。

You may be best off using a heuristic at runtime and unit testing to ensure that memory stays within bounds. For example, you could use JMX to monitor the heap sizes and when you see the old gen growing then you can raise an alert. Using getThreadAllocatedBytes to calculate rate of allocation could also be useful.

良好的运行时监控工具: appdynamics newrelic visualvm yourkit

Good run time monitoring tools: appdynamics, newrelic, visualvm and yourkit

对于离线内存分析, mat jclarity 非常好。

For offline memory analysis, mat and jclarity are very good.

一个非常有用的工具来帮助一个地方是否存在泄漏,或者至少与预期不同的是打印每个类当前在堆上的实例数量的计数: jcmd< pid> GC.class_histogram

A very useful tool to help one spot whether there is a leak, or at least is running different to expectations is to print a count of how many instances of each class are currently on the heap: jcmd <pid> GC.class_histogram.

这篇关于线程消耗的内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆