java内存分为 堆 栈 方法区
-
堆区:
- 存储的全部是对象 ,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
- jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
- 栈区:
- 每个线程包含一个栈区 ,栈中 只保存基础数据类型的对象和自定义对象的引用(不是对象) ,对象都存放在堆区中
- 每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问 。
- 栈分为3个部分: 基本类型变量区、执行环境上下文、操作指令区(存放操作指令) 。
- 方法区:
- 又叫 静态区 ,跟堆一样, 被所有的线程共享 。方法区 包含所有的class和static变量 。
- 方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
java引用类型
- 强引用
- 即java中不同的引用,该类型即使内存不足,也不会被释放
String str = "abc"; List<String> list = new Arraylist<String>(); list.add(str);
- 软引用
- 使用SoftReference类间接的引用,在内存不足时,会将其作为可回收对象释放
A a = new A(); SoftReference<A> sr = new SoftReference<A>(a);
- 使用SoftReference类间接的引用,在内存不足时,会将其作为可回收对象释放
- 弱引用
- 使用WeakReference类间接引用,GC触发时便会被回收
Object c = new Car(); //只要c还指向car object, car object就不会被回收 WeakReference<Car> weakCar = new WeakReference(Car)(car);
- 使用WeakReference类间接引用,GC触发时便会被回收
- 虚引用
- 若对象被回收时将会把虚引用加入到于对象关联的引用队列
类加载器
- 若对象被回收时将会把虚引用加入到于对象关联的引用队列
- Bootstrap(启动引导)加载器
- EXt(扩展)加载器
- APP(系统)加载器
- 自定义加载器
类的生命周期
- 加载:获取类的二进制字节流;生成方法区的运行时存储结构;在内存中生成Class对象
- 验证:确保该Class字节流符合虚拟机要求
- 准备:初始化静态变量
- 解析:将常量池的符号引用替换成直接引用
- 初始化:执行静态代码,变量赋值
- 使用
- 卸载
判定是否为垃圾的方法
- 引用计数法
- 可达性分析法:
定义:从 GC ROOT 开始搜索,不可达的对象都是可以被回收的 - GC ROOT:
1.虚拟机栈/本地方法栈中引用的对象
2.方法区中常量/静态变量引用的对象垃圾处理机制
- 标记清除法:
直接对可回收对象删除,这样的做法会产生大量内存碎片 - 标记复制法:
将内存空间划分为两部分,永远保持一部分是空的,先将存活对象复制到一侧,然后将另一侧清空,这样做内存浪费,相当于只有一半内存可用 - 标记压缩法:
将可回收对象清理后,在将存活对象移动。使其空间连续,效率较低。 - 分代回收(jvm使用的):
- 将内存分为青年代,老年代,永久代三个区。
- 对于青年代又可分为to(s1) from(s0) eden
- 将eden区,s0,s1区相结合使用标记复制法,即eden区满了(将存活对象)移动到s0区,s0区满了移动到s1区。
- 经过多代(大约7代)后将仍然存活的s1区对象移动到老年区,老年区使用复制压缩法。老年区满后使用标记复制法移动到永久区。
- 标记清除法: