[英]Java: flushing memory out to disk
假设我有一个 Java 应用程序,它大致执行以下操作:
有没有办法鼓励或强制 JVM 在长时间空闲时将其内存刷新到磁盘? (例如,在第 2 步结束时,进行一些函数调用,有效地说“嘿 JVM!我要睡一会儿了。”)
我不介意使用大量虚拟内存,但物理内存在我使用的机器上非常宝贵,因为有很多后台进程。
我认为操作系统应该处理这个问题。
否则,您可以在初始化后手动将应用程序存储到磁盘或数据库,然后从该数据进行更快的初始化,也许吧?
与其让您的程序闲置并耗尽资源,为什么不使用 cron 对其进行调度? 或者更好的是,因为您使用的是 Java,所以使用Quartz 来安排它? 尽最大努力缓存冗长的初始化过程的元素,这样您就不必在每次计划任务运行时付出很大的代价。
您必须确保的第一件事是您的对象是可垃圾回收的。 但这只是第一步。
其次,JVM 使用的内存可能根本不会返还给操作系统。
例如。 假设您有 100mb 的 java 对象,您的 VM 大小约为 100mb。 在垃圾收集之后,您可以将堆使用量减少到 10mb,但 VM 将保持在 100mb 左右。 此策略用于允许 VM 为新对象提供可用内存。
要让应用程序将“物理”内存返回给系统,您必须检查您的 VM 是否支持这样的事情。
还有一些额外的VM 选项可以让您的应用程序向操作系统返回更多内存:
-XX:MaxHeapFreeRatio=70 GC 后空闲堆的最大百分比,以避免收缩。
-XX:MinHeapFreeRatio=40 GC 后堆空闲的最小百分比以避免扩展。
根据我自己的解释,如果使用这些选项,VM 将在低于 70% 时推卸。 但坦率地说,我不知道是只有堆会收缩并返回到操作系统,还是只在VM内部收缩。
有关热内存管理工作的完整描述,请参见:
HotSpot GC 描述:Java HotSpot 虚拟机中的内存管理白皮书: https : //www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf
拜托,拜托。 试一试并让我们知道这是否有效地减少了内存消耗。
至少可以说这是一个黑客,但假设您使用的是 Win32 并且如果您准备放弃可移植性 - 编写一个调用SetProcessWorkingSetSize的小 DLL 并使用 JNI 调用它。 这允许您向操作系统建议WS 大小应该是什么。 您甚至可以指定 -1,在这种情况下,操作系统将尝试尽可能多地分页。
假设这是一个等待请求的服务器,你能这样做吗?
这意味着内存密集型 Worker 对象会从内存中卸载(当 gc 下次运行时,您可以通过在将 Worker 对象设置为 null 后调用 System.gc() 来鼓励 gc 运行),但是由于您保存了它的状态,您可以从磁盘重新加载它并让它完成工作而无需再次进行初始化。 如果它需要每“x”小时运行一次,您可以在 Server 类中放置一个 java.util.Timer 而不是侦听套接字。
编辑:还有一个 JVM 选项 -Xmx 用于设置 JVM 堆的最大大小。 在这种情况下这可能没有帮助,但只是想我会把它扔在那里。
这不是页面文件的用途吗? 如果您的 JVM 闲置了一段时间并且不访问它的内存页面。 它很可能会被分页,因此不会使用太多的实际 RAM。
但是你可以做一件事......大多数守护程序都有一个启动阶段(它们解析文件并创建数据结构等)和一个运行阶段,它们使用在启动时创建的对象。 如果 JVM 被允许,它将在第二阶段启动而不进行垃圾收集,这可能会导致进程的大小增长,然后在进程的生命周期内保持那么大(因为 GC 从不/很少减少实际大小)过程)。
如果您确保在下一个阶段开始之前在程序生命周期的每个不同阶段分配的所有内存都是可 GC 的,那么您可以使用 -Xmx 设置来强制降低进程的最大大小,并使您的程序在阶段之间不断进行 GC。 我以前这样做过并取得了一些成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.