Li *_*oyi 65 java memory performance operating-system web-services
有没有什么好方法可以在运行时将剩余内存提供给JVM?这种情况的用例是让Web服务在接近其内存限制时优雅地失败,拒绝新连接时出现错误消息"太多人使用它,稍后再试",而不是突然死于OutOfMemory错误.
注意,这与预先计算/估计每个对象的成本无关.原则上,我可以估计我的对象占用了多少内存,并根据该估计拒绝新连接,但这似乎有点hacky/fragile.
Bli*_*der 82
编辑:我最初提供了这个样本(链接到William Brendel关于另一个主题的答案).该主题的创建者(Steve M)想要创建一个多平台Java应用程序.具体来说,用户试图找到一种方法来评估运行机器的资源(磁盘空间,CPU和内存使用情况).
这是该主题中给出的答案的内联记录.然而,尽管我的回答被标记为已被接受,但已经在该主题上指出它不是理想的解决方案.
public class Main {
public static void main(String[] args) {
/* Total number of processors or cores available to the JVM */
System.out.println("Available processors (cores): " +
Runtime.getRuntime().availableProcessors());
/* Total amount of free memory available to the JVM */
System.out.println("Free memory (bytes): " +
Runtime.getRuntime().freeMemory());
/* This will return Long.MAX_VALUE if there is no preset limit */
long maxMemory = Runtime.getRuntime().maxMemory();
/* Maximum amount of memory the JVM will attempt to use */
System.out.println("Maximum memory (bytes): " +
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
/* Total memory currently in use by the JVM */
System.out.println("Total memory (bytes): " +
Runtime.getRuntime().totalMemory());
/* Get a list of all filesystem roots on this system */
File[] roots = File.listRoots();
/* For each filesystem root, print some info */
for (File root : roots) {
System.out.println("File system root: " + root.getAbsolutePath());
System.out.println("Total space (bytes): " + root.getTotalSpace());
System.out.println("Free space (bytes): " + root.getFreeSpace());
System.out.println("Usable space (bytes): " + root.getUsableSpace());
}
}
}
Run Code Online (Sandbox Code Playgroud)
用户Christian Fries指出,假设Runtime.getRuntime().freeMemory()在发生内存不足错误之前可以分配的内存量是错误的.
从文档中,签名返回Runtime.getRuntime().freeMemory()是这样的:
返回:当前可用于将来分配的对象的内存总量的近似值,以字节为单位.
但是,用户Christian Fries声称这个功能可能会被误解.他声称,在发生内存不足错误(可用内存)之前可能分配的大致内存量可能由以下公式给出:
long presumableFreeMemory = Runtime.getRuntime().maxMemory() - allocatedMemory;
Run Code Online (Sandbox Code Playgroud)
随着allocatedMemory被给出:
long allocatedMemory =
(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
Run Code Online (Sandbox Code Playgroud)
这里的关键是自由记忆概念之间的差异.一件事是操作系统提供Java虚拟机的内存.另一个是包含Java虚拟机本身实际使用的内存块的块的总字节数.
考虑到Java应用程序提供的内存是由Java虚拟机以块为单位进行管理的,因此Java虚拟机可用的可用内存量可能与Java应用程序可用的内存不完全匹配.
具体来说,Christian Fries表示使用-mx或-Xmx标志来设置Java虚拟机可用的最大内存量.他注意到以下功能差异:
/* Returns the maximum amount of memory available to
the Java Virtual Machine set by the '-mx' or '-Xmx' flags. */
Runtime.getRuntime().maxMemory();
/* Returns the total memory allocated from the system
(which can at most reach the maximum memory value
returned by the previous function). */
Runtime.getRuntime().totalMemory();
/* Returns the free memory *within* the total memory
returned by the previous function. */
Runtime.getRuntime().freeMemory();
Run Code Online (Sandbox Code Playgroud)
克里斯蒂安总结了他的答案,说明Runtime.getRuntime().freeMemory()事实上可以回归所谓的可能的自由记忆; 即使未来的内存分配没有超过该函数返回的值,如果Java虚拟机尚未收到主机系统分配的实际内存块,java.lang.OutOfMemoryError仍可能产生a.
最后,正确使用的方法将对应用程序的细节有不同程度的依赖性.
我提供了另一个可能有用的链接.这是用户Richard Dormand提出的问题,并由stones333回答了有关确定使用的默认Java堆大小的问题.
Chr*_*ies 64
注:所有的答案到目前为止,即使是接受了一个,似乎通过说回答这个问题Runtime.getRuntime().freeMemory()让你可以分配,直到出现内存不足,错误的内存量.但是:这是错误的.
在发生内存不足错误之前可以分配的大致内存量,即可能的空闲内存
long presumableFreeMemory = Runtime.getRuntime().maxMemory() - allocatedMemory;
Run Code Online (Sandbox Code Playgroud)
哪里
long allocatedMemory = (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
Run Code Online (Sandbox Code Playgroud)
说明:
如果通过-mx参数(或-Xmx)启动JVM,则指定JVM可用的最大数量.Runtime.getRuntime().maxMemory()会给你这个金额.从这个系统内存量中,JVM将以块为单位分配内存,例如64 mb的块.在开始时,JVM将仅从系统分配这样的块而不是全部量.Runtime.getRuntime().totalMemory()给出了系统分配的总内存,同时Runtime.getRuntime().freeMemory()为您提供免费的内存中分配的内存总量.
因此:
long definitelyFreeMemory = Runtime.getRuntime().freeMemory();
Run Code Online (Sandbox Code Playgroud)
是JVM已经保留的可用内存,但它可能只是少量的.你可能会得到presumableFreeMemory.当然,即使您尝试分配小于的数量,也可能会出现内存不足异常presumableFreeMemory.如果JVM没有从系统获取下一个内存块,则可能会发生这种情况.但是,在大多数系统上,这种情况永远不会发生,系统宁愿开始交换 - 这是您想要避免的情况.Wrt原来的问题:如果-mx设置为合理的值,那么它presumableFreeMemory是空闲内存的一个很好的指标.
除了使用Runtime方法之外,您还可以使用获取一些额外的内存信息
MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heap = memBean.getHeapMemoryUsage();
MemoryUsage nonheap = memBean.getNonHeapMemoryUsage();
Run Code Online (Sandbox Code Playgroud)
每个MemoryUsage提供init,used,committed和max值.如果创建一个内存监视器线程来轮询内存并将其记录下来,这可能很有用,为您提供一段时间内存使用情况的历史记录.有时,查看导致错误的内存使用情况会很有帮助.
如果你真的想把它变为极端,那就创建一个堆转储线程.监控你的内存使用情况随着时间的推移,当它超过一定的阈值时,执行以下操作(这适用于JBoss 5.0 - 你的里程可能会有所不同):
// init code
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean diagBean = ManagementFactory.newPlatformMXBeanProxy(server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
// loop code
// add some code to figure if we have passed some threshold, then
File heapFile = new File(outputDir, "heap-" + curThreshold + ".hprof");
log.info("Dumping heap file " + heapFile.getAbsolutePath());
diagBean.dumpHeap(heapFile.getAbsolutePath(), true);
Run Code Online (Sandbox Code Playgroud)
稍后您可以使用eclipse 内存分析器或类似工具查看这些堆转储文件,以检查内存泄漏等.
除了另一个答案之外,我想要注意的是,这样做不一定是个好主意,因为您的应用程序中可能有一个使用SoftReferences的缓存.
一旦JVM达到其内存限制,这样的缓存就会释放内存.分配内存,即使没有足够的可用内存,也会首先导致内存被软引用释放,并使其可用于分配.
要获取操作系统范围内的可用内存,请OSHI使用以下maven依赖项添加:
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>LATEST</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
然后在Java中,使用以下代码:
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
long availableMemory = hal.getMemory().getAvailable();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
72876 次 |
| 最近记录: |