内存区块
引用了:http://www.cnblogs.com/dolphin0520/p/3613043.html
0.提示
①java中一个进程就会开启一个虚拟机。
②一个进程中可以包含很多线程。
③执行的最小单位是线程。
④这些设计是java的设计规范,人为规定了大致,并不唯一。
1.程序计数器
①程序计数器,在汇编中是cpu的寄存器,它保存的是程序当前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址)。
②在java虚拟机中并不是物理上的寄存器,但是逻辑功能上等同于程序计数器。
③jvm中每个线程对应一个程序计数器。
2.java栈
①java中的栈也不是物理意义上的栈。Java栈是Java方法执行的内存模型。
②Java栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法,在栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、指向当前方法所属的类的运行时常量池(运行时常量池的概念在方法区部分会谈到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些额外的附加信息。
③这也是为什么递归会溢出的原因。
3.本地方法栈
java对于本地方法栈,没有太多规定。只要实现类似于java栈的功能就好了。
4.堆
①这里存放着对象的实例。
②也是我们最关心的释放的地方。
③jvm中只有一个堆,线程共享。
5.方法区
①被线程共享的区域。
②在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
③用来存储编译期间生成的字面量和符号引用。
怎么判断哪些该回收
自由发散思维
①根据没有引用就证明它没用,引用数=0--->可以被回收。
②但是,a引用b, b引用a,怎么回收?
③想想,忽然想到互联网。
④网页==源码,源码里包含很多其他网页链接。是不是很像引用。
⑤假设世界上有三大堆网页集中区域+100个国防部内部局域网网页集中区域。堆内网页互联,堆与堆互不联系。那么谁才是互联网呢?
⑥3个图,好像只要遍历三个图,就能找到整个互联网了,剩下的100个国防部已经被放弃了,他们的每一个网页,我们都不知道,我们不知道从哪里开始,他们不属于互联网。
⑦搜索引擎--->从他们自己的数据库中查数据。
他们的数据来源---->从好几个重要的节点去遍历图。
什么是互联网---->能够连接到开始的几个重要节点的网页才被承认是互联网上的。
怎么回收---->能被连接到虚拟机中几个重要对象实例的实例就可以不被回收,其他的就要回收。
看看根搜索
从根节点开始,能够到达的不被回收,不能到达的被回收。
那怎么选取根节点? 可以作为根节点的是:
1.虚拟机栈中引用的对象(本地变量表)
2.方法区中静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈中引用的对象(Native对象)
怎么回收
标记-清除
特点:很明显,容易出现碎片化空间,如果要分配大内存,可能找不到适合的区域。
复制
特点:一般只有一半可用,但清理高效,无碎片化空间。
标记-整理
特点:无碎片化空间。内存完整。
虚拟机的做法
①一般分为新生代和老年代和方法区(永久代)
②新生代代谢比较快,一般采用复制的回收办法。
③老年代代谢比较慢,一般采用标记整理的回收方法。
④jvm不同厂商一般不同,所以采用什么做法并不确定。
⑤至于内部更细致的方法,就由有兴趣,有时间的专家去探究吧。
永久代的回收有两种:常量池中的常量,无用的类信息,常量的回收很简单,没有引用了就可以被回收。对于无用的类进行回收,必须保证3点:
类的所有实例都已经被回收
加载类的ClassLoader已经被回收
类对象的Class对象没有被引用(即没有通过反射引用该类的地方)