为什么我的JVM访问的内存少于通过-Xmx指定的内存?

“嘿,你能来看看奇怪的东西吗?” 这就是我开始研究一个支持案例的方式,该案例将我引向了这篇博客文章。 当前的特殊问题与不同的工具报告了有关可用内存的不同数字有关。

简而言之,一位工程师正在研究特定应用程序的过多内存使用情况,据他所知,该应用程序可以使用2G的堆。 但是无论出于什么原因,JVM工具本身似乎都没有决定该进程真正拥有多少内存。 例如, jconsole猜测总可用堆等于1,963M,而jvisualvm声称其等于2,048M。 那么哪个工具是正确的,为什么另一个却显示不同的信息呢?

确实确实很奇怪,尤其是看到通常的可疑对象都被淘汰了– JVM并没有采取任何明显的技巧,例如:

  • -Xmx-Xms相等,因此在运行时堆增加期间报告的数字不会更改
  • 通过关闭自适应大小调整策略( -XX:-UseAdaptiveSizePolicy ),防止JVM动态调整内存池大小。

重现差异

理解问题的第一步是放大工具实现。 通过标准API访问可用的内存信息非常简单,如下所示:

System.out.println("Runtime.getRuntime().maxMemory()="+Runtime.getRuntime().maxMemory());

确实,这就是手头工具似乎正在使用的工具。 回答此类问题的第一步是拥有可重现的测试用例。 为此,我编写了以下代码段:

package eu.plumbr.test;
//imports skipped for brevitypublic class HeapSizeDifferences {static Collection<Object> objects = new ArrayList<Object>();static long lastMaxMemory = 0;public static void main(String[] args) {try {List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();System.out.println("Running with: " + inputArguments);while (true) {printMaxMemory();consumeSpace();}} catch (OutOfMemoryError e) {freeSpace();printMaxMemory();}}static void printMaxMemory() {long currentMaxMemory = Runtime.getRuntime().maxMemory();if (currentMaxMemory != lastMaxMemory) {lastMaxMemory = currentMaxMemory;System.out.format("Runtime.getRuntime().maxMemory(): %,dK.%n", currentMaxMemory / 1024);}}static void consumeSpace() {objects.add(new int[1_000_000]);}static void freeSpace() {objects.clear();}
}

该代码通过循环中的新int [1_000_000]分配内存块,并检查当前已知可用于JVM运行时的内存。 每当发现最后一个已知的内存大小发生更改时,它都会通过打印Runtime.getRuntime()。maxMemory()的输出来报告该更改,如下所示:

Running with: [-Xms2048M, -Xmx2048M]
Runtime.getRuntime().maxMemory(): 2,010,112K.

确实- 即使我已指定JVM使用2G堆,运行时仍无法以某种方式找到其中的85M 。 您可以通过将Runtime.getRuntime()。maxMemory()的输出除以2,010,112K除以1024来转换为MB,从而仔细检查我的数学运算。结果将等于1,963M,与2048M的差值为85M。

寻找根本原因

在能够重现案例之后,我记下了以下笔记–使用不同的GC算法运行似乎也会产生不同的结果:

GC算法 Runtime.getRuntime()。maxMemory()
-XX:+ UseSerialGC 2,027,264千
-XX:+ UseParallelGC 2,010,112千
-XX:+ UseConcMarkSweepGC 2,063,104千
-XX:+ UseG1GC 2,097,152千

除了G1完全消耗了我给该进程分配的2G内存外,其他所有GC算法似乎都始终丢失半随机的内存。

现在是时候深入研究JVM 的源代码了,在CollectedHeap的源代码中,我发现了以下内容:

// Support for java.lang.Runtime.maxMemory():  return the maximum amount of
// memory that the vm could make available for storing 'normal' java objects.
// This is based on the reserved address space, but should not include space
// that the vm uses internally for bookkeeping or temporary storage
// (e.g., in the case of the young gen, one of the survivor
// spaces).
virtual size_t max_capacity() const = 0;

我不得不承认答案是非常隐蔽的。 但是仍然有一些真正的好奇心可以找到的暗示–指的是在某些情况下,堆大小计算中可能会排除一个幸存空间

java-heap-permgen-不同的内存池

从这里一直是顺风顺水–打开GC日志记录发现,实际上,使用2G堆,串行,并行和CMS算法都将幸存空间的大小设置为恰好缺少了差异。 例如,在上面的ParallelGC示例中,GC日志记录演示了以下内容:

