Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何通过堆中的多个StackTraceElement模拟完整gc_Java_Jvm_Java.util.concurrent - Fatal编程技术网

Java 如何通过堆中的多个StackTraceElement模拟完整gc

Java 如何通过堆中的多个StackTraceElement模拟完整gc,java,jvm,java.util.concurrent,Java,Jvm,Java.util.concurrent,最近我的运营同事报告生产环境有很多完整的gc,并影响应用程序响应时间。他提供了一个图像 他特别提到StackTraceeElement有85M,并建议不要使用这些代码,例如 e.printStackTrace(); 现在我想在本地模拟这种情况,并编写如下测试代码 public class FullGCByLogTest { private static final Logger log = Logger.getLogger(FullGCByLogTest.class); pu

最近我的运营同事报告生产环境有很多完整的gc,并影响应用程序响应时间。他提供了一个图像

他特别提到StackTraceeElement有85M,并建议不要使用这些代码,例如

e.printStackTrace();
现在我想在本地模拟这种情况,并编写如下测试代码

public class FullGCByLogTest {
    private static final Logger log = Logger.getLogger(FullGCByLogTest.class);
    public static final byte[] _1M = new byte[1 * 1024 * 1024]; //placeholder purpose

    public static void main(String[] args) throws InterruptedException {
        int nThreads = 1000; // concurrent count
        ExecutorService pool = Executors.newFixedThreadPool(nThreads);
        while (true) {
            final CountDownLatch latch = new CountDownLatch(nThreads);
            for (int i = 0; i < nThreads; i++) {
                pool.submit(new Runnable() {
                    @Override
                    public void run() {
                        latch.countDown();
                        try {
                            latch.await(); // waiting for execute below code concurrently
                        } catch (InterruptedException e1) {
                        }
                        try {
                            int i = 1 / 0;
                            System.out.println(i);
                        } catch (Exception e) {
                            e.printStackTrace();
                            // log.error(e.getMessage(), e);
                        }

                    }
                });
            }
            try {
                Thread.sleep(100); // interval 1s every concurrent calling
            } catch (InterruptedException e) {
            }
       }

    }
}
然后在jvisualvm VisualGC中,我发现旧的gen是7m,但我设置的最大堆是4m

此外,在heapdump中,我没有找到StackTraceElement。那么,我怎样才能成功地模拟这个问题呢


在实例化异常对象时,实际上会创建
StackTraceeElement
对象,一旦无法访问异常对象,它们就有资格进行垃圾收集

我怀疑导致(明显的)存储泄漏的真正原因是代码中的某些内容正在保存大量异常对象

调用
printStackTrace()
不会泄漏对象。你的同事误诊了这个问题。然而到处调用
printStackTrace()
是很难看的。。。如果这种情况频繁发生,将导致性能问题


您的模拟和结果是一条模糊的线索,但是堆比您要求的要大的可能原因是JVM已经“四舍五入”到了更大的堆大小。(4Mb是一个很小的堆大小,对于大多数Java程序来说是不切实际的。)


那么,我怎样才能成功地模拟这个问题呢


仿真不太可能告诉您任何有用的信息。您需要从生产系统获取堆转储并对其进行分析

为了重现,禁用预分配的异常非常重要
-XX:-省略StackTraceInFastThrow
谢谢!但是添加这个vm arg,仍然找不到stacktraceelementEach
StackTraceElement
包含对至少两个
String
实例(三个,如果源文件名已知)的引用,这三个实例又引用了一个带有实际字符串内容的
char[]
数组,该数组的大小通常超过了以前的对象。因此,在统计中看到秩3上的
StackTraceElement
非常奇怪,尤其是当秩2既不是
String
也不是
char[]
时。你的应用程序中有深度递归吗?@Holger谢谢!但是您说:“探查器应用程序在JVM本身中使用StackTraceElements记录调用堆栈的副作用。如果我们假设探查器在HashMap中存储调用方,那么这与HashMap$Entry实例的数量甚至更高的情况是一致的。”。其实我不明白,你能给我一些链接可以解释这一点吗?没有网站跟踪我并解释我的评论。我只是说了一种可能性,因为我们根本不知道你的同事用什么方法得到这个统计数据。毕竟,您同事的报告中包含的
HashMap$Entry
实例比
StackTraceElement
还要多,所以不清楚您为什么不担心它们(或最上面的条目)…谢谢!顺便说一句,我上面模拟并发调用的代码是正确的吗?没有更精确的方式来模拟并发调用没有“精确”的方式来“模拟”并发行为。它是不确定的。但是有1000个线程的线程池是毫无意义的。(一个创建数千个线程的实际应用程序非常需要重新设计。它可能只在线程堆栈上消耗千兆字节的非堆内存。)因此您认为我上面使用java代码的方式与
ab-n10000-c100相比http://foo.com
,哪一个更适合我的情况,哪一个更像真实情况下的并发性?不,我不知道。此外,您还没有提供任何证据来证明真正的问题(太多完整的gc)是与并发相关的问题。我认为你的这个“理论”是在浪费时间。您最好按照我上面所说的去做——获取堆转储并分析它是否存在可能的存储泄漏。这不是真正的证据。这纯粹是猜测。你>>可能
-Xmx4m -Xms4m -XX:NewSize=1m -XX:MaxNewSize=1m -XX:+PrintGCDetails