浅谈JAVA内存管理与垃圾收集

浅谈JAVA内存管理与垃圾收集


当我们谈到JAVA的内存管理,常常只把内存分为堆和栈,这是因为这两个区域是最重要的两个地方,也是程序员们最关注的。事实上JAVA内存的区分要比这复杂得多。


内存管理

在JAVA程序的运行时数据区中,我们按线程共享与线程隔离来分类:

线程共享

  1. 方法区(人们常称它为永久代):存储已经被虚拟机加载的类信息,运行时常量池,静态变量,即时编译器编译后的代码等数据。这个区域的内存回收目标主要是废弃常量和无用的类。
  2. 堆:存储对象实例。Java heap是JAVA虚拟机所管理的内存中最大的一块,也是垃圾收集器管理的主要区域。(Java虚拟机规范中指出,堆仅要求放在逻辑上连续的内存中,不一定是物理上的连续内存。)

线程隔离

  1. 程序计数器:我们知道Java源码经编译后会变成Java虚拟机能看明白的字节码,程序计数器就是当前线程所执行的字节码的行号指示器。每条线程都有各自独立的程序计数器。
  2. 虚拟机栈:(我们常说的栈实际上就是这里的虚拟机栈)每个方法在执行时都会创建一个栈帧,用于存放局部变量表(在编译一个方法期间,局部变量表需要占用多大内存是确定的),操作数,动态链接,方法出口等信息。
  3. 本地方法栈:与虚拟机栈相似,只不过虚拟机栈为Java虚拟机中的字节码(即Java方法)服务,而本地方法栈为Native方法服务。(一个Native方法即一个Java调用非Java代码的接口。)

堆与方法区的垃圾收集

上文说到,Java虚拟机管理的内存分为线程隔离和线程共享的两类,其中线程隔离的程序计数器、虚拟机栈和本地方法栈都随线程(方法)而生,随线程(方法)而死,这里不再赘述。下面主要讨论堆和方法区的垃圾收集。

  • 堆:

    1. 我们知道堆中存放的是对象实例。所以首先第一步就是:如何找到对象?
      通常我们访问对象,都是通过本地方法栈中reference数据来操作具体的。目前主流的对象的访问定位方式有两种:句柄和直接指针。(对象实例数据在堆中,对象类型数据在方法区中)
      句柄:堆中需要专门划分出一块内存作为句柄池,池中存放着到对象类型数据的指针(方法区)和到对象实例数据的指针。reference仅指向堆中的 指向对象实例数据 的句柄,该句柄再指向该对象的实例数据。这样做的好处就是JAVA本地变量表中的reference存储的是稳定的句柄地址
      直接指针:reference中存储的直接就是对象地址。速度快捷,节省了一次指针定位的时间开销

    2. 如何判断对象已死?
      2.1 引用计数算法
      给对象中添加一个引用计数器,每当有一个地方引用它时,计数器+1;当引用失效时,计数器-1。计数器为零时说明说明对象不再被使用。很难解决对象之间相互循环引用的问题

      2.2 可达性分析算法
      通过一系列的称为“GC ROOTS”的对象作为起始点,从这些节点开始往下搜索,走过的路径称为引用链,当一个对象没有与任何引用链相连,证明该对象无用。
      可作为GC ROOTS的对象:
      - 虚拟机栈(栈帧中的本地变量表)中引用的对象
      - 方法区中类静态属性引用的对象
      - 方法区中常量引用的变量
      - 本地方法栈中Native方法引用的变量

  • 方法区
    永久代的垃圾回收主要为:废弃常量、无用的类。

    1. 如何判断常量已废弃?
      没有任何对象引用该常量,其他地方也没有引用该常量,有必要的话,该常量就会被系统清理出常量池。
    2. 如何判断类已无用?
      2.1 该类的所有实例都已经被回收
      也就是说Java堆中不存在该类的任何实例。
      2.2 加载该类的ClassLoader已经被回收
      2.3 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

垃圾收集算法

  1. 标记-清除算法(一般老年代使用):首先标记出所有需要回收的对象,标记完成后统一回收。缺点:标记和清理的效率都不高;标记清除后会产生大量内存碎片
  2. 复制算法(一般新生代使用):将可用内存分成大小相等的两块,每次只使用其中一块。当这一块的内存用完了,就将还存活的对象复制到另一块上,然后再把已经使用过的内存空间一次清理掉。
  3. 标记-整理算法(一般老年代使用):标记出所有需要回收的对象后,让所有存活着的对象向一端移动,然后直接清理掉端边界以外的内存。

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值