Running with: [-Xms2g, -Xmx2g, -XX:+UseParallelGC, -XX:+PrintGCDetails]
Runtime.getRuntime().maxMemory(): 2,010,112K.... rest of the GC log skipped for brevity ...PSYoungGen      total 611840K, used 524800K [0x0000000795580000, 0x00000007c0000000, 0x00000007c0000000)eden space 524800K, 100% used [0x0000000795580000,0x00000007b5600000,0x00000007b5600000)from space 87040K, 0% used [0x00000007bab00000,0x00000007bab00000,0x00000007c0000000)to   space 87040K, 0% used [0x00000007b5600000,0x00000007b5600000,0x00000007bab00000)ParOldGen       total 1398272K, used 1394966K [0x0000000740000000, 0x0000000795580000, 0x0000000795580000)

从中可以看到Eden空间设置为524,800K,两个幸存者空间(从和到)都设置为87,040K,旧空间的大小为1,398,272K。 将Eden,Old和一个幸存者空间加在一起总计为2,010,112K,这证实丢失的85M或87,040K确实是剩余的幸存者空间

摘要

阅读该文章后,您现在对Java API实施细节有了新的了解。 下次某些工具将总可用堆大小可视化为略小于Xmx指定的堆大小时,您会知道差异等于您的Survivor空间之一的大小。

我必须承认,这一事实在日常编程活动中并不是特别有用,但这不是该帖子的重点。 取而代之的是,我写了一篇文章,描述了我一直在优秀工程师中寻找的一个特殊特性- 好奇心 。 优秀的工程师一直在寻找了解事物如何以及为什么以某种方式起作用的方式。 有时答案仍然隐藏,但我仍然建议您尝试寻求答案。 最终,沿途积累的知识将开始带来红利。

翻译自: https://www.javacodegeeks.com/2015/02/jvm-access-less-memory-specified-via-xmx.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux怎么安装高德导航软件,高德地图车机版如何安装?高德地图车机版安装教程...

高德地图车机版是高德为汽车车载机提供的一个专用版本&#xff0c;对于车主们来说有时候用手机导航实在是非常不方便&#xff0c;不仅屏幕小而且还可能中途来个电话什么的。高德地图车机版可以帮你的车载机装上导航地图&#xff0c;就算你不想买导航设备也能让你的车子为你导航…

SharePoint 2010 技术参数(整理)

今天整理一些 SharePoint 2010 的技术参数&#xff0c;其内容都来自 SharePoint-Sandbox 网站。 有些参数值是硬性的&#xff0c;比如列表单条记录的尺寸&#xff1b;而有些是为了使用和性能考虑的推荐值。 技术参数值列表最大记录数500万条列表单条记录上限8KB&#xff08;不含…

Dropwizard,MongoDB和Gradle实验

介绍 我使用Dropwizard&#xff0c;MongoDB和Gradle创建了一个小项目。 它实际上是从一个实验性的Guava缓存开始的&#xff0c;作为将计数器发送到MongoDB&#xff08;或任何其他DB&#xff09;的缓冲区。 我也想尝试MondleDB插件的Gradle。 接下来&#xff0c;我想创建某种接口…

linux eclipse svn插件安装,Linux上Eclipse安装SVN插件和安装JavaHL

在Eclipse上安装svn插件有两种选择&#xff0c;一种是Subclipse&#xff0c;一种是Eclipse Subversion。前者是svn的官网eclipse插件&#xff0c;后者是eclipse的官方svn插件&#xff0c;具体有什么不同我也不算很清楚&#xff0c;想知道的请自行百度。网上建议用Subclipse&…

用apache的httpclient发请求和接受数据

此处发请求的是用httpclient4,请自己下载所需要的jar包。 发post请求&#xff0c;并得到数据。 String url "http://localhost:8080/lee";url url "/query/action/export.action";String exportFilePath "lee"".csv.";final HttpCl…

使用Flyway在Java EE中进行数据库迁移

任何Java EE应用程序的数据库模式都会随着业务逻辑一起发展。 这使得数据库迁移对于任何Java EE应用程序都非常重要。 您是否还在执行应用程序时手动执行它们&#xff1f; 它仍然是一个锁定步骤过程&#xff0c;还是作为两个单独的脚本运行–一个用于应用程序部署&#xff0c;…

suse linux安装rpm包,linux – 如何为Suse创建RPM

重建现有的src.rpm可能是最简单的.我肯定不会采用configure,make,make install的方式,因为(a)不能扩展,(b)不提供容易删除/升级包和(c)不是原子的.建立RPM并不是那么难.在他们销毁网站之前,Linux.com上曾经有一个非常好的初学者教程.你可以尝试这个one,但这是很多文字,不容易消…

在wp中,使用NavigationService.Navigate导航页面出现错误

我们在WP项目中采用页面导航时候&#xff0c;经常会使用以下代码 NavigationService.Navigate(new Uri("/Page1.xaml",UriKind.Relative));但是&#xff0c;有的时候会出现错误&#xff1a; "Error 1 An object reference is required for the non-static field…

