您的位置:首页 > 编程语言 > Java开发

java 虚拟机系列-java内存分配、类加载,垃圾回收机制算法

2017-08-19 21:13 405 查看

请参看:

https://zhuanlan.zhihu.com/p/25511795?comefrom=http://blogread.cn/news/   总结的很好

https://zhuanlan.zhihu.com/p/25575446

http://www.cnblogs.com/wabi87547568/p/5282892.html

一、前言

最近看了《深入理解java虚拟机》中内存分配和类加载两个章节的内容,其实之前也看过这两节,但是觉得每次看都会有收获,这次看觉得对java虚拟机的运行时数据区了解的更深入了一些,对类加载的过程所做的事情和涉及到的数据区也更清楚了。

jvm体系总体分四大块:

类的加载机制

jvm内存结构

GC算法 垃圾回收

GC分析 命令调优

二、总结

1、java运行时数据区:jvm内存结构

分为五大块:程序计数器;虚拟机栈;本地方法栈;java堆;方法区。

(1)程序计数器:线程私有,是java字节码行号指示器;

作用:用来选取下一条要执行的字节码的指令,像循环,跳转、分支、异常处理、线程恢复(多线程间的切换竞争处理器)等,都需要读取程序计数器中数据。

(2)虚拟机栈:线程私有,也称局部变量表,为虚拟机执行java方法(字节码)服务;

作用:虚拟机在虚拟机栈中为每个方法创建一个栈桢,存放局部变量表,操作数栈,动态链接,方法出口等信息,每个方法的调用都会对应一个栈帧出栈和入栈的过程。 

(局部变量表:存放编译器可知的java基本类型、对象引用类型(可以指向一个对象也可指向一个句柄)、和returnAddress类型(指向一条java字节码指令)一个局部变 量空间是32位,long和double要占用2个)

(3)本地方法栈:用来存放本地方法(native)的数据,为虚拟机执行本地方法服务。HotSpot将虚拟机栈和本地方法栈合二为一。

(4)java 堆:线程共享,在虚拟机启动时创建,可通过设置 -Xmn  和 -Xms 设置最大,最小堆内存

作用:存放所有对象和数组。若空间不足,会抛出 outofmemery 和stackoverflow异常。

从内存回收的角度来看:现在GC收集器都采用分代手机算法,所以java堆还需分为年轻代和老年代。Eden空间,From Survivor空间,To Survivor空间;

(5)方法区:线程共享,被称为”永久代“,但hotSpot的GC分代回收机制扩展至方法区;主要收集常量池和对类型卸载(效果不好)。

作用:用于存放虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等。内存不足时会抛出outofmemery异常。

(6)运行时常量池:是方法区的一部分,class文件中除了存放类的版本,字段,方法等信息外,还有一个常量池,存放编译期生成的字面量和符号引用。

作用:存放编译期生成的字面量和符号引用。(在类加载的加载阶段,虚拟机将二进制字节流加载进运行时数据区的方法区)

注意:直接内存,并不是java运行时数据区的一部分,但是也是频繁使用的,基于通道和缓冲区的IO方式。NIO; 内存不够会报 outofmemery异常。

  使用实例:下面通过 一个对象的创建过程 来看看虚拟机是怎样利用这些运行时数据区的:

当虚拟机遇到一个new指令时,首先到常量池中检查该符号引用(若找不到说明这个类没有加载到内存),并检查这个符号引用代表的类是否已经被加载,解析和初始化(若没有,则先进行类加载),然后在java堆中分配该对象所需的内存空间(对象的大小在类加载阶段确定的),然后对对象进行初始化工作。

对象内存分配方法:

指针碰撞法:   适合规整的内存;中间有个指针,使用的内存放指针的一边,未使用过的放另一边。

空闲列表法:适合不规整的内存,相互交错;维护一个列表,记录哪块内存可用。

内存是否规整取决于:垃圾回收算法

2、类加载的过程(类的加载机制)

类加载的过程分为 加载 ;验证;准备;解析;初始化;

(1)加载阶段:虚拟机通过累的全限定名找到对应的二进制流文件;  --- 》  将二进制流文件加载到运行时数据区的方法区;----》在堆中生成一个java.lang.class对象,作为堆中对象访问方法区的入口。

(2)连接阶段:包括验证、准备、解析(位置不固定)

验证:验证文件格式(是否符合定义规范,版本信息是否正确等);元数据验证(对类的数据类型进行语义分析); 字节码校验(对类的方法进行语义分析,是否安全);

准备:为类变量分配内存,并设置初始值。初始化常量池中的静态变量为默认值(常量在 javac 编译时,已经生成了constValue值了,所以在准备阶段是将constantValue值赋给常量;

解析:将常量池内的符号引用转换成直接引用,直接关联内存;

(3)初始化(对类中的类变量和静态语句块赋值)

在网上关于java内存分配模型的讲解真的是数不胜数,其中的源头应该都是《深入理解java虚拟机》这本书吧。我吧这些总结起来,就是想做个记录,以后在面试前好好看看,能快速想起来。  

参考:《深入理解java虚拟机》

结合:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: