为什么Java程序占用的内存比实际分配给它的要多
很多人错误的认为运行Java程序时使用-Xmx和-Xms参数指定的就是程序将会占用的内存,但是这实际上只是Java堆对象将会占用的内存。堆只是影响Java程序占用内存数量的一个因素。要更好的理解你的Java程序将会占用多大的内存需要先了解有哪些因素会影响到内存的占用。这些因素包括:
- 对象(Objects)
- 类(Classes)
- 线程(Theads)
- 本地数据结构(Native data structures)
- 本地代码(Native code)
每个因素对内存占用的影响又会随着应用程序、运行环境和系统平台的不同而变化,那怎样计算总的内存占用量?是的,想得到一个准确的数字不是那么容易,因为你很难控制本地(Native)部分。你能控制的部分只有堆大小:-Xmx,类占用的内存:-XX:MaxPermSize,还有线程栈:-Xss控制每个线程占用的内存。注意当把栈大小设置的太小时会导致StackOverflow异常、程序出错。所以,计算公式为:
(-Xmx) + (-XX:MaxPermSize) + 线程数 * (-Xss) + 其它内存
其它内存部分取决于本地代码占用的内存,如NIO、socket缓冲区、JNI等。它一般大约是jvm内存的5%左右。所以假设我们有下面的JVM参数和100个线程:
-Xmx1024m -XX:MaxPermSize=256m -Xss512k
那么jvm进程至少会占用内存数量为:1024m + 256m + 100*512k + (0.05 * 1330m) = 1396.5m
我一般使用(1.5 * 堆最大值)来作为一个近似值表示一个tomcat进程会需要的最小内存,如果你有需要增加MaxPermSize到256M以上的应用这个值可以更大些。如果你使用这个来衡量你的系统将会占用多少内存要记住你需要为系统和其它运行在系统上的程序留下足够的内存,否则会导致系统使用过多的虚拟内存,这样会降低性能。
不光是Java,任何依托在OS上执行的程序,OS所分配的内存都要大于程序内部自己申请的内存.很简单的道理,你不是一个人再战斗,程序的运行牵涉到方方面面,你写的代码只是其中的一个环节.托管语言更不可控.
我觉得Java把主要精力放到堆上是和它的gc相关,与线程相关的内存生命周期短。可能和主题不相干,看完之后想到的,就回复了。
空间换时间 。
如果内存很小的话 你看看JIT 还能不能那么强大 当然 是JIT可以跑起来的环境 但是内存小。
就是说除了程序所占用的内存,还有一个虚拟机在消耗内存。
Java所编写的程序在运行的时候占用内存是否真的很大了?“java程序运行的时候占用内存很大”我相信只要接触IT这个行业的人大部分的人都会毫不犹豫回答java程序运行的时候占用内存很大。也是许多java程序员默认的说法。在这里在这里我想在这里说下。
和许多程序员一样我也从c转到java的。由于c是公认的最接近机器语言的,而大部分程序员都会c语言。所以这里我用c与java进行测试比较结果。测试环境:计算机:P4,CPU:2.1GHz;内存:2G;jdk:1.7
测试:为了让效果精确,我特意让c和java两个程序所实现的功能语句尽量相同,在所写的行数上也力求一致。除此之外最重要的是让程序能裸奔。好啦,我相信大家和我一样迫不及待了吧,现在让我们来开始测试:
java:
public class JavaTest{
public static void main(String[] args){
for(int i=1;i<100000;i++){
for(int j=1;j<100000;j++){
}
}
}
}
现在我们在CMD中键入:java JavaTest<回车>,然后打开“任务管理器”可以看到这个程序占用内存“4910K”,也许大家看到这里还是觉得它占用内存很大。不要急的,我们再在CMD中键入:java @##@¥<回车>,这个是故意输错参数的,应为这个是java.exe本身运行的时候占用的内存,这个时候我们在看“任务管理器”显示进程占用内存为“4371K”。
那么这个程序到底占用内存多少了?4910K-4371K=539K.
好啦,我们现在来看看c程序运行的结果:
c:
int main (int argc,char* argv[])
{
for(int i=1;i<100000;i++){
for(int j=1;j<100000;j++){
}
}
return 0;
}
我们用vc++6.0编译运行,同样查看“任务管理器”程序占用内存情况。
可以看出内存为“675K”.
测试结果:总体来看,java进程“4910K”的确比c进程的“675K”多占用几倍内存。但是如果除去java本身所占用的内存,那么,这个java进程所占用内存实际占用比c进程占用内存还小,哈哈。。可能说道这里大家都不相信,呵呵。。。可是这是事实,大家如果不相信可以亲自测试下,那么大家可能要问那么java本身的占用内存那么大为什么啊?呵呵。。。只要大家看看sun公司开发java语言的目标和优点,就知道为什么啦,这个介绍就不具体时候了,网上有许多解释的文章,大家有需要可以上网了解一下。在这里另外说明一点的就是c能做的事情java也能做到,并且能很快做到,做的很好。除了很底层的事情:驱动、原始套接字(相信以后sun会提供)、系统级的程序(谁让系统是用c开发的了)。以后大家在看见有人说java占的内存多就可以辩论下了!同时也可以让大家明白凡事要自己求证,尤其作为程序员!
java占用大,是因为jvm、gc机制和oop造成的。
你这个简单的循环打印,因为有常量池的存在所以内存占用不明显,这是jvm对于自我的优化。
c++的很多方面都由自己手动和编译器控制,所以一个优秀的程序员和一个优秀的c++编译器同样重要。
而java把这方面更多的交由jvm控制,释放了程序员的压力,降低了程序员的门槛。
----------------------------------------------------------------------------------------------------
这个测试实例,是最简单的100000*100000次的循环,这个里面没有涉及到人工的任何优化,虽然jvm和c++编译器都会进行优化,对于这个内部优化谁的说不清楚在某种情况下谁优化的更好,现在很多的高级语言,很多都是基于c做起来的,所以暂时假设两种优化效果一样!很多客观的原因不能考虑一样,但是我们尽量做到一样、、、哈、、、这个也是做一定的探索、、、
---------------------------------------------------------------------------
在这里另外说明一点的就是c能做的事情java也能做到,并且能很快做到,做的很好。除了很底层的事情:驱动、原始套接字(相信以后sun会提供)、系统级的程序(谁让系统是用c开发的了)。这叫C能做的事情Java都可以做?那C可以写JVM.Java能写JVM么?就是因为Java干不了C的活所以才用C来做。另外内存占用C是可以调整的在PE结构里面就可以修改。Java可以修改么?单纯循环。vc连接器里面可以指定输出的可执行文件默认内存。最小可以优化到1k。非要比这个那就比吧讨厌那些Javaer总是自以为是的认为Java无敌的思想。如果你想要承认自己无敌你就要做出一些让别人信服的。C内存占用大那是系统分配给他就这么大。堆栈本身就需要占用。这个是可以优化掉的。JVM你可以优化掉么?优化掉Java怎么执行?所以被自欺欺人了。Java本来就以牺牲运行性能和内存为代价来模拟跨平台的。没人说错了。开发效率挺高的。这点牺牲也很值得。
为什么Java程序占用的内存比实际分配给它的要多的更多相关文章
- Java程序占用的内存可能会大于Xmx
很多人认为Xmx和-Xms参数指定的就是Java程序将会占用的内存,但是这实际上只是Java堆对象将会占用的内存.堆只是影响Java程序占用内存数量的一个因素. 除了堆,影响Java程序所占用内存的因 ...
- Java程序占用实际内存大小
很多人错误的认为运行Java程序时使用-Xmx和-Xms参数指定的就是程序将会占用的内存,但是这实际上只是Java堆对象将会占用的内存.堆只是影响Java程序占用内存数量的一个因素.要更好的理解你的J ...
- java程序运行时内存分配详解
java程序运行时内存分配详解 这篇文章主要介绍了java程序运行时内存分配详解 ,需要的朋友可以参考下 一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个 ...
- c/C++编译的程序占用的内存分为以下几个部分
首先要搞清楚编译程序占用的内存的分区形式:一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)—由编译器自动分配释放,存放函数的参数值,局部变量的值等 ...
- Java程序运行时内存划分
1.Java程序跨平台运行的原因 主要原因是:各种平台的JVM和字节码文件 Java源程序--具体平台的机器代码文件---被编译器翻译成平台无关的Class文件,又用特定JVM运行字节码文件,JVM在 ...
- linux下分析java程序占用CPU、内存过高
一.CPU过高分析 1)使用TOP命令查看CPU.内存使用状态可以发现CPU占用主要分为两部分,一部分为系统内核空间占用CPU百分比,一部分为用户空间占用CPU百分比.其中CPU状态中标示id的为空闲 ...
- java程序运行时内存分配详解 (转)
转自:http://www.tuicool.com/articles/uU77v2 一. 基本概念 每运行一个java程序会产生一个java进程,每个java进程可能包含一个或者多个线程,每一个Ja ...
- windows下揪出java程序占用cpu很高的线程 并找到问题代码 死循环线程代码
我的一个java程序偶尔会出现cpu占用很高的情况 一直不知道什么原因 今天终于抽时间解决了 系统是win2003 jvisualvm 和 jconsole貌似都只能看到总共占用的cpu 看不到每个线 ...
- 如何获知PHP程序占用多少内存(复制)
想要知道编写的 PHP 脚本需要占用多少内存么?很简单,直接使用 PHP 查看当前分配给 PHP 脚本的内存的函数 memory_get_usage() 就可以了 下面是使用示例: 复制代码 代码如下 ...
随机推荐
- Webstorm常用快捷键大全
webstorm应该是目前最强的js编辑器了,结合sublime text可以很效率的开发项目.今天整理了一些webstorm比较实用的快捷键: Ctrl+/ 或 Ctrl+Shift+/ 注释(// ...
- 【LeetCode 67_字符串_算术运算】Add Binary
string addBinary(string a, string b) { int alen = a.size(); int blen = b.size(); ) return b; ) retur ...
- (转)Android学习笔记②——HelloWorld的创建已经基本知识
开发第一应用 可以开发属于自己的应用,是否有点小激动?好吧!让我们开始,首先点击Start a new Android Studio Project创建工程:接下来需要输入应用名称(第一个字母要大写) ...
- Linux系统在启动过程中grub引导文件丢失的解决方法
在/boot/grub2目录下有一个grub.cfg文件:该文件主要是用来自动地引导系统启动内核程序和系统的初始化程序. 问题一:当系统在启动的情况下,我们不小心删除/boot/grub2/grub. ...
- charles抓包unknow
如果能抓到包,可是解析不出请求,那一定是证书问题,注意以下几点: 1.设备安装证书,注意要抓包的每一个设备都要安装证书,每一个设备! 2.pc端也要安装证书 如果以上两点都做到一定可以解析https请 ...
- Linux:时间同步
时间同步 硬件时间的设置 hwclock clock clock和hwclock用法相近,只用一个就行,只不过clock命令除了支持x86硬件体系外,还支持Alpha硬件体系. 查看硬件时间 hwcl ...
- d3.js(v5.7)力导向图(关系图谱)
先上图,后面再一一解释: ok,为了方便理解,这里我就没有用之前封装的automatch函数来将数据和节点匹配了,如果你对enter(),exit()函数还不是很理解的话,请移步至我之前写的<n ...
- ubuntu16 jdk7 install&config
1,下载jdk文件 http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521 ...
- SpringMVC札集(07)——JSON数据
自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onL ...
- Machine Learning|Andrew Ng|Coursera 吴恩达机器学习笔记(完结)
Week 1: Machine Learning: A computer program is said to learn from experience E with respect to some ...