2,理解JVM

Posted 机械狂魔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2,理解JVM相关的知识,希望对你有一定的参考价值。

 
一、内存管理:
 
1,内存结构:
栈和堆区别,栈是连续内存区,一般是2M单位,堆是不连续的链表。受限于虚拟内存,new时分配
PC寄存器、java栈、堆、方法区、本地方法区、运行常量池
java栈:对应一个线程,每个栈中的栈帧关联每个方法,运行一个方法创建一个栈帧,执行完就弹出栈帧。不是线程共享,不用关心数据一致性和同步锁这些线程问题。
:程序猿最关心的,是new对象和对象数组时创建的,所有线程共享,保证一致性。
方法区:储存类结构信息,比如class文件解析后,常量池,方法数据,方法体,构造函数,实例初始化等储存在这里。
常量区:每个class文件的常量表,是方法区的一部分。即和方法区的常量池是一回事。
本地方法栈,为运行Native方法准备的,类似java栈。
 
 
2,内存分配策略:
静态分配: 程序编译和连接的时候,不允许有可变数据结构如可变数组,也不允许嵌套或递归。 C语言,源文件大小,和编译生成另外一个大小
栈内存分配:程序对数据区编译时是未知的,运行时才知道,但规定进入一个程序模块时,必须知道所需的数据区大小。也是先进后出的栈
堆分配:运行到相应代码时才会知道空间大小。
 
3,java内存分配:
堆和栈
栈一般不关心,是对应到线程的。速度比对快,仅次于寄存器。栈帧的数据大小和生存期必须确定,缺乏灵活性。
堆,程序猿最要关心的,每个java应用对应唯一JVM实例,每个实例唯一对应一个堆。当然由这个应用的所有线程共享。由于垃圾回收GC来释放。
通俗的说,栈来执行程序,一个栈对应一个线程,堆来存放对象。堆要请求操作系统来分配内存,所以分配和销毁都需要时间,所以效率低。优点是灵活可变。
 
二、内存回收
 
1,静态内存回收
自动的,方法结束,对应的栈帧也就撤销。
 
2,动态内存回收
对象是否被使用,何时回收。
不被引用的对象,即不可达。这些对象会被回收
 
内存泄露就是被引用了,可达的。但是无用的,程序不用使用它们。不被GC回收,占内存浪费。
 
三、基于分代GC算法
 
分几组,年轻和年老的,几次回收后还存活,就放到年老组,年老组手机频度不那么高。
对不同的区使用不同收集算法。
1,串行
在client模式下默认,单线程完成,JVM其他应用被暂停。
适合内存有限,回收慢
 
2,并行
在server模式下默认,多线程,其它应用也被暂停。
效率高,堆过大时,暂停时间长
 
3,并发
并发数默认为4
old区暂停时间段,但产生内存碎片,耗CPU

4,G1收集器

G1是目前垃圾收集技术发展的最新成果之一,它与前面的几款GC最大的不同在于:
 
G1可管理整个堆区,包括新生代和老年代。G1在物理上不区分新生代和老年代。G1会把整个堆划分为很多区域(Region),新生代和老年代现在变更了仅仅是逻辑上的概念,它们并不需要在物理上严格区分。G1会对所有Region进行回收效率排序,优先清理回收效率最高的Region
除此之外,G1与CMS也是并发执行的GC,即执行清理时可以与用户线程同时(并发)执行,但是G1可以做到比CMS更短暂的停顿时间
 
 
GC组合实践:Server模式下的HotSpot JVM
为新生代和老年代指定不同的GC
1,老年代用并发
2,-XX:UseG1GC  全部用G1GC
 
-Xms是设置内存初始化的大小
-Xmx是设置最大能够使用内存的大小
 
设置方法:
1,eclipse可以设置VM参数 对在当前开发环境中运行的java程序皆生效
编辑当前使用的JRE,在缺省VM参数中输入:
 
2,tomcat,对tomcat下的应用程序生效
打开Tomcat根目录下的bin文件夹,编辑catalina.bat,在setJAVA_OPTS=%JAVA_OPTS%....这句之后加上:setJAVA_OPTS=%JAVA_OPTS%-Xms1024m-Xmx1024m
 
四、内存泄露
 
就是被引用了,可达的。但是无用的,程序不用使用它们。不被GC回收,占内存浪费。
如何检测JVM内存泄漏
如何检测Java的JVM内存泄漏。目前,我们通常使用一些工具来检查Java程序的JVM内存泄漏问题。市场上已有几种专业检查JavaJVM内存泄漏的工具,它们的基本工作原理大同小异,
都是通过监测Java程序运行时,所有对象的申请、释放等动作,将内存管理的所有信息进行统计、分析、可视化
 
五、写代码时要注意的内存泄露
 
0,单例+对象池是个好习惯,无论数据库连接池、http连接池,还是redis,MQ消息队列。可以说单例+对象池是性能优化的万能灵药,减少了资源占用,提升了效率。
1,避免使用Vector,对象放入一个Vector中,如果我们仅仅释放引用本身,那么Vector仍然引用该对象。也要注意List、MAP
2,小心内部类,如果内部类被引用了。导致整个对象被引用,实际上整个对象可能用不到。
3,注意代码中死循环或递归调用 
由于我是C#转来的,Vector和内部类不在我的食谱中无需考虑。
3,Js也要小心内存泄露。同样小心循环引用,对于后台人员写JS,这不是问题
 
 
 

以上是关于2,理解JVM的主要内容,如果未能解决你的问题,请参考以下文章

深入理解_JVM内存管理典型配置举例09

深入理解_JVM内存管理内存分配和回收策略06

2,理解JVM

深入理解_JVM内存管理JDK监控工具与故障处理工具08

深入理解_JVM内存管理调优案例分析与实战10

每周一书《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》分享!