【问题标题】:How to free up memory?如何释放内存?
【发布时间】:2011-01-31 05:32:34
【问题描述】:

一段时间以来,我们的应用服务器一直面临内存不足错误。我们看到已用堆大小逐渐增加,直到最终达到可用堆大小。这种情况每 3 周发生一次,之后需要重新启动服务器来解决此问题。 通过对堆转储的分析,我们发现问题出在 JSP 中使用的对象。

JSP 对象会是 Appserver 内存问题的真正原因吗?我们如何释放 JSP 对象(使用 usebean 或其他标签实例化的对象)?

我们有一个带有 2 个节点和一个 IHS 的集群 Websphere 应用服务器。

编辑:上面的发现是基于下面使用 IBM 支持助手给出的 heap-dump 和 nativestderr 日志分析

nativestd err 日志分析:

alt text http://saregos.com/wp-content/uploads/2010/03/chart.jpg

堆转储分析:

![替代文字][2]

显示直接支配者的堆转储分析(上图中的 hastable 条目的 2 级)

![替代文字][3]

最后一张图片显示直接支配者实际上是在 JSP 中使用的对象。

EDIT2:更多信息请访问http://saregos.com/?p=43

【问题讨论】:

  • 我记得一个与部署未预编译的 JSP 相关的旧内存泄漏问题。 sun 编译器存在内存泄漏,JSP 在被引用时正在动态编译,这最终导致内存不足错误。解决方案是在部署之前预编译 JSP。
  • 但在我们的例子中,堆耗尽是逐渐的......内存在 3 周内耗尽。这似乎不是预编译问题。此外,我们会预编译我们的 JSP
  • 3 周 - 无论在应用程序中做了什么?你使用任何与计时器相关的东西吗?听起来像是一个没有正确释放的周期性动作。
  • 如果您使用的是最新版本的 Java,请确保使用包含的 VisualVM 进行分析...您可以拍摄正在创建的对象的快照,这对于调试这些对象非常有用东西。
  • Ahhh...www-01.ibm.com/support/docview.wss?uid=swg1PK38940 出现内存泄漏 .... 堆使用量随着时间的推移而增加,这会导致 OutOfMemory 情况。对堆转储的分析表明,以下对象占用的空间越来越多: 40,543,128 [304] 47 class com/ibm/wsspi/rasdiag/DiagnosticConfigHome 40,539,056 [56] 2 java/util/Hashtable 0xa8089170 40,539,000 [2,064] 511 数组java/util/Hashtable$Entry 0xaac7ef20 6,300,888 [40] 3 java/util/Hashtable$HashtableCacheHashEntry

标签: java memory-leaks websphere out-of-memory


【解决方案1】:

我先附上一个分析工具,告诉你这些“对象”是什么占用了所有内存。

Eclipse 有 TPTP, 或者有 JProfiler 或JProbe。

其中任何一个都应该显示对象堆正在增加,并允许您检查它以查看堆上的内容。

然后搜索代码库以找到创建这些的人。

也许你有一个包含元素的缓存或树/地图对象,而你只对这些对象实现了“equals()”方法,并且需要实现“hashcode()”。 这将导致地图/缓存/树变得越来越大,直到它倒塌。 不过这只是猜测。

JProfiler 将是我的第一个电话

Javaworld 有内存中内容的示例屏幕截图...


(来源:javaworld.com

还有一个对象堆建立和清理的屏幕截图(因此是锯边)


(来源:javaworld.com

更新 ********************************************** ***

好的,我会看看...

http://www-01.ibm.com/support/docview.wss?uid=swg1PK38940

堆使用量随着时间的推移而增加,这会导致 OutOfMemory 健康)状况。对 heapdump 的分析表明,以下内容 对象正在占用越来越多的空间:

40,543,128 [304] 47 类

com/ibm/wsspi/rasdiag/DiagnosticConfigHome 40,539,056 [56] 2 java/util/Hashtable 0xa8089170 40,539,000 [2,064] 511 个 java/util/Hashtable$Entry 数组 6,300,888 [40] 3 java/util/Hashtable$HashtableCacheHashEntry

【讨论】:

  • 我已经分析了 heapdumps、coredumps 和 nativestderr 日志并得到了对象列表。然而问题是如何解决这个问题......
  • 哇不错的堆大小! :-) 好的,我会在 JSP 中搜索任何地图的/hashmap/treemaps 等。我猜想某个地方有人正在使用 String 键将对象放入 hashmap 中,而该键还不够安静。或者作为 key 的对象没有实现 equals 和 hashcode 方法。
【解决方案2】:

据我了解,那些顶级内存消耗者是缓存存储和存储在其中的对象。可能您应该确保缓存在占用过多内存时会释放对象。如果您只需要缓存活动对象,则可能需要使用weak-ref。

【讨论】:

    【解决方案3】:

    我建议阅读Effective Java, chapter 2。跟踪它以及分析器将帮助您确定应用程序产生内存泄漏的位置。

    释放内存并不是解决大量内存消耗的方法。大量的内存消耗可能是由两件事造成的:

    • 未正确编写代码 - 解决方案是正确编写代码,使其不会消耗超过所需的内容 - 有效的 Java 将在此提供帮助。
    • 应用程序只需要这么多内存。然后你应该使用XmxXmsXX:MaxHeapSize,...来增加VM内存。

    【讨论】:

      【解决方案4】:

      如果您在 Sun 6 JVM 下运行,强烈考虑使用 JDK 中的 jvisualvm 程序来初步了解程序内部实际发生的情况。快照比较确实可以帮助您进一步了解哪些对象潜入。

      如果 Sun 6 JVM 不是一个选项,那么请调查您拥有哪些分析工具。试验可以让你走得很远。

      它可以是一些简单的东西,比如你在列表中收集的子字符串下面的巨大字符数组,例如家务。

      【讨论】:

        【解决方案5】:

        至少据我所知,没有具体的释放 JSP 中分配的对象。与其调查这些选项,我更愿意专注于在您的应用程序代码中找到实际问题并进行修复。

        一些可能有帮助的提示:

        • 检查 bean 的范围。不是 你例如存储用户或 请求具体到“应用程序” 范围(错误地)?
        • 检查 Web 应用程序中的 Web 会话超时设置,然后 应用服务器设置。
        • 您提到堆消耗逐渐增长。如果真是这样, 尝试查看堆大小 随着各种用户场景的增长: 获取堆转储,运行测试,让 会话数据超时,抓另一个 转储,比较两者。那可能 让你知道堆上的对象来自哪里
        • 检查您的 bean 是否有任何明显的内存泄漏,确定 :)

        编辑:检查 Daniel 提到的未发布的静态资源是另一件值得做的事情 :)

        【讨论】:

          【解决方案6】:

          手动触发垃圾回收并不能解决您的问题 - 它不会释放仍在使用的资源。

          您应该使用分析工具(如 jProfiler)来查找您的漏洞。您可能使用的代码将引用存储在运行时未释放的列表或映射中 - 可能是静态引用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-09-10
            • 2017-06-26
            • 2020-07-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多