JVM是根据运行时数据的存储结构来划分内存结构的,运行时数据包括java程序本身的数据信息和jvm运行java程序需要的额外数据信息。

JVM运行时数据区


程序计数器

每条线程有一个独立的程序计数器,用于保存当前正常执行的程序的内存地址


动态内存分配。

所有线程共享,在虚拟机启动时创建,可以处于物理上不连续的存储空间。

此区域的唯一目的就是存放对象实例


方法区

线程共享。

当JVM使用类装载器装载某个类时,首先获取class文件,提取该文件的内容信息,将这些信息存储到方法区,最后返回一个class实例。方法区用于存储已经被虚拟机加载的类信息(class)(版本,字段,方法,接口等描述信息),常量,静态变量(static),即时编译期编译后的代码数据等。称为“永久代”。GC在这区域较少出现,内存回收的主要目标是针对常量池的回收和对类的卸载(某个类不再使用)。

运行时常量池

是方法区的一部分,class文件中除了有类的版本,字段,方法,接口等描述信息以外,还有一项信息是常量池。常量池:用于存放编译期生成的各种字面量(final修饰的常量,字符串)和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。运行时常量池对于class文件常量池具备动态性,在程序运行期间也可以将新常量放入池中。


静态内存分配。

线程私有,它的生命周期与线程相同。

每当创建一个线程时,JVM为这个线程创建一个对应的栈;

每运行一个方法就在栈中创建一个栈帧,每个栈帧会含有局部变量表,操作数栈,动态链接,方法出口等信息。(局部变量表,存放了编译期可知的各种基本数据类型,对象引用类型。局部变量表所需的内存空间在编译期间完成分配,方法运行期间不会改变局部变量表的大小)

栈帧分配多少内存基本在编译时期就已知的

每一个方法从调用直至执行完成的过程,就对应着一个栈帧在栈中入栈到出栈的过程。

本地方法栈

与栈作用类似,本地方法栈为虚拟机运行native方法服务(很多native方法由c语言实现)


        《JVM》(二)内存结构与垃圾回收_内存结构


垃圾收集器和内存分配策略

程序计数器,栈都是跟随线程而生而灭,所以线程结束内存直接被回收,不用过多考虑。主要是java堆和方法区


堆对象:

1.引用计数法

2.可达性分析法

引用的分类

1.强引用strong reference。 new Object() 只要强引用还在,GC永远不会回收

2.软引用soft reference。在内存不够时被回收

3.弱引用weak reference。对象只能生存到下一次GC之前

4.虚引用phantom reference。


方法区回收的两部分内容:

                1. 废旧的常量

                2. 无用的类

        无用的类;

                     1.该类所有实例都被回收

                     2.加载该类的classLoader已被回收

                     3.该类对应的class对象没有在任何地方被引用(无法通过反射访问该类的方法)

垃圾回收算法

        Full GC:老年代GC(速度慢)

Minor GC:新生代GC(很频繁,速度很快)


1.标记-清除算法(产生大量内存碎片)—— 老年代

2.复制算法(可用内存缩小)—— 新生代

3.标记-整理算法(标记清除之后进行整理)—— 老年代

4.分代收集算法

复制算法

HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)默认比例为8:1。

一般情况下,新创建的对象都会被分配到Eden区(一些大对象特殊处理),这些对象经过第一次Minor GC后,如果仍然存活,将会被移到Survivor区。对象在Survivor区中每熬过一次Minor GC,年龄就会增加1岁,当它的年龄增加到一定程度时,就会被移动到年老代中。

在GC开始的时候,对象只会存在于Eden区和名为“From”的Survivor区,Survivor区“To”是空的。

Eden区中所有存活的对象都会被复制到“To”;

“From”区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值的对象被移动到老年代,没有达到阈值的对象会被复制到“To”区域。

经过这次GC,Eden区和From区已经被清空。“From”和“To”会交换他们的角色

    《JVM》(二)内存结构与垃圾回收_java_02

内存分配策略

1.对象优先在新生代Eden中分配,当新生代没有内存时,将发起一次minor gc

2.大对象直接进入老年代,大对象指,需要大量连续内存空间的java对象

3.长期存活的对象将进入老年代,survivor中的对象每熬过一次minor gc,age就增加一岁(默认15岁进入老年代)

4.分配担保:无法保证每次回收存活的对象都在”To”区中,即小于10%,把Survivor无法容纳的对象直接进入老年代区。