浅谈JVM原理及性能调优分享
Posted 艾编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈JVM原理及性能调优分享相关的知识,希望对你有一定的参考价值。
JVM,熟悉JVM架构与GC垃圾回收机制以及相应的堆参调优,有过在linux进⾏系统调优的经验。本次课程的主题内容:
1、JVM组成结构
2、JVM体系结构概览
3、栈(Stak)
4、堆(Heap)
5、JVM垃圾收集(Java Garbage Collection)(下次教程分享)
6、GC三⼤算法(下次教程分享)
7、GC⾯试题(下次教程分享)
如上图以上操作
⼀、JVM组成结构谈谈
JVM是运⾏在操作系统之上的,他与硬件没有直接的交互。
⼆、JVM体系结构概览
1. Class Loader类加载器
负责加载class⽂件,class⽂件在⽂件开头有特定的⽂件标示,并且ClassLoader只负责class⽂件的加载
2. Execution Engine执⾏引擎 负责解释命令,提交操作系统执⾏
3. Native Interface 本地接⼝
Java语⾔本身不能对操作系统底层进⾏访问和操作,但是可以通过JNI接⼝调⽤其他语⾔来实现对底层的访问。
4. Native Method Stack 本地⽅法栈
java在内存中专⻔开辟了⼀块区域处理标记为native的代码,他的具体做法是Native Method
Stack中登记native⽅法,在Execution Engine执⾏时加载native libraies。
5. Runtime Data Area 运⾏数据区
6. Method Area⽅法区
⽅法区是被所有线程共享,所有字段和⽅法字节码、以及⼀些特殊⽅法如构造函数,接⼝代码也在此定义。简单说,所有定义的⽅法的信息都保存在该区域,==此区属于共享区间==。⽤来保存装载的类的元结构信息。
==静态变量+常量+类信息+运⾏时常量池存放在⽅法区==
==实例变量存在堆内存中==
7. PC Register 程序计数器
每个线程都有⼀个程序计数器,就是⼀个指针,指向⽅法区中的⽅法字节码(下⼀个将要执⾏的指令代码),由执⾏引擎读取下⼀条指令,是⼀个⾮常⼩的内存空间,可以忽略不记
==栈管运⾏,堆管存储==
8. Java Stack 栈
栈也叫栈内存,主管Java程序的运⾏,是在线程创建时创建,它的⽣命期是跟随线程的⽣命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程⼀结束该栈就Over,⽣命周期和线程⼀致,是线程私有的。基本类型的变量、实例⽅法、引⽤类型变量都是在函数的栈内存中分配
栈管运⾏,堆管存储
三、栈(Stak)
栈也叫栈内存,主管Java程序的运⾏,是在线程创建时创建,它的⽣命期是跟随线程的⽣命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程⼀结束该栈就Over,⽣命周期和线程⼀致,是线程私有的。基本类型的变量、实例⽅法、引⽤类型变量都是在函数的栈内存中分配。
1 、栈存储什么
先进后出,后进先出即为栈
栈帧中主要保存3类数据
本地变量(Local Variables):输⼊参数和输出参数以及⽅法内的变量;
栈操作(Operand Stack):记录出栈、⼊栈的操作;
栈帧数据(Frame Data):包括类⽂件、⽅法等。
2 、栈运⾏原理
栈中的数据都是以栈帧(Stack Frame)的格式存在,栈帧是⼀个内存去块,是
⼀个数据集,是⼀个有关⽅法(Method)和运⾏期数据的数据集,当⼀个⽅法A被调⽤时就产⽣⼀个栈帧F1,并被压⼊到栈中,
A⽅法调⽤了B⽅法,于是产⽣栈帧F2也被压⼊到栈,B⽅法调⽤了C⽅法,于是产⽣栈帧F3也被压⼊到栈。。。
执⾏完毕后,先弹出F3,再弹出F2,再弹出F1.。。。
遵循“先进后出/后进先出”的原则。
图示在⼀个栈中有两个栈:
栈2是最先被调⽤的⽅法,先⼊栈,
然后⽅法2调⽤了⽅法1,栈帧1处于栈顶的位置,
栈帧2处于栈底,执⾏完毕后,依次弹出栈帧1和栈帧2,线程结束,栈释放。
每执⾏⼀个⽅法都会产⽣⼀个栈帧,保存到栈(后进先出)的顶部,顶部栈就是当前的⽅法,该⽅法执⾏完毕后会⾃动将此栈帧出栈。
3、判断JVM优化是哪⾥
主要时优化堆
4、 三种JVM
1、Sun公司的HotSpot
2、 BEA公司的JRockit
3.、IBM公司的 J9 VM
四、堆(Heap)
1 、堆内存示意图
2、新⽣区
新⽣区是类的诞⽣、成⻓、消亡的区域,⼀个类再这⾥产⽣,应⽤,最后被垃圾回收器收集,结束⽣命。新⽣去⼜分欸两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是再伊甸区被new出来。幸存区⼜连个:0区和1区。当伊甸园的空间⽤完是,程序有需要创建对象,JVM的垃圾回收器将对伊甸园区进⾏垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引⽤的对象进⾏销毁。
然后将伊甸园区中的⽣于对象移动到幸存0区,若幸存0区也满了,再对该区进⾏垃圾回收,然后移动到1区。如果1区也满了,再移动到养⽼区。若养⽼区也满了,那么这时候将产⽣MajorGC(FullGC),进⾏养⽼区的内存清理。若养⽼区执⾏了FullGC后发现依然⽆法进⾏对象保存,就会产⽣OOM异常(OutOfMemoryError)。
如果出现 java.lang.OutOfMemoryError:Java heap space 异常,说明java虚拟机的堆内存不够。原因有⼆:
1. Java虚拟机的对内存设置不够,可以通过参数-Xms、-Xmx来调整默认最⼤内存是机器的四分之⼀⼤⼩
2. 代码中创建了⼤量⼤对象,并且⻓时间不能被垃圾收集器收集(存在被引⽤)
==JDK1.8之后,永久代取消了,由元空间取代==
3 、养⽼区
养⽼区⽤于保存从新⽣区筛选出来的JAVA对象,⼀般池对象都在这个区域活跃。
4、永久区
永久存储区是⼀个常驻内存区域,⽤于存放JDK滋⽣所携带的Class,Interface的元数据,也就是说它存储的是运⾏环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM才会释放此区域所占⽤的内存。
如果出现 java.lang.OutOfMemoryError:PermGen space ,说明是Java虚拟机对永久带Perm内存设置不够,⼀般出现这种情况,都是程序启动需要加载⼤量的第三⽅jar包。例如在⼀个Tomcat下部署了太多的应⽤。或者⼤量动态反射⽣成的类不断被加载,最终导致Perm区被沾满。
Jdk1.6之前:有永久代,常量值1.6在⽅法区
Jdk1.7:有永久代,但已经逐步“去永久代”,常量池1.7在堆
Jdk1.8之后:⽆永久代,常量池1.8在元空间
5、⼩总结
逻辑上堆由新⽣代、养⽼代、元空间构成、实际上堆只有新⽣和养⽼代;⽅法区就是永久代,永久代是⽅法区的实现
⽅法区(Method Area)和堆⼀样,是各个线程共享的内存区域,它⽤于存储虚拟机加载的类信息、普通常量、静态常量、编译器编译后的代码等,虽然JVM规范将⽅法区描述为堆的⼀个逻辑部分,但他却还有⼀个别名叫做Non-Heap(⾮堆),⽬的就是要和堆分开。对于HotSpot虚拟机,很多开发者习惯将⽅法区成为
“永久代”,但严格本质上说两者不同,或者说使⽤永久代来实现⽅法区⽽已,永久代是⽅法区(相当于⼀个接⼝Interface)的⼀个实现,JDK1.7的版本中,已经将原本放在永久代的字符串常量池移⾛。
常量池(Constant Pool)是⽅法区的⼀部分,Class⽂件除了有类的版本、字段、⽅法、接⼝等描述信息外,还有⼀项信息就是常量池,这部分内容将在类加载后进⼊⽅法区的运⾏时常量池中存放
相关推荐
1、
2、
3、
4、
5、
回复关键词
Redis 分布式限流 消息队列 alibaba JVM性能调优
看更多精彩教程
喜欢本文,记得点击个在看,或者分享给朋友哦!
以上是关于浅谈JVM原理及性能调优分享的主要内容,如果未能解决你的问题,请参考以下文章