jjzjj

java - 即使没有 GC 根,类加载器也不会被垃圾回收

coder 2024-03-28 原文

我们有一个在 Glassfish V2.1.1 下运行的复杂应用程序。为了能够动态加载我们的代码,我们实现了一个能够重新定义类的 CustomClassloader。 行为非常简单:当动态加载的类发生变化时,CustomClassloader 的当前实例将被“丢弃”,并创建一个新实例来重新定义所需的类。

除了同一个类被重新加载几次后(因此每次创建一个新的 CustomClassloader),这工作得很好,我们得到一个 PermGen 空间错误,因为 CustomClassloader 的其他实例没有被垃圾收集。 (该类应该只有一个实例)

我尝试了不同的方法来追踪泄漏的位置:

  1. visualvm => 我进行堆转储并提取 CustomClassloader 的所有实例。我可以看到它们都没有最终确定。当我检查最近的 GC 根目录时,visualvm 告诉我没有(最后一个实例除外,因为它是“真正”使用过的根目录)。
  2. jmap/jhat => 它给了我几乎相同的结果:我看到了 CustomClassloader 的所有实例,然后当我单击链接以查看其中一个的引用在哪里时,我得到一个空白页面,这意味着没有...
  3. Eclipse Memory Analyzer Tool => 当我运行以下 OQL 查询时,我得到了一个奇怪的结果: SELECT c FROM INSTANCEOF my.package.CustomClassloader c 只有一个结果,表明只有一个实例显然是正确的。

我也检查了这个link并在创建新的 CustomClassloader 时实现了一些资源释放,但没有任何变化:PermGen 内存仍在增加。

所以我可能遗漏了一些东西,第 (1-2) 点和 (3) 点之间的差异显示了一些我不理解的东西。我在哪里可以了解问题出在哪里? 由于我遵循的所有教程都展示了如何使用“搜索最近的 GC 根”功能搜索泄漏的引用(在我的例子中没有),我不知道如何跟踪错误。

编辑 1:我上传了一个堆转储示例 here .可以使用以下查询在 visualvm 中选择未卸载的 ClassLoader:select s from saierp.core.framework.system.SAITaskClassLoader s 可以看到有 4 个实例,前三个应该被收集,因为没有 GC 根......某处一定有引用,但我不知道如何搜索它。欢迎任何提示:)

编辑 2:经过一些更深入的测试后,我看到了一个非常奇怪的模式。泄漏似乎取决于 OpenJPA 正在加载的数据:如果没有加载新数据,则可以对类加载器进行 GC,否则不会。这是我在创建新的 SAITaskClassLoader 以“清除”旧的时使用的代码:

PCRegistry.deRegister(cl);
LogFactory.release(cl);
ResourceBundle.clearCache(cl);
Introspector.flushCaches();

= 模式 1(类加载器被 GCed):=

  1. 新的 SAITaskClassLoader
  2. 加载数据 D1、D2、...、Dn
  3. 新的 SAITaskClassLoader
  4. 加载数据 D1、D2、...、Dn
  5. ...

= 模式 2(类加载器未被 GC):=

  1. 新的 SAITaskClassLoader
  2. 加载数据 D1、D2、D3
  3. 新的 SAITaskClassLoader
  4. 加载数据 D3、D4、D5
  5. 新的 SAITaskClassLoader
  6. 加载数据 D5、D6、D7
  7. ...

在所有情况下,被清除的SAITaskClassLoader都没有GC根。我们正在使用 OpenJPA 1.2.1。

谢谢和最好的问候

最佳答案

如果没有 CustomClassLoader 的源代码片段或实际的堆转储,将很难找到问题所在。您的 CustomClassLoader 不能是单例。如果是,则您的设计无法正常工作(或者我遗漏了一些东西)。

您需要获取 CustomClassLoader 类型的 ClassLoader 实例列表,并追踪对这些对象的引用。

这些帖子可能会帮助您进一步分析它并深入了解寻找 ClassLoader 泄漏的黑暗细节:

关于java - 即使没有 GC 根,类加载器也不会被垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13778822/

有关java - 即使没有 GC 根,类加载器也不会被垃圾回收的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  3. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  9. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  10. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

随机推荐