Tag: 垃圾收集

JVisualVM / JConsole中的System.gc()vs GC按钮

我目前正在测试我的概念certificate原型处理XML模式,并围绕一个非常耗费内存的外部库构建树自动机(我已经获得了源代码),我想绘制“真正的峰值”(堆) )随着模式大小的增加,不同运行的内存消耗(使用的度量标准适合我的purpouse并且不影响问题),或者至少是它的合理近似值。 为了给出一个数量级,对于一个真正的峰值为100MB的运行(我测试它运行几次完全相同的输入/参数配置,强制jvm内存-Xmx和-Xms减少值,我得到Exception in线程“main”java.lang.OutOfMemoryError:GC开销限制超过 <100MB,具有稳定且可重复的结果)它占用大约1.1GB,这就是为什么获取实数非常重要,因为它们差别很大! 我花了最近10天在网上和stackoverflow中阅读问题,我实际知道的是: System.gc()“建议”GC运行,不以任何方式强制它,因此不可能依赖它来检测内存使用峰值 通常建议的是计算对象占用(我看到了SizeOf项目,我尝试并且工作正常,即使它不符合我的需要),这对我来说是不可行的,因为由于创建了大量的内存分配很多收集(设置,列表和映射)迭代器在不同的方法中,被称为非常多次(对于我记忆中的10分钟,每个数百万次),因此检测所有涉及的对象将非常困难并执行总和(我用内存消耗图调试了很多次运行而不能只识别一个瓶颈) 没有办法轻易获得方法的内存占用(表示为对象内存分配的峰值) 事实上,我自己经历过System.gc()调用不可靠(例如,由于GC真的被调用而在System.gc()之后读取不同的内存),但是当我按下JVisualVM或Jconsole中的“GC按钮”它永远不会运行GC或拒绝这样做。 所以我的问题是:调用它们的按钮实现(我还没有尝试过,但是对于我现在所读到的,使用带有attach api的 jconsole.jar似乎是可行的)将不同于直接调用System.gc()从我的代码,从而解决我的问题? 如果没有,你如何解释该按钮的“确定性行为”? 到目前为止,我对10个增加的模式大小进行了实际内存峰值的手动测试(对于这种测量,模式是从单个“复杂度参数”自动生成的)并且我绘制了预期曲线,如果我将无法获得一个更好的解决方案我想将我的代码作为外部jar运行,其中-Xmx / -Xms等于略低于我对预期内存峰值的预测,捕获外部进程ErrorStream中的OutMemoryException并重新启动增加的内存直到完成运行已完成。 (如果天真的记忆预测不够健壮,我将应用适当的机器学习技术)。 我知道这不是一个优雅的解决方案,但在我的情况下(学术界)我可以花费一些额外的时间来进行这些测量。 如果您对此powershell方法有其他建议或改进,欢迎(非常)欢迎您分享。 系统信息(机器是Fedora 17,64位): java版“1.7.0_04”Java(TM)SE运行时环境(版本1.7.0_04-b20)Java HotSpot(TM)64位服务器VM(版本23.0-b21,混合模式) 在此先感谢,亚历山德罗

我可以在java中连续分配对象吗?

假设我有一大堆相对较小的对象,我需要经常迭代。 我想通过提高缓存性能来优化我的迭代,所以我想在内存上连续分配对象 [而不是引用],这样我就可以减少缓存丢失,整体性能可以更好。 在C ++中,我可以只分配一个对象数组,它会按照我的意愿分配它们,但是在java中 – 在分配数组时,我只分配引用,并且一次只分配一个对象。 我知道如果我“一次”分配对象[一个接一个],jvm 最有可能将对象分配为尽可能连续,但如果内存碎片化则可能还不够。 我的问题: 有没有办法告诉jvm在我开始分配对象之前对内存进行碎片整理? 是否足以确保[尽可能]连续分配对象? 这个问题有不同的解决方案吗?

垃圾收集器是守护程序线程吗?

垃圾收集器是守护进程(后台)线程吗? 谢谢。

标记要在GC中删除的对象

有没有我可以在java中标记一个对象,以便在下次清理时进行垃圾回收? 我听说将对象设置为null不再有效。

Java中的垃圾收集如何工作?

我想知道Java中的垃圾收集器如何处理以下情况。 对象A具有对象B的引用,而对象B具有对对象C的引用。主程序具有对象A的引用。因此,您可以通过对象A使用对象B,通过对象A通过对象B使用对象C. 如果对象A和对象B之间的链接设置为null,对象B和对象C会发生什么? 现在垃圾收集器是否收集了对象B和对象C? 我的意思是对象B和对象C之间仍然存在连接。

