1.先了解几个概念:
-
①.java数据类型氛围基础数据类型(:boolean、byte)和引用数据类型(类、接口、数组)
-
②.堆、方法区 、栈
堆区:
提供所有类实例和数组对象存储区域
jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
方法区:
又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
运行时常量池都分配在 Java 虚拟机的方法区之中 例子
这个例子中
public void test(){
A a = new A();
int b = 1;
}
public class A{
}
a是A对象的引用所以放在栈中,A是自定义对象所以放在堆中.
b是基础数据类型所以在栈中.
小结
这里用一个在别处看到的栗子总结再好不过
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就
走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自
由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由
度大。
2.jvm heap区域是分代的,分为年轻代,老年代和持久代
年轻代:所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。
年老代:在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,
可以认为年老代中存放的都是一些生命周期较长的对象。
持久代:用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,
但是有些应用可能动态生成或者调用一些class,例如Hibernate 等
3.Full Gc
gc的主要作用是回收堆中的对象。
Full GC 是清理整个堆空间—包括年轻代和永久代。
4.垃圾回收算法
猿们都知道JVM的内存结构包括五大区域:程序计数器、虚拟机栈、本地方法栈、堆区、方法区。
其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生、随线程而灭,因此这几个区域的内
存分配和回收都具备确定性,就不需要过多考虑回收的问题,因为方法结束或者线程结束时,
内存自然就跟随着回收了。而Java堆区和方法区则不一样、不一样!(怎么不一样说的朗朗上口),
这部分内存的分配和回收是动态的,正是垃圾收集器所需关注的部分。
引用计数算法:
优点:实现简单,效率较高,在大部分情况下是一个不错的算法。
缺点:引用计数法很难解决对象之间相互循环引用的问题,主流Java虚拟机没有选用引用计数法来管理内存。
标记-清除
优点:标记-清除算法不需要进行对象的移动,只需对不存活的对象进行处理
缺点:产生内存不连续使用,碎片问题
复制算法
优点:解决内存不连续,碎片问题
缺点:内存使用增加一倍,资源浪费
标记-整理(Mark-Compat)算法
优点:标记-整理算法是在标记-清除算法的基础上,又进行了对象的移动,使得内存对象连续使用
缺点:移动内存对象消耗资源,对象整理代价较高
分代收集(Generational Collection)算法(年轻态,老年态)