【问题标题】:High memory usage when resolving @Transactional解析@Transactional 时内存使用率高
【发布时间】:2014-02-04 10:58:53
【问题描述】:

我正在分析我的 web 应用程序(使用 Spring + Hibernate),并发现在必须将服务方法解析为事务性时,我会使用大量内存。

这是从控制器调用服务方法:

User e = userService.getUser();

这是服务中的上述方法:

@Transactional(readOnly = true)
    public User getUser(Long id) throws GenericDataBaseException, InstanceNotFoundException {
        User e = userDao.findById(id);
        return e;
    }

通过调试我的应用程序,我在方法调用(第一个代码 sn-p)中放置了一个断点,并在 getUser() 的第一行放置了另一个断点。现在只有 @Transactional 注释的注入和方面解析会触发 30 mb 的内存使用。这是 VisualVM 的屏幕截图:

你看到的颠簸是由这个电话引起的。现在,如果单个控制器方法多次调用事务服务方法,这会累积到大约 100MB 的内存使用量。这可能是垃圾收集,所以它不是内存泄漏,但我很好奇可能导致这个问题的原因,以及它是否是正常行为。这仅在第一次调用事务方法时发生。连续调用几乎不占用内存。

编辑:这是内存碰撞后的堆转储:

EDIT2:这是另一个屏幕截图,其中一些 ZipFileInflaterInputStream 中的 Finalizer 对象占用了大量内存(我不使用它!)

【问题讨论】:

  • 进行堆转储以查看当时内存中的内容。
  • 我在内存使用转储后使用堆转储编辑了我的原始帖子
  • 我发现这只发生在 LocalSessionFactoryBean 作为事务管理器的情况下。使用另一个事务管理器不会导致这种内存碰撞,我猜这与休眠 SessionFactory 使用太多内存有关。
  • 刚刚添加了我的堆转储的另一个屏幕截图,其中很多内存被一些 ZipFileInputStream 对象占用!
  • 我们很难远程分析这个,你有点靠你自己。您可以使用eclipse.org/mat 之类的工具来提供帮助。如果我是你,我会在之前和之后进行堆转储,然后尝试比较它们,或者使用 eclipse mat 尝试查找一些热点。祝你好运。

标签: java spring hibernate memory


【解决方案1】:

对不起,我无法发表评论,我没有足够的代表,但我猜想,Hibernate 正在创建 ZipFileInputStream 来处理、解压缩和创建被送回的对象为每个字段(可能)创建一个 Finalizer 实例的数据库。我猜这个文件会被压缩以进行传输,尽管如果你不使用 LocalSessionFactory 就不会发生这种情况很有趣。除了直觉之外,我没有任何证据证明这一点,但它可能会导致某个地方。

【讨论】:

  • 这听起来可能,我不知道 Hibernate 使用了 ZipFileInputStreams。无论如何,它似乎积累了太多的这些终结器实例,在我看来,它可能在终结对象时遇到了一些麻烦。问题是为什么?网上好像没有这方面的信息。
  • 哈哈哈我不知道 Hibernate 用它们做什么,这只是一个疯狂的猜测。您是否正在使用延迟加载的集合对象进行任何工作?您的用户对象是否包含 ArrayList 或 HashMap 或其他内容?
猜你喜欢
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 1970-01-01
  • 2011-03-31
  • 1970-01-01
  • 2011-09-17
相关资源
最近更新 更多