JAVA项目之JVM设置
1.JVM结构
JVM是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间.
操作系统装入JVM是通过jdk中来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例 4.调用JNIEnv 实例装载并处理class类。
JVM 全称是Java Virtual Machine,Java虚拟机。JVM构成图: Array
整个 JVM分为四部分:
Class Loader 类加载器 只要符合文件结构就加载,至于说能不能运行,则不是它负责的。
Execution Engine 执行引擎 ,执行引擎也叫做解释器(Interpreter),负责解释命令,提交操作系统执行。
Native Interface 本地接口 作用是融合不同的编程语言为 Java 所用,它的初衷是融合 C/C++程序,它的
具体做法是 Native Method Stack中登记 native方法,在Execution Engine 执行时加载native libraies。目前很少使用。
Runtime data area 运行数据区是整个 JVM 的重点。我们所有写的程序都被加载到这里,之后才开始
运行 。
2.Stack(栈)
Stack 栈 ,栈也叫栈内存,是 Java程序的运行区,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就 Over。
栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是一个内存区块,是一个数据集,是
一个有关方法(Method)和运行期数据的数据集,当一个方法A被调用时就产生了一个栈帧 F1,并
被压入到栈中,A方法又调用了 B方法,于是产生栈帧 F2 也被压入栈,执行完毕后,先弹出 F2
栈帧,再弹出 F1 栈帧,遵循“先进后出”原则。
Stack(栈)是JVM的内存指令区。 所以Java 基本数据类型,Java 指令代码,常量都保存在Stack中。
栈帧中主要保存3 类数据:本地变量(Local Variables),包括输入参数和输出参数以及方
法内的变量;栈操作(Operand Stack),记录出栈、入栈的操作;栈帧数据(Frame Data),包括类文件、方法等等。
3.Heap(堆)
一个 JVM 实例只存在一个堆类存(Heap),所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。Heap 的管理很复杂,每次分配不定长的内存空间,专门用来保存对象的实例。实际上也只是保存对象实例的属性值,属性的类型和对象本身的类型标记等,并不保存对象的方法(方法是指令,保存在Stack中),而对象实例在Heap 中分配好以后,需要在Stack中保存一个4字节的Heap 内存地址,用来定位该对象实例在Heap 中的位置,便于到该对象实例。
JVM中另有一个GC进程,定期扫描Heap ,它根据Stack中保存的4字节对象地址扫描Heap ,定位
Heap 中这些对象,进行一些优化(例如合并空闲内存块什么的),并且假设Heap 中没有扫描到的区域都是空闲的,统统refresh(实际上是把Stack 中丢失了对象地址的无用对象清除了),这就是垃圾收集的过程 。堆结构图:
堆内存分为三部分: Young Generation Space 新生区(年轻代) 新生区是类的诞生、成长、消亡的区
域,一个类在这里产生,应用,最后被垃圾回收器收集, 结束生命。新生区又分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) 所有的类都是在伊甸区被new 出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0 区。若幸存 0区也满了,再对该区进行垃圾回收,然后移动到 1 区。那如果1 区也满了呢?再移动 到养老区。 Tenure generation space 养老区 (年轻代) 养老区用于保存从新生区筛选出来的 JAVA 对象,一般池对象都在这个区域活跃。 P ermanent Space 永久存储区是一个常驻内存区域, 指明虚拟机为j ava 永久生成对象(P ermanate generation)如,class 对象、方法对象这些可反射(reflective)对象分配内存限制。被装载进此区域的数据是
不会被垃
圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。
4.JVM内存产生的方式及常见问题
1.JVM 向操作系统申请空闲内存向操作系统申请空闲内存。JVM对操作系统说“给我64M空闲内存”,于是操作系统就查自己的内存分配表,了段64M的内存写上“Java占用”标签,然后把内存段的起始地址和终止地址给JVM。
2.JVM获得到 64M内存,首先给 heap分个内存,并且是按照 heap的三种不同类型分好的,然后给栈内存也分配好。
3.常见问题:
(a)为什么会产生 StackOverflowError
答:因为一个线程把 Stack 内存全部耗尽了,一般是递归函数造成的。
(b)为什么会产生 OutOfMemor y
答: Heap 内存中没有足够的可用内存了。这句话要好好理解,不是说 Heap没有内存
了,是说新申请内存的对象大于 Heap空闲内存,比如现在 Heap还空闲 1M,但是新申请的内存需
要 1.1M,于是就会报 OutOfMemor y了,可能以后的对象申请的内存都只要0.9M,于是就只出现
一次OutOfMemor y,GC也正常了,看起来像偶发事件,就是这么回事。 但如果此时 GC没有回
eclipse导入整个项目收就会产生挂起情况,系统不响应了。
(c)产生的对象不多为什么还会产生 OutOfMemor y
答:你继承层次忒多了,Heap中 产生的对象是先产生 父类,然后才产生子类.
(d)OutOfMemor y错误分几种
答:分两种,分别是“OutOfMemor y Error:j ava heap si z e”和”OutOfMemor y Error:P ermGen space”,两种都是内存溢出
j ava heap si z e是说申请不到新的内存了,这个很常见,检查应用或调整堆内存大小。
P ermGen space是因为永久存储区满了,这个也很常见,一般在热发布的环境中出现,是因为每次发布应用系统都不重启,久而久之永久存储区中的死对象太多导致新对象无法申请内存, 一般重新启动一下即
可。
5.JVM内存设置
1. Stack Space:
当递归调用太深的时候,就有可能耗尽Stack Space,爆出StackOverflow的错误。Stack Space的大小随着OS,JVM以及环境变量的大小而发生变化。一般说来默认的大小是512K。在64位的系统中,这个Stack Space值会更大。一般说来,Stack Space为128K是够用的。 可以使用-X ss来调整Stack Space的大小为128K。-X ss512K
整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.
2.PermSize持久代 :
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
-XX:PermSize=64M
-XX:MaxPermSize=256M
3.Heap(年轻代+ 年老代) :
JVM初始分配的Heap 内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx相等以避免在每次G C 后调整堆的大小。
PS:不同厂家的jdk垃圾回收算法不一样。在sun的jdk下,Xms和Xmx设置一样,可以减轻伸缩堆大小带来的压力,但在ibm的jdk下面,设置为一样会增大堆碎片产生的几率。
-X ms512M -X m x512M
4.-Xmn (年轻代; eden+ 2 survivor space )
增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。 -Xmn256M
年轻代择响应时间优先的应用:尽可能设大,直到接近系统的最低响应时间限制(根据实际情况选择).在此种情况下,年轻代收集发生的频率也是最小的.同时,减少到达年老代的对象.
年老代大小选择响应时间优先的应用:年老代使用并发收集器,所以其大小需要小心设置,一般要考虑并发会话率和会话持续时间等一些参数.如果堆设置小了,可以会造成内存碎片,高回收频率以及应用暂停而使用传统的标记清除方式;如果堆大了,则需要较长的收集时间.最优化的方案,一般需要参考以下数据获得:
-Xss32m -Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m
6.设置 Eclipse
Eclipse导入了一个比较大的项目,出现了an internal error occurred during building workspace 错误。 内存溢出问题。可以通过修改eclipse.ini文件解决,
优化之后的ini文件内容:
-startup
lipse.e q uino x.launcher_1.3.0.v20130327-1440.j ar
--launcher.librar y
lipse.e q uino x.launcher.win32.win32.x86_64_1.1.200.v20140116-2212
-product
--launcher.defaultAction
openFile
--launcher.XX Ma xP ermSi z e
256M
-showsplash
--launcher.XX Ma xP ermSi z e
256M
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
- q uiredJavaVersion=1.6
-X ms256m
-X m x256m
简介:
JVM是java运行的环境,也是java的基础。JVM参数的优化调整将直接涉及最终的性能。同时JVM
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论