Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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 web应用程序_Java_Garbage Collection - Fatal编程技术网

频繁垃圾收集java web应用程序

频繁垃圾收集java web应用程序,java,garbage-collection,Java,Garbage Collection,我有一个web应用程序,它根据用户请求将JavaBean序列化为xml或json 当我给它加上一点负载时,它会很快使用所有分配的内存,并达到最大容量,我面临着一个令人费解的问题。然后,我观察到完整GC每20-40秒都非常努力地工作 看起来不像是内存泄漏问题。。。但我不太确定如何解决这个问题 序列化为xml/json的bean引用了其他bean和其他bean。我使用json库和jaxb来序列化bean yourkit内存分析器告诉我char[]是最消耗内存的活动对象 任何洞察都是值得赞赏的。如果没

我有一个web应用程序,它根据用户请求将JavaBean序列化为xml或json

当我给它加上一点负载时,它会很快使用所有分配的内存,并达到最大容量,我面临着一个令人费解的问题。然后,我观察到完整GC每20-40秒都非常努力地工作

看起来不像是内存泄漏问题。。。但我不太确定如何解决这个问题

序列化为xml/json的bean引用了其他bean和其他bean。我使用json库和jaxb来序列化bean

yourkit内存分析器告诉我char[]是最消耗内存的活动对象


任何洞察都是值得赞赏的。

如果没有更多的信息(代码和GC日志),就不可能诊断出这一点,但我的猜测是,您正在以大字符串的形式读取数据,然后用substring()切掉小位。当您这样做时,子字符串使用与父字符串相同的底层字符数组生成,因此只要它是活动的,就会将该数组保留在内存中。这意味着这样的代码:

String big = a string of one million characters;
String small = big.substring(0, 1);
big = null;
仍将在内存中保留巨大字符串的字符数据。如果是这种情况,则可以通过构造新实例,强制小字符串使用新的、更小的字符数组来解决此问题:

small = new String(small);

但正如我所说,这只是一个猜测。

我不确定您的代码中有多少内容,以及您正在使用的工具中可能有多少内容,但有一些关键的东西需要注意

最糟糕的情况之一是在循环中不断添加字符串。一个简单的“hello”+“world”一点问题都没有,它实际上非常聪明,但是如果你在一个循环中这样做,它会不断地重新分配字符串。尽可能使用StringBuilder

有一些Java探查器可以快速将您指向分配发生的位置。只需在java应用程序运行时使用探查器闲逛一段时间,您就可以将GCs减少到几乎为零,除非问题在您的库中——即使这样,您也可以找到解决问题的方法


您分配然后快速释放的东西不需要GC阶段的时间--。确保你没有把绳子留得比你需要的时间长。在从请求处理程序返回之前,将它们带进来,处理它们并返回到以前的状态。

有两种可能:内存泄漏,或者您的Web应用程序正在生成大量垃圾

  • 判断是否有内存泄漏的蛮力方法是运行它很长一段时间,看看它是否会因OOME而崩溃。或者打开GC日志记录,查看垃圾收集后剩余的平均空间是否随着时间的推移不断增加

  • 无论是否存在内存泄漏,都可以通过增加最大堆大小来提高性能(减少GC时间百分比)。事实上,你的webapp看到了很多完整的GCs,这对我来说意味着它需要更多的堆。(如果内存泄漏,这只是一种绷带解决方案。)

  • 如果事实证明您没有遭受内存泄漏,那么您应该看看应用程序为什么会产生这么多垃圾。这可能取决于您执行XML和JSON序列化的方式


您应该附上套件并记录分配(例如,每10次分配;包括所有大的分配)。他们有一个诊断过度gc的分步指南:

对我来说,这听起来像是您试图通过某个未准备好的编码器序列化递归对象。
(或者至少:非常深入/几乎是递归的)

你为什么认为自己有问题?GC是一种自然和正常的事情。我们的客户每秒使用GC(持续时间不到100毫秒),只要不断回收内存就可以了


在我看来,每20-40秒进行一次GCing并不是一个问题——只要它不占用20-40秒的大部分时间。大多数主要的商业JVM的目标是将GC保持在5-10%的时间范围内(20-40秒中只有1-4秒)。以GC日志的形式发布更多数据可能会有所帮助,我还建议使用类似的工具来帮助您可视化并获得有关GC配置文件外观的建议。

Java的原生XML API确实“嘈杂”,通常在资源方面是浪费的,这意味着如果您的请求和XML/JSON生成周期很短,总承包商将有很多东西需要清理


我调试了一个非常类似的案例,并以艰难的方式发现了这一点,我至少可以在不进行重大重构的情况下有所改善的唯一方法是使用适当的VM标志隐式调用GC,这实际上会使
System.GC()从非操作调用到可能的操作调用。

我首先检查正在运行的应用程序,查看堆上创建了什么。
可以为您收集这些信息,然后可以使用进行分析。

可以在命令行中使用来调试内存分配问题。可以跟踪收集的对象分配,并根据其生命周期将收集的对象拆分为存储桶


在跟踪模式下,此工具可用于。

只需注意:字符串在内部使用char[]。对于web应用程序/web服务来说,这并不奇怪。您为该应用程序分配了多少内存-X*参数感谢所有建议。。。一旦我想出你的建议,我会更新的。说得好,特伦特。但是频繁的GC意味着更多的工作,这就是为什么我认为这是一个问题。让我们把它具体化——你在GC中花费的时间百分比是多少?我认为这是你真正想关注的衡量标准,以确定你是否有问题。