上篇文章我们介绍了JVM所管理的内存结构也就是运行时数据区(Run-Time Data Areas),现在我们将介绍JVM的内存分配与回收
静态内存分配与动态内存分配

JVM的内存分配主要分为两种:静态内存分配与动态内存分配与之对应的是基本类型内存分配与对象内存分配;
1、静态内存分配
       静态内存分配在编译时已确定好内存空间,程序载入时JVM把一次内存分配给它,此后不会再发生变化。这些内容包括:方法中的局部变量(基本数据类型)、类变量(基本数据类型)、对象的引用;对于方法中的局部变量是存储在Java栈的局部变量表中,方法执行结束栈帧出栈,局部变量也会跟着收回内存空间;而类变量是存储在方法区中的,这里的内存回收时间是不确定的。
2、动态内存分配
      Java里给对象分配内存是动态分配的,编译的时候并不能确定对象的存储空间大小,只是创建对象时才能进行内存空间分配,而内存空间的回收是在对象不再被引用时才能回收。对象是存储在堆中,只有当GC触发时才清理回收那些没有被引用的对象的内存空间;
如下面代码段;
    public class Test {
      byte[] bytes=new byte[1024*1024*5];
      long a=1000;
      public static void main(String[] args){
        long b=2;
        byte[] base=new byte[1024*1024*1];
        Test t=new Test();
      }
    }
    bytes:是数组内存分配在堆中的,但引用存储才方法区中,JVM将使用动态内存分配,编译时无法确定存储空间只有当创建test对象时才为bytes分配存储空间,只有当该对象没有被引用时才能被GC回收;
    a:是类变量,基本数据类型,当Test编译载入时就确定了存储空间,存储在方法区中;
    b:是方法中的基本数据类型局部变量只有执行该方法时才在栈帧的局部变量表中分配存储空间方法执行完成后就释放该栈帧,也回收局部变量表中的存储空间;
    base:局部变量,只有执行到该语句时才在堆中为它分配存储空间,引用存储在栈帧局部变量表中没有被引用时才能被GC回收;
    t:对象与数组一样在堆中分配存储空间,但对象引用存储在栈帧局部变量表中,对象没有被引用时GC才能回收存储空间;

确定是否可被回收
    接下来我们将介绍JVM的内存回收,JVM在进行垃圾回收时首先要做的是确定哪些是垃圾,然后才能回收垃圾所占用的内存空间。上面我们说过,对象要是被回收内存的前提是该对象没被活动的对象引用,那JVM是怎么知道一个对象是否被引用的呢。
一般用于确定对象是否被引用的算法有两种:引用计数算法、根搜索算法;
    引用计数算法(Reference Counting):在对象中添加个引用计数器,当有引用时对象计数器加一,引用消失时,计数器减一,只要引用计数器为0时该对象就是没有被引用的,比少编程语言使用该算法,如:python等。
    根搜索算法(GC Roots Tracing):Java、C#等使用该算法判断对象是否存活,该算法从一系列为“GC Roots”的对象为起点,从这些节点开始搜索,走过的路径为引用链(Reference Chain),当对象到GC Roots无任何引用链时,此对象就是不可用的,此不可用的对象将作为回收的对象。


               1、2、3为活动对象,三个对象到GC Roots均有引用链
               4、5 为死对象,对象到GC Roots不可达

Java中,可用于作为GC Roots的对象有:
         虚拟机栈的栈帧中局部变量表中引用的对象
         本地方法栈中的引用对象
         方法区中常量引用的对象
         方法区的中的类静态属性引用的对象
         类的Class对象的引用

垃圾收集算法
    1、 标记-清除算法(Mark-Sweep),算法分为了标记、清除两个阶段,他根据我们前面所讲的方法判断对象是否可被回收,如可回收则标记起来,待标记完所有对象后统一进行回收;
    2、 复制算法(Copying)复制收集算法把内存分为两块容量相同的空间,每次只使用一快,当一快用完时就将还存活的对象复制到另一块中,然后把原来使用过的内存空间进行回收。
    3、 标记-整理算法(Mark-Compact)该算法与标记清除算法一样首先对要清理的对象进行标记,不同的是,接下来他将存活的对象往一端移动,然后回收该端边界以外的内存空间。
    4、 分代收集算法(Generational Collection),现在不少虚拟机采用该算法,如:HotSpot,该算法把对象按不同的存活周期将内存瓜分为几个区域。如:HotSpot把堆分为新生代与老年代,然后根据各个区域的特点采用比较适合的收集算法。一般新生代对象生命周期比较短,所以采用复制算法;而老年代对象生命周期较长,所以比较适合采用标记-清理、标记-整理算法来回收。

