浅谈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是运⾏在操作系统之上的,他与硬件没有直接的交互。


⼆、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.。。。

遵循先进后出/后进先出的原则。


浅谈JVM原理及性能调优分享


图示在⼀个栈中有两个栈:

2是最先被调⽤的⽅法,先⼊栈,

然后⽅法2调⽤了⽅法1,栈帧1处于栈顶的位置,

栈帧2处于栈底,执⾏完毕后,依次弹出栈帧1和栈帧2,线程结束,栈释放。

每执⾏⼀个⽅法都会产⽣⼀个栈帧,保存到栈(后进先出)的顶部,顶部栈就是当前的⽅法,该⽅法执⾏完毕后会⾃动将此栈帧出栈。


3、判断JVM优化是哪⾥


主要时优化堆


4、 三种JVM

1、Sun公司的HotSpot

2、 BEA公司的JRockit

3.、IBM公司的 J9 VM


四、堆(Heap




1 、堆内存示意图

浅谈JVM原理及性能调优分享

2、新⽣区

新⽣区是类的诞⽣、成⻓、消亡的区域,⼀个类再这⾥产⽣,应⽤,最后被垃圾回收器收集,结束⽣命。新⽣去⼜分欸两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是再伊甸区被new出来。幸存区⼜连个:0区和1区。当伊甸园的空间⽤完是,程序有需要创建对象,JVM的垃圾回收器将对伊甸园区进⾏垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引⽤的对象进⾏销毁。

然后将伊甸园区中的⽣于对象移动到幸存0区,若幸存0区也满了,再对该区进⾏垃圾回收,然后移动到1区。如果1区也满了,再移动到养⽼区。若养⽼区也满了,那么这时候将产⽣MajorGCFullGC),进⾏养⽼区的内存清理。若养⽼区执⾏了FullGC后发现依然⽆法进⾏对象保存,就会产⽣OOM异常(OutOfMemoryError)。


如果出现 java.lang.OutOfMemoryError:Java heap space 异常,说明java虚拟机的堆内存不够。原因有⼆:


1. Java虚拟机的对内存设置不够,可以通过参数-Xms-Xmx来调整默认最⼤内存是机器的四分之⼀⼤⼩

2. 代码中创建了⼤量⼤对象,并且⻓时间不能被垃圾收集器收集(存在被引⽤)


==JDK1.8之后,永久代取消了,由元空间取代== 


3 、养⽼区

养⽼区⽤于保存从新⽣区筛选出来的JAVA对象,⼀般池对象都在这个区域活跃。


4、永久区

永久存储区是⼀个常驻内存区域,⽤于存放JDK滋⽣所携带的ClassInterface的元数据,也就是说它存储的是运⾏环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭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原理及性能调优分享的主要内容,如果未能解决你的问题,请参考以下文章

jvm原理及性能调优系列(调优工具)

jvm性能调优都做了啥

jvm原理及性能调优系列(自动内存管理机制)

浅谈数据库JVM缓存SQL等性能调优方法和原则

浅谈数据库JVM缓存SQL等性能调优方法和原则

资源分享 | 深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理)