Java内存分析 --- 虚拟机运行时数据区

Java内存分析:虚拟机运行时数据区算法

1)程序计数器(Program Counter Register):能够看作当前线程所执行的字节码的行号指示器
	工做:经过改变这个计数器的值来选取下一条须要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。
	说明:程序计数器是线程私有的。每条线程都须要有一个独立的程序计数器,各条线程间的计数器互不影响,独立储存。
	举例:若是线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令地址;若是正在执行的是native方法,这个计数器值则为空。

2)Java虚拟机栈:描述的是Java方法执行的内存模型。
	工做:每一个方法在执行的同时都会建立一个栈帧(Stack Frame)用于储存局部变量表、操做数栈、动态连接、方法出口等信息,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈道出栈的过程。
	说明:	1)Java虚拟机栈是线程私有的,它的生命周期与线程相同。
			2)通常人们所说的“栈”就是指虚拟机栈,或者指虚拟机栈中局部变量表部分
				局部变量表存放了编译期可知的各类基本数据类型(boolean、byte、char、int..)、对象引用等

	异常:虚拟机栈中规定了两种异常情况:
		1)若是线程请求的栈深度大于虚拟机所容许的深度,将抛出StackOverflowError异常;
		2)若是虚拟机栈能够动态扩展(当前大部分的Java虚拟机均可以动态扩展),若是扩展时没法申请到足够的内存,就会抛出OutOfMemoryError异常

3)本地方法栈(Native Method Stack):为虚拟机使用到的Native方法服务。
	说明:与虚拟机栈的区别:虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。
		Sun HotSpot虚拟机直接就把本地方法栈和虚拟机栈合二为一。


	异常:与虚拟机栈中规定的异常相同。
	
4)Java堆:是被全部线程共享的一块内存区域,在虚拟机启动时建立。惟一的目的就是存放对象实例
	
	如今收集器基本都采用分代收集算法
	
	Java堆分为新生代、老年代
		新生代(Young generation)
			结构:Eden空间、From Survivor空间、To Survivor空间
			特色:新生代中大部分的对象是“朝生夕死”的,每次垃圾收集时都发现有大批对象死去,只有少许存活
		老年代(Tenured generation)
			特色:老年代中的对象存活率高、没有额外空间对它进行分配担保。
	
	注:新生代GC(Minor GC)、老年代GC(Full GC、Major GC)
	
5)方法区(永久代:Permanent Generation):用于储存已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
	说明:	1)与Java堆同样,方法区是各个线程共享的内存区域。
			2)Java虚拟机规范把方法区描述为堆的一个逻辑部分,可是它却有一个别名叫作 Non-Heap(非堆)

	运行时常量池:是方法区的一部分
	
	方法区的回收:
		主要回收:废弃的常量、无用的类
		
		废弃常量:没有任何引用关联着的常量即废弃常量。
		无用的类:同时知足如下3个条件的类
			1)该类全部的实例都已经被回收,也就是说Java堆中不存在该类的任何引用。
			2)加载该类的ClassLoader已经被回收
			3)该类对应的Class对象没有再任何地方被引用,没法在任何地方经过反射访问该类的方法。
		注:知足条件的类是否会被回收,由虚拟机设定:由 -Xnoclassgc 参数进行控制。
		
		重要:在大量使用反射、动态代理(jdk动态代理、cglib动态代理等)、动态生成jsp 的场景中都须要虚拟机具有类卸载功能,以保证方法区不会溢出。
相关文章
相关标签/搜索