假设我有一个Java应用程序,大致如下:
有没有办法鼓励或强制JVM在长时间闲置期间将其内存刷新到磁盘? (例如,在第2步结束时,进行一些函数调用,有效地说“HEY JVM!我将要睡一段时间。”)
我不介意使用大块虚拟内存,但物理内存在我正在使用的机器上非常重要,因为有很多后台进程。
答案 0 :(得分:2)
我认为操作系统应该处理这个问题。
否则,您可以手动将应用程序存储到磁盘或数据库后初始化,并可以从该数据进行更快的初始化,可能吗?
答案 1 :(得分:2)
为什么不用cron安排它,而不是让你的程序闲置并耗尽资源?或者更好的是,既然您正在使用Java,请使用Quartz进行安排?尽力缓存冗长的初始化过程中的元素,这样每次计划任务运行时都不必支付大笔罚金。
答案 2 :(得分:2)
您必须首先确定的是,您的物品是垃圾收集品。但这只是第一步。
其次,JVM使用的内存可能根本不会返回给操作系统。
例如。假设你有100 MB的java对象,你的VM大小将是100mb aprox。垃圾收集后,您可以将堆使用量减少到10 MB,但VM将保持在100 MB左右。此策略用于允许VM为新对象提供可用内存。
要让应用程序将“物理”内存返回给系统,您必须检查VM是否支持此类内容。
还有其他VM options 可能允许您的应用向操作系统返回更多内存:
-XX:MaxHeapFreeRatio = 70 GC之后的最大堆空闲百分比,以避免收缩。
-XX:MinHeapFreeRatio = 40 GC之后的最小堆空闲百分比,以避免扩展。
根据我自己对这些选项的解释,如果VM低于70%,VM将会推卸。但坦率地说,我不知道只有堆会缩小和返回到操作系统,还是只收缩内部 VM。
有关热点的完整描述,内存管理工作请参见:
HotSpot GC的描述:Java HotSpot虚拟机中的内存管理白皮书:http://java.sun.com/j2se/reference/whitepapers/memorymanagement_whitepaper.pdf
请拜托。试一试并测量一下,如果这有效地减少了内存消耗,请告诉我们。
答案 3 :(得分:1)
至少可以说这是一个黑客,但假设你在Win32上并且如果你准备放弃可移植性 - 编写一个调用SetProcessWorkingSetSize并使用JNI调用它的小DLL。这允许您向操作系统建议 WS大小应该是什么。您甚至可以指定-1,在这种情况下,操作系统将尝试尽可能地分页。
答案 4 :(得分:0)
假设这类似于正在等待请求的服务器,你可以这样做吗?
这意味着内存密集型Worker对象从内存中卸载(当gc下次运行时,你可以通过在将Worker对象设置为null后调用System.gc()来鼓励gc运行),但是因为你保存它的状态,你有能力从磁盘重新加载它,让它做它的工作,而无需再次进行初始化。如果需要每隔“x”小时运行一次,则可以在Server类中放置java.util.Timer,而不是在套接字上监听。
编辑:还有一个JVM选项-Xmx,用于设置JVM堆的最大大小。在这种情况下,这可能没什么用,但只是想我会把它丢进去。
答案 5 :(得分:0)
这不是页面文件的用途吗?如果您的JVM空闲了很长时间并且没有访问它的内存页面。它很可能会被分页,因此不会使用太多实际的RAM。
你可以做的一件事......大多数守护程序都有一个启动阶段(他们解析文件和创建数据结构等)和一个运行阶段,他们使用启动时创建的对象。如果允许JVM,它将在第二阶段启动而不进行垃圾收集,可能导致进程的大小增长,然后在进程的生命周期内保持那么大(因为GC从不/很少减少实际的大小处理)。
如果在下一个阶段开始之前确保在程序生命周期的每个不同阶段分配的所有内存都是GCable,那么可以使用-Xmx设置强制降低进程的最大大小并使程序持续GC阶段之间。我之前已经取得了一些成功。