Java垃圾收集器 – 定期运行不正常

我有一个不断运行的程序。 通常,它似乎是垃圾收集,并保持在大约8MB的内存使用量。 但是,每个周末,它都会拒绝垃圾收集,除非我明确打电话给它。 但是,如果它接近最大堆大小,它仍将是垃圾收集。 然而,注意到这个问题的唯一原因是因为它实际上在一个周末因内存耗尽而崩溃,即它必须达到最大堆大小,而不是运行垃圾收集器。 下图(单击以查看)是程序一天内存使用情况的图表。 在图的两侧,您可以看到程序内存使用情况的正常行为,但第一个大峰似乎是周末开始的。 这个特殊的图是一个奇怪的例子,因为在我对垃圾收集器进行了一次显式调用后,它成功运行了,但随后它又回到了最大堆大小并成功地将垃圾收集到它自己的两次。 这里发生了什么? 编辑: 好的,从评论来看,似乎我没有提供足够的信息。 程序只接收UDP数据包流,这些数据包放在队列中(设置为最大大小为1000个对象),然后对其进行处理,使其数据存储在数据库中。 平均而言,它每秒大约有80个数据包,但可以达到150个。它在Windows Server 2008下运行。 问题是,这个活动是相当一致的,如果有的话,在内存使用开始时它稳定攀升,活动应该更低,而不是更高。 请注意,我上面发布的图表是我唯一一个延伸到目前为止的图表,因为我只更改了Java Visual VM包装器,以便将图形数据保持足够远,以便在本周看到它,所以我不知道它是否完全正确每周的同一时间,因为我不能在周末观看它,因为它是在私人网络上,而且我周末不上class。 这是第二天的图表: 这几乎就是每周其他日子的内存使用情况。 程序永远不会重新启动,我们只会在周一早上告诉它垃圾收集因为这个问题。 有一周我们尝试在星期五下午重新启动它,它在周末的某个时间仍然开始爬升,所以我们重新启动它的时间似乎与下周的内存使用没有任何关系。 它成功地垃圾收集所有这些对象的事实,当我们告诉它向我暗示对象是可收集的时,它只是在它达到最大堆大小时才执行它,或者我们显式调用垃圾收集器。 堆转储没有告诉我们什么,因为当我们尝试执行一个时,它突然运行垃圾收集器,然后输出堆转储,这当然看起来完全正常。 所以我想我有两个问题:为什么它突然没有垃圾收集它在本周剩余时间内的方式,为什么在一个场合,当达到最大堆大小时发生的垃圾收集无法收集所有这些对象(也就是说,为什么会有一次这么多对象的引用,而每隔一段时间就不会有这样的对象)? 更新: 今天早上很有趣。 正如我在评论中提到的,该程序正在客户端的系统上运行。 我们在客户组织中的联系人报告说,凌晨1点,该程序失败了,他今天早上上class时必须手动重启,而且服务器时间再次不正确。 这是我们过去曾遇到过的一个问题,但直到现在,这个问题似乎从来没有关系过。 查看我们的程序生成的日志,我们可以推断出以下信息: 在01:00,服务器以某种方式重新启动它的时间,将其设置为00:28。 在00:45(根据新的,不正确的服务器时间),程序中的一个消息处理线程抛出了内存不足错误。 但是,另一个消息处理线程(我们收到两种类型的消息,它们的处理方式略有不同,但它们都不断进入),继续运行,并且像往常一样,内存使用量继续攀升,没有垃圾回收(从我们记录的图表中可以看出,再一次)。 在00:56,日志停止,直到早上7点,我们的客户重新启动程序。 但是,此时的内存使用情况图仍在稳步增长。 不幸的是,由于服务器时间的变化,这使得我们的内存使用图上的时间不可靠。 但是,它似乎是尝试垃圾收集,失败,将堆空间增加到最大可用大小,并立即杀死该线程。 既然最大堆空间已经增加,它很乐意在不执行主要垃圾收集的情况下使用所有堆空间。 所以现在我问这个问题:如果服务器时间突然像它一样发生变化,那么这会导致垃圾收集过程出现问题吗?

java – 垃圾收集器如何快速知道哪些对象不再引用它们?

我知道在Java中,如果一个对象不再有任何引用,垃圾收集器会在一段时间后回收它。 但是垃圾收集器如何知道某个对象是否有与之关联的引用? 垃圾收集器是使用某种hashmap还是表? 编辑: 请注意,我不是在问gc的工作原理。 真的,我不是那么想的。 我特别要求gc知道哪些对象是活的,哪些是死的,效率很高。 这就是为什么我在我的问题中说gc维护某种hashmap或set,并且不断更新对象的引用数量?