文章首发地址:Solinx

http://www.solinx.co/archives/45

JVM探索之——内存管理(二)的更多相关文章

  1. JVM探索之——内存管理(一)

    本系列的第一篇文章,预计本系列最后面会有两三个案例. Java与C.C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder ...

  2. JVM探索之内存管理(三)

    上节我们介绍了JVM垃圾回收的原则,还有几个垃圾收集算法:标记-清除算法.复制算法.标记整理算法.分代收集算法:现在将要说HotSpt的垃圾收集器,这小节将只是理论. Java虚拟机规范对垃圾收集器的 ...

  3. JVM内存管理(二)

    JVM内存管理          JVM在执行java程序的过程中,会把内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖 ...

  4. jvm大局观之内存管理篇(二):当java中new一个对象,背后发生了什么

    https://zhuanlan.zhihu.com/p/257863129?utm_source=ZHShareTargetIDMore 番茄番茄我是西瓜 那是我日夜思念深深爱着的人啊~ 已关注   ...

  5. JVM介绍&自动内存管理机制

    1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...

  6. OC的内存管理(二)ARC

    指针: 指向内存的地址指针变量 存放地址的变量指针变量值 变量中存放的值(地址值)指针变量指向的内存单元值 内存地址指向的值1):强指针:默认的情况下,所有的指针都是强指针,关键字strong ):弱 ...

  7. Linux内存描述之内存节点node--Linux内存管理(二)

    1 内存节点node 1.1 为什么要用node来描述内存 这点前面是说的很明白了, NUMA结构下, 每个处理器CPU与一个本地内存直接相连, 而不同处理器之前则通过总线进行进一步的连接, 因此相对 ...

  8. PHP内核探索:内存管理开篇

    内存是计算机非常关键的部件之一,是暂时存储程序以及数据的空间,CPU只有有限的寄存器可以用于存储计算数据,而大部分的数据都是存储在内存中的,程序运行都是在内存中进行的.和CPU计算能力一样, 内存也是 ...

  9. Linux内存描述之内存节点node–Linux内存管理(二)

    日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDrivers Linux内存管理 #1 ...

随机推荐

  1. loadrunner录制回放常见问题及解决办法

    1.录制错误    1)录制本机 WebTours 或录制本地网站无法打开    当 使 用 Vista 以 后 的 操 作 系 统 时 , 会 出 现 该 问 题 . 这 是 由 于 在 本 地Wi ...

  2. Java继承中成员方法的overload(重载/过载)

    如果Java基础类有一个方法名被"过载"使用多次,在衍生类里对那个方法名的重新定义就不会隐藏任何基础类的版本.所以无论方法在这一级还是在一个基础类中定义,过载都会生效. publi ...

  3. jquery的insertBefore(),insertAfter(),after(),before()

    insertBefore():a.insertBefore(b) a在前,b在后, a:是一个选择器,b:也是一个选择器 <!DOCTYPE html> <html> < ...

  4. a标签的target属性

    _blank 浏览器总在一个新打开.未命名的窗口中载入目标文档. _self 这个目标的值对所有没有指定目标的 <a> 标签是默认目标,它使得目标文档载入并显示在相同的框架或者窗口中作为源 ...

  5. 来自 Codrops 的7种创新的拖放交互界面

    Codrops 分享了一些界面拖放的交互设计想法.基本的思路是在拖动一个项目的时候,为特定的操作呈现出可投掷的区域.这节省了大量的界面空间 ,并给出了一个有趣的动态的互动.有很多应用场景,例如分类和组 ...

  6. Vue数据绑定隐藏的神坑....

    今天被Vue的一个坑给折磨了一天,终于发现是什么问题,我们先来模拟一个场景: 代码如下: <!DOCTYPE html> <html lang="en"> ...

  7. 解决Android studio 非法字符的问题

    前言:今天遇到一个问题,从一个项目中把一些类拷贝到Android studio 里面,运行的时候,报错. 显示刚才拷贝的类中有非法字符,我又检查了一遍,发现类中没有非法字符. 在网上查到了,相关的解决 ...

  8. Android studio .9图片造成的错误总结

    前言,今天早晨遇到一个很奇葩的问题,导致我花费了很长的时间来解决.从eclipse 项目里复制过来4张.9图片,粘贴到android studio 项目里, 一运行发现报错,开始是 找不到这几张.9图 ...

  9. 你真的了解UIResponder吗?

    1:首先查看一下关于UIResponder的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIResponder : NSObject //响应链中负责传递事件的 ...

  10. 【代码笔记】iOS-截屏功能

    代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. // ...