Java 如何让JVM使用服务器的最大(全部剩余)内存

Java 如何让JVM使用服务器的最大(全部剩余)内存,java,memory,memory-management,jvm,Java,Memory,Memory Management,Jvm,我有一个DFS算法java控制台应用程序,当提供更多内存时运行得更快。只是一个DFS算法应用程序,既没有I/O,也没有其他外部JVM资源使用。它只消耗CPU和内存。应用程序可以使用1GB内存运行,但使用2GB内存运行速度更快。提供的内存越多,应用程序运行得越快。由于提供了12GB内存,我还没有达到速度限制。所以我必须使用服务器的所有剩余内存来加速它。而且应用程序不需要并行,一次只需要一个请求 我需要在不同的服务器上安装不同内存大小的应用程序 有没有办法让JVM使用服务器的所有剩余内存 -XX:M

我有一个DFS算法java控制台应用程序,当提供更多内存时运行得更快。只是一个DFS算法应用程序,既没有I/O,也没有其他外部JVM资源使用。它只消耗CPU和内存。应用程序可以使用1GB内存运行,但使用2GB内存运行速度更快。提供的内存越多,应用程序运行得越快。由于提供了12GB内存,我还没有达到速度限制。所以我必须使用服务器的所有剩余内存来加速它。而且应用程序不需要并行,一次只需要一个请求

我需要在不同的服务器上安装不同内存大小的应用程序

有没有办法让JVM使用服务器的所有剩余内存

-XX:MaxRAMFraction=1
MaxRAMFraction并不是每台服务器都好,有些服务器会导致启动JVM失败,比如位置内存故障,有些工作正常

使用包装器应用程序获取系统剩余内存,减去除Xmx以外的一些内存使用量,然后使用相同的Xms和Xms启动实际应用程序。该方法还将导致JVM内存分配错误。因为下面的代码返回的内存远远超过了我们可以使用的内存,而不仅仅是Xss256m的负数或更多的非堆JVM内存

com.sun.management.OperatingSystemMXBean mbean = (com.sun.management.OperatingSystemMXBean)
    ManagementFactory.getOperatingSystemMXBean();
long size = mbean.getFreePhysicalMemorySize();

那么,有没有一种好方法可以让JVM使用服务器的所有剩余内存呢?

对于堆外使用的大内存区域,这可以减少GC上的开销,好处之一是在运行时可以是任何大小,如果您仔细操作,甚至可以比主内存大。您可以使用direct
ByteBuffer
s,但我使用了我编写的一个库,它扩展了ByteBuffer功能(>>2 GB且线程安全)。任何人使用的最大容量是约100 TB映射到磁盘的虚拟内存

在编年史字节之上有两个数据结构,一个键值存储和一个队列/日志。这可以使用更高级别的接口更容易地存储堆外数据

按照堆的工作方式,它必须在启动时将最大堆大小保留为单个连续虚拟内存块。特别是,GC假设在清理时随机访问此内存,这意味着如果您的内存使用率略高,可能是因为在您的内存之后启动了一个进程,并且交换了一些堆,那么您将看到整个机器的性能急剧下降。Windows倾向于开始交换GUI,这意味着如果不关闭电源,就无法恢复控制。Linux并没有那么糟糕,但此时您会想要终止您的进程。这使得调整它的大小,以使用所有的内存非常困难,如果您的机器使用的变化


通过比较使用虚拟内存,GC不会触及它,因此未使用的部分几乎没有影响。虚拟内存的面积可以是主内存的许多倍,但只有当前的工作集才重要,这是运行时完全由您控制的大小。注意:在Linux上,虚拟内存的大小可以是可用磁盘空间的1000倍,但请小心使用,如果触摸过多页面而耗尽内存,程序将崩溃。

编写一个在操作系统上运行的脚本,以找出剩余内存,然后用-Xmx和剩余内存量启动Java。注意:这可能很危险,因为时间点X的内存需求可能与时间点Y非常不同。您想要什么使它非常依赖于何时启动VM(是否在夜间批处理作业期间?)-最好从所需内存量的角度出发,而不是从可用内存的角度出发。@ErwinBolwidt这不是夜间批处理作业,只是一个DFS算法应用程序,既没有I/O,也没有其他外部JVM资源。应用程序可以使用1GB内存运行,但如果使用2GB内存运行得更快,则提供的内存越多,应用程序运行得越快。那么,为什么不使用服务器的所有剩余内存呢?如果您从未在服务器上运行过其他任何东西,并且服务器的内存使用随着时间的推移总是相同的,那么当然,没有问题。但是,您也可以手动确定一次,并找出要传递给Java的
-Xmx
参数。@Erwin手动确定一次:(如果我需要在几十台不同的服务器上安装应用程序,并使用不同的内存大小,那将是一件可怕的事情。我也不确定在服务器/操作系统维护后,可用内存是否会发生变化。正如我在第一篇评论中所建议的,您可以在启动Java之前编写一个脚本来确定它。无论如何,您都需要知道在启动Java之前,您不能在VM启动后更改它。这是一个很好的解决方案。要应用它,OP需要控制源代码和带宽,以适应您的库,但这取决于他的用例,这可能是值得的。@ErwinBolwidt如果他不想使用我的库,他可以使用多个ByteBuffers,尽管这样做会有好处我怀疑还有更多的工作要做。是的,堆外使用是一个伟大而正确的想法。我也在考虑做这件事(或者干脆换一种内存管理更好的语言?哈哈)。但是旧的应用程序有大量的对象类型需要保留在内存中,将其重写为仅使用字节的堆外方法将是非常痛苦的。因此,我们可以只关注一些方法而不太更改代码吗?@rufushuang最简单的解决方案当然是添加更多内存。我不建议使用堆外方法,直到您的数据/堆已经恢复und 32 GB。我8岁的孩子有一台旧电脑,我已经2年没用了,它有24 GB,我的电视有16 GB。如果你需要1+TB,自我管理的虚拟内存是任何语言中唯一的答案。