匿名监听器是否与弱引用不兼容?

我正在读这个刚问的问题: 避免回调中的内存泄漏? 我很困惑,直到有人回答以下问题: “这种方法的问题是你不能有一个只在集合中引用的监听器,因为它会随机消失(在下一个GC上)” 我是否理解使用弱引用(如存储在WeakHashMap中)与匿名侦听器不兼容? 我通常传递这样的听众: public static void main(String[] args) { final Observable obs = new SomeObservable(); obs.addObserver(new Observer() { public void update(final Observable o, final Object arg) { System.out.println(“Notified”); } }); obs.notifyObservers(); … // program continues its life here } private static final class SomeObservable extends Observable { @Override public void addObserver(final Observer […]

除了互斥锁或垃圾收集之外的哪些机制可以减慢我的multithreadingjava程序?

问题 我有一段java代码(相关的JDK 1.6.0._22),它实现了一个没有互斥量的无状态,无副作用的函数。 然而它确实使用了大量内存(我不知道这是否相关)。 在过去,我访问过Sun Laboratories并收集了标准的“性能与线程数”曲线。 由于这个函数没有互斥锁,它有一个很好的图形,尽管随着线程数量的增加垃圾收集开始。 经过一些垃圾收集调整后,我能够使这条曲线几乎平坦。 我现在在英特尔硬件上做同样的实验。 硬件有4个CPU,每个CPU有8个内核和超线程。 这给出了64个availableProcessors()。 不幸的是,“性能与线程数”的曲线很好地适用于1,2,3线程和3线程的大写。 在3个线程之后,我可以根据需要添加任意数量的线程,并且性能不会更好 尝试解决问题 我的第一个想法是我曾经愚蠢并在某处引入了一些同步代码。 通常要解决此问题,我运行JConsole或JVisualVM,并查看线程堆栈跟踪。 如果我有64个线程以3的速度运行,我预计其中有61个会等待进入互斥锁。 我没有找到这个。 相反,我发现所有线程都在运行:非常慢。 第二个想法是,时间框架可能引入了问题。 我用一个虚拟函数替换了我的函数,使用AtomicLong计算到十亿。 这与线程数量相当精确:使用64个线程比使用1个线程,我能够快速计算到10倍10,000倍。 我想(绝望开始)也许垃圾收集花了很长时间,所以我调整了垃圾收集参数。 虽然这改善了我的延迟变化,但它对吞吐量没有影响:我仍然有64个线程以我期望3运行的速度运行。 我已经下载了英特尔工具VTunes,但我的技巧很弱:它是一个复杂的工具,我还不明白。 我订购了说明书:给自己一个有趣的圣诞礼物,但是现在有点太晚了 题 我可以用什么工具(精神或软件)来提高我对正在发生的事情的理解? 除了互斥锁或垃圾收集之外的哪些机制可能会减慢我的代码速度?

有没有办法在Java中安排完整的垃圾收集?

我有一个24×6计划运行的应用程序。 目前,在运行几天后,会自动执行Full GC – 通常在一天的繁忙时段执行,这会对用户响应时间产生负面影响。 我想做的是强制使用全GC – 可能在每晚的午夜,在极低的使用时间内 – 以防止它在白天发生。 我已经尝试过System.gc(),但它似乎并不能保证何时会发生Full GC,或者即使它会发生。 有没有办法做到这一点? 版本信息: Java(TM)SE运行时环境(版本1.6.0_11-b03) Java HotSpot(TM)服务器VM(版本11.0-b16,混合模式) 另外 – 小型GC正在运行,大约每10-15秒运行一次。 但这些都没有释放足够的RAM来让应用程序整整一周。 当Full GC确实发生时,将释放近50%的堆。 关于上述内容,调用System.gc()似乎并不意味着任何下一个GC都将具有释放那些大量内存所需的Full格式。 是的,它已启用(或未启用,具体取决于您阅读-XX选项的方式)。 我已经玩了几个CMS GC设置,这有很大帮助,但没有解决问题。 最初它每周投掷两次到三次OOM。 我想停止无限循环: 不断增加堆空间 – 这只能持续这么长时间 不断调整和测试GC设置 – 它已经超过了收益递减点 我不想像对待NT机器那样对待它,并且每晚都会反弹。 整个晚上都有活跃的用户会话,弹出应用程序意味着会丢失会话数据。 更具体地说,我正在寻找一种技术来确保完全GC将要发生,而不是一个简单的方法/函数来调用它来运行它。 目前,我正在考虑修改CMS使用的百分比阈值,以确定何时需要完整GC。 谢谢你的帮助。