关于java:线程消耗的内存 您所在的位置:网站首页 warframe占多少内存 关于java:线程消耗的内存

关于java:线程消耗的内存

2024-04-14 00:38| 来源: 网络整理| 查看: 265

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

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

我在四个线程上运行了很长时间。尽管作业不会连续累积内存,但getThreadAllocatedBytes返回的值仍在增加,甚至不会下降。这意味着getThreadAllocatedBytes不会返回线程使用的堆上的实际内存量。它返回自线程启动以来在堆上为线程分配的内存总量。我的平台详细信息如下:

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的预期行为吗? 如果是这样,则无法在线程使用的堆上找到有效的内存。

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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394package 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 threadIds = Collections.synchronizedList(new ArrayList()); private void dummyJob() {     List primes = new ArrayList();     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(); } } 相关讨论 请注意,System.gc()不能保证GC已运行。 尤其是在您可能以小于毫秒的时间间隔调用System.gc()的情况下,VM可能决定将GC运行推迟到任意时间。 通常到可用内存因某种原因而变低时。 您能否提供一个更完整的示例,我想在本地重复您的实验。 SAP JVM(tools.hana.ondemand.com/#cloud)似乎完全支持此功能。 我从未使用过此VM,不过仅阅读它受支持。

据我所知,没有可靠的方法可以在运行时执行此操作。正如源问题中指出的那样,堆是共享资源,因此单个线程的堆大小没有意义,因为它会与其他线程的对象引用重叠。

就是说,当我确实想知道单个线程的"保留"大小,是的,保留大小与您所要求的度量标准是不同但相似的指标时,我可以通过进行堆转储然后使用MAT来实现。 (http://www.eclipse.org/mat/)。

我知道有人使用Java代理来检测对象的分配,然后使用弱引用来监视何时获得GC。但是,这样做对性能的影响很大。很高。

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

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

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

一个非常有用的工具可以帮助您发现是否存在泄漏,或者至少运行与预期不同,它是打印每个类当前在堆上有多少实例的计数:jcmd GC.class_histogram。

相关讨论 我主要对应用程序上下文中的运行时监视感兴趣。因此,在我们的案例中,从外部对应用程序进行性能分析不会有太大帮助。但是,我想检查分析器是否提供了每个线程的堆内存消耗。除了visualVM以外的所有产品均为商业许可。所以我只检查了VisualVM。它不提供每个线程使用的堆内存量。不知道是否有其他探查器提供此功能。根据到目前为止的答复和所有搜索,似乎没有办法获取每个线程消耗的堆内存量。 @SarveswaranMeenakshiSundaram是正确的,尚无确定的方法。正如一些答复所指出的那样,每个线程消耗的堆内存实际上意味着什么。堆是共享资源,任何单个对象都可以由多个线程访问。这就是我提到保留大小的原因,保留大小是可以离线或在运行时计算的指标。但是,在运行时会付出代价,并且取决于您的执行方式,它也不准确。脱机是实现此目的的正常方法,而MAT等免费工具支持该功能。两者的细节都在上面。

Java VisualVM可用于"监视本地应用程序,并查看内存堆,线程活动以及Java虚拟机(JVM)中加载的类的实时,高级数据。监视应用程序的开销较低,并且可以可以长期使用。"

另请参阅如何监视Java内存使用情况? 其他可能性。

相关讨论 我尝试了VisualVM。有一列显示每个线程分配的内存量。这与ThreadMXBean中的getThreadAllocatedBytes返回的值匹配。甚至视觉虚拟机也无法提供每个线程使用的堆上的实际内存!这意味着没有JVM级别的支持/黑客来实时监视每个线程使用的内存量。 如果使用netbeans,实际上是在Netbeans Profiler中,对吗? @DavidPostill ... @gumuruh不知道。这个问题与Netbeans无关。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有