Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:将内存刷新到磁盘_Java_Memory Management - Fatal编程技术网

Java:将内存刷新到磁盘

Java:将内存刷新到磁盘,java,memory-management,Java,Memory Management,假设我有一个Java应用程序,它大致完成以下功能: 初始化(需要很长时间,因为这很复杂) 快点做些事情 等待很长时间(这里是您最喜欢的机制) 转至步骤2 有没有办法鼓励或强制JVM在长时间空闲时将其内存刷新到磁盘上?(例如,在第2步结束时,进行一些函数调用,有效地说“嘿,JVM!我要睡一会儿。”) 我不介意使用一大块虚拟内存,但在我使用的机器上,物理内存非常重要,因为有很多后台进程。我认为操作系统应该处理这个问题 否则,您可以在初始化后手动将应用程序存储到磁盘或数据库中,并从该数据进行更快的初始

假设我有一个Java应用程序,它大致完成以下功能:

  • 初始化(需要很长时间,因为这很复杂)
  • 快点做些事情
  • 等待很长时间(这里是您最喜欢的机制)
  • 转至步骤2
  • 有没有办法鼓励或强制JVM在长时间空闲时将其内存刷新到磁盘上?(例如,在第2步结束时,进行一些函数调用,有效地说“嘿,JVM!我要睡一会儿。”)


    我不介意使用一大块虚拟内存,但在我使用的机器上,物理内存非常重要,因为有很多后台进程。

    我认为操作系统应该处理这个问题


    否则,您可以在初始化后手动将应用程序存储到磁盘或数据库中,并从该数据进行更快的初始化,也许?

    与其让程序处于空闲状态并耗尽资源,为什么不使用cron计划它呢?或者更好的是,既然您使用的是Java,那么就用?尽量缓存冗长的初始化过程中的元素,这样就不必在每次计划任务运行时都付出太大的代价。

    至少可以说这有点像黑客,但假设您在Win32上,并且准备放弃可移植性,那么就编写一个小DLL,使用JNI调用它。这允许您向操作系统建议WS的大小。您甚至可以指定-1,在这种情况下,操作系统将尝试尽可能多地向外翻页。

    假设这类似于正在等待请求的服务器,您可以这样做吗

  • 创建两个类,Server和Worker
  • 服务器仅在需要时侦听和启动Worker
  • 如果员工从未进行过初始化,请对其进行初始化
  • 在Worker完成它需要做的任何事情之后,序列化它,将它写入磁盘,并将Worker对象设置为null
  • 等待请求
  • 当收到请求时,从磁盘读取序列化的工作对象并将其加载到内存中
  • 执行辅助任务,完成后,序列化、写出并将辅助对象设置为null
  • 冲洗并重复
  • 这意味着内存密集型工作对象将从内存中卸载(当gc下次运行时,您可以在将工作对象设置为null后通过调用System.gc()来鼓励gc运行),但由于您保存了它的状态,因此您可以从磁盘重新加载它,并让它完成工作,而无需再次进行初始化。如果它需要每“x”小时运行一次,那么可以在服务器类中放置java.util.Timer,而不是监听套接字


    编辑:还有一个JVM选项-Xmx,它设置JVM堆的最大大小。在这种情况下,这可能没有帮助,但我只是想把它扔进去

    您必须确保的第一件事是,您的对象是可垃圾回收的。但这只是第一步

    其次,JVM使用的内存可能根本不会返回到操作系统

    比如说。假设您有100mb的java对象,您的VM大小大约为100mb。在垃圾收集之后,您可以将堆使用量减少到10mb,但VM将保持在100mb左右。此策略用于允许VM为新对象提供可用内存

    要让应用程序将“物理”内存返回到系统,您必须检查VM是否支持这样的操作

    您的应用程序还可以通过其他方式向操作系统返回更多内存:

    -XX:MaxHeapFreeRatio=70 GC后堆空闲的最大百分比,以避免收缩

    -XX:MinHeapFreeRatio=40在GC之后为避免扩展而释放的堆的最小百分比

    根据我自己的解释,如果低于70%,虚拟机将逃避使用这些选项。但坦率地说,我不知道是只有堆会收缩并返回到操作系统,还是只在虚拟机内部收缩

    有关热内存管理工作的完整说明,请参阅:

    Java HotSpot虚拟机白皮书中的HotSpot GCs说明:内存管理:


    求你了,求你了。试一试,然后告诉我们这是否有效地减少了内存消耗。

    这不是页面文件的用途吗?如果JVM空闲任意时间,并且不访问其内存页。它很可能会被分页,因此不会使用太多实际RAM

    但你可以做一件事。。。大多数守护程序都有一个启动阶段(解析文件和创建数据结构等),还有一个运行阶段,使用启动时创建的对象。如果允许JVM运行,它将在第二阶段启动,而不进行垃圾收集,这可能会导致进程的大小增加,然后在进程的生命周期内保持如此大的大小(因为GC从不/很少减少进程的实际大小)


    如果在下一个阶段开始之前确保在程序生命周期的每个不同阶段分配的所有内存都是可GCable的,那么可以使用-Xmx设置强制降低进程的最大大小,并使程序在阶段之间不断GC。我以前也这样做过,并取得了一些成功。

    Quartz是否擅长鼓励JVM在空闲期间将内存分页到磁盘?@Jason S:Quartz基本上是用Java编写的cron。因此,它所做的只是安排任务,这些任务运行并终止,这自然会释放所有内存。基本上,我建议您重新考虑您的设计,使您的任务是一个单一的执行,可以由调度器多次调用,而不是由守护进程调用。@asah因为Quartz在Java中是一个cron,您无论如何都必须保持应用程序运行,所以cron被安排在第一位。不过,收集内存的问题仍然存在。这只能解决第一步3@OscarReyes:Quartz是一个始终存在的守护进程