我们有一个基于Java的应用程序(TeamCity,Tomcat,Java1.7)运行在Windows 2012 R2上。Java运行的最大堆大小为6GB,系统有10 6GB的RAM。它是机器上唯一运行的非OS服务。
对于稳定的状态,一切都很好。不幸的是,当Java偶尔执行一个完整的GC时,我们发现Java堆的一部分已经被分页,需要回呼,因此GC需要几分钟而不是几秒。
普遍的观点是,永远不要完全禁用Windows页面文件,但我不知道这是否是一个反例?(我们真的不想让这个世界停顿几分钟,因为它会把它写回GC!)
是否有更好的方法来确保JVM不会被分页到磁盘,因为高IO工作负载会导致Windows驱逐一些堆,而倾向于磁盘缓存?
谢谢你,罗伯
发布于 2015-01-28 18:02:14
爪哇。:(
首先,我将给您一个简短的回答:是的,我认为这可能是一个没有页面文件运行的有效理由,当然,我知道您将无法再生成系统崩溃转储,并且您的机器将崩溃或不稳定到您希望内存耗尽时它会崩溃的程度。然而,你只需要为自己权衡利弊。从技术上讲,Windows可以在没有页面文件的情况下正常运行,只要您不使用内存.例如,除非旧的或设计糟糕的应用程序愚蠢地假设存在分页文件。
现在,长话短说。
首先,为什么会发生分页?操作系统使用页面替换算法,其中每个内存页都标记为“年龄”,这是自上次访问内存页以来的计数器。有很长一段时间没有被访问的内存页最终会被写入磁盘,以便其他可能更重要的数据可以在RAM中得到空间。如果一个进程更频繁地使用其分配的内存,那么将这些页面写入页面文件的可能性就会更小。
应用程序开发人员可以调用VirtualLock Windows函数来要求Windows将页面锁定到调用进程的工作集中。但是,要想成功地调用该功能,需要一定的操作系统权限,因为如果您玩得不好,将页面锁定到RAM中的能力可能会对整个系统产生不利影响。但这对您没有帮助,因为VirtualLock是您在开发应用程序时在代码中使用的东西。你不能在别人的运行过程中调用它。
但是使用Java,现在您正在运行一个虚拟机,它的内部内存管理器位于实际的操作系统和内存管理器之上,这两者并不总是很好地协同工作,就像您正在体验的那样。将进程(或者更准确地说,将进程分配的所有内存锁定到物理内存中)锁定到物理内存是操作系统特有的,因此Java不会处理它,因为Java致力于实现不可知论和跨平台。
因此,我所知道的让Java将其分配锁到RAM中以避免被分页的唯一方法是使用JNI ()和mlock()/mlockall()。
https://serverfault.com/questions/663100
复制相似问题