linux iso合并,把RedHat Linux 5.0的CD ISO合并成DVD的脚本

最近找RedHat Linux5.0 x86_64的DVD ISO文件&#xff0c;结果一直找不到&#xff0c;却找到了6个cd的ISO&#xff0c;因为最后一个为源码盘&#xff0c;暂时不管&#xff0c;把其他5个CD合并成一个DVD。脚本如下&#xff1a;vim dvd.sh#!/bin/bash# by Chris Kloiber# A quick …

Guava的测试集合实现

我目前正在为LibFX添加一个新功能&#xff0c;为此我创建了一些类似于Java Collections Framework的自定义集合。 我一直在寻找可以针对它们进行测试的测试&#xff0c;并很高兴发现Google的Guava包含了我所需要的&#xff1a;一个庞大的测试套件&#xff0c;它针对JDK和Guava的…

SSDT – Error SQL70001 This statement is not recognized in this context-摘自网络

March 28, 2013 — arcanecode One of the most common errors I get asked about when using SQL Server Data Tools (SSDT) Database Projects is the error “This statement is not recognized in this context”. This is actually a pretty simple error to fix. Envisi…

linux wget 图片,15个Linux Wget下载实例终极指南

9、使用wget -i下载多个文件首先&#xff0c;保存一份下载链接文件cat>filelist.txt url1 url2 url3 url4接着使用这个文件和参数-i下载wget -i filelist.txt10、使用wget --mirror镜像网站下面的例子是下载整个网站到本地。wget --mirror -p --convert-links -P ./LOCAL UR…

带有JAX-RS和PrimeFaces的RESTful图表

通常&#xff0c;利用图表提供数据的可视表示很有用。 PrimeFaces提供制图解决方案&#xff0c;可轻松将数据的可视表示形式添加到Web和移动应用程序中。 如果将PrimeFaces图表组件与RESTful Web服务数据结合使用&#xff0c;我们可以创建自定义图表&#xff0c;以适合桌面和移…

UVAlive 6131 dp+斜率优化

这道题和06年论文《从一类单调性问题看算法的优化》第一道例题很相似。 题意&#xff1a;给出n个矿的重量和位置&#xff0c;这些矿石只能从上往下运送&#xff0c;现在要在这些地方建造m个heap&#xff0c;要使得&#xff0c;sigma距离*重量最小。 思路&#xff1a;O(n ^ 3)的…

c语言错误重定义,C语言的重定义错误求解

追问那如果要用到全局变量&#xff0c;要把它写在C文件中&#xff1f;那全局变量的主要作用其实就是跨文件作用域来传递一些东西&#xff0c;写在C文件中&#xff0c;不太好在别的文件中引用吧。用的时候写extern进去&#xff1f;感觉全局变量在C里用起来比较麻烦&#xff0c…

Netty:另一种Web(套接字)服务器

如今&#xff0c; Netty已用于Internet上的各种应用程序中&#xff0c;以处理数千&#xff08;即使不是数百万&#xff09;的聊天对话&#xff0c;包括Minecraft &#xff0c; Twitter和许多其他应用程序在内的多人游戏。 但是&#xff0c;它并没有在开发企业应用程序的企业程序…

arm opcode hook

/**************************************/* 作者:半斤八兩/* 博客:http://cnblogs.com/bjblcracked/* 日期:2013-09-05 11:11/**************************************只是感兴趣&#xff0c;没有其他目的。失误之处敬请诸位大侠赐教!因工作需要,最近一直在研究arm.看到论坛也…

c语言程序整数四则运算,c语言中三个整数随机的四则运算

满意答案hors10722014.01.06采纳率&#xff1a;58% 等级&#xff1a;12已帮助&#xff1a;18274人#include #include #include #define N 10 //随机出10道题目int main(){int num1, num2, num3, count0, result,resultTrue,flag;//result:用户输入结果 resultTrue:正确结果 …

带有调试器的Apache Camel Eclipse工具

大约2个月前&#xff0c; Lars Heineman在 JBoss工具堆栈中的博客中介绍了改进的Apache Camel Eclipse工具。 在即将发布的版本中&#xff0c;他们将Camel调试器与本机Eclipse调试器集成在一起&#xff0c;因此当您使用断点时&#xff0c;您将获得Eclipse调试体验&#xff0c;…

马秀丽C语言程序设计答案pdf,C语言程序设计清华大学马秀丽刘志妩科后习题9答案.doc...

C语言程序设计清华大学马秀丽刘志妩科后习题9答案习 题 9二 编程题main(){int n,*a,i,j,t0;scanf("%d",&n);for(i0;ifor(j0;jscanf("%d",ai*nj);for(i0;ifor(j0;jif (*(ai*nj)!0) t1;if (t0) printf("is xia san jiao fang zhen");else prin…