上篇文章我们介绍了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. Oracle数据库,序列、索引、视图

    一.序列:生成自动增长(或减少)的整数值 Sequences中新建 调取: th_test.nextval 获取下一个值 th_test. currval获取当前值 二.视图:在物理表的基础上定义的虚 ...

  2. sql传入组合字符串批量操作

    批量操作时我们可以传入一个有规律的ID或则是其他唯一值字段的组合字符串,然后:select/update/inset......where  字段 in(传入的组合字符串),而且很多时候我们还涉及到其 ...

  3. C#实现WebService服务 项目完整总结

    先说一下这个项目做了什么.先介绍一下背景(备注一下,每次项目发生更改之后,要进行clean 和rebuild两个操作,否则最新的更改保存不到exe文件中,这样上线后的系统还是执行得原有的已编译过的程序 ...

  4. 通俗易懂地讲解TCP建立连接的三次握手和释放连接的四次挥手

    TCP建立连接时,为什么要进行三次挥手? 每一次TCP连接都需要三个阶段:连接建立.数据传送和连接释放.三次握手就发生在连接建立阶段. 在谢希仁著<计算机网络>第四版中讲三次握手的目的是为 ...

  5. Java final类

    如果说整个类都是final(在它的定义前冠以final关键字),就表明自己不希望从这个类继承,或者不允许其他任何人采取这种操作.换言之,出于这样或那样的原因,我们的类肯定不需要进行任何改变:或者出于安 ...

  6. javascript(定时函数)

    一setTimeout函数和setInterval函数的语法以及应用 1.setTimeout函数 定义和用法:setTimeout()方法用于在指定的毫秒数后调用函数或计算表达式. 语法:setTi ...

  7. IO碰到的问题

    1.流关了,并不代表流对象为空 可是java并没提供查看流是否关闭的方法 不过如果流已经关闭了以后,再对流进行操作的话,会抛出IOException:Stream closed异常 可以根据这个异常来 ...

  8. Android应用开发基础之十:多媒体编程

    多媒体概念 文字.图片.音频.视频 计算机图片大小的计算 图片大小 = 图片的总像素 * 每个像素占用的大小 单色图:每个像素占用1/8个字节 16色图:每个像素占用1/2个字节 256色图:每个像素 ...

  9. 如何创建C# Closure ?

    JavaScript中一个重要的概念就是闭包,闭包在JavaScript中有大量的应用,但是你知道么?C#也可以创建Closure.下面就介绍一下如何在C#中创建神奇的闭包. 在这之前,我们必须先知道 ...

  10. jQuery构造函数init参数分析(三)

    分析完了字符串情况剩下的就不多了. 5.参数selector是函数 这个就是很容易想到了,首先说一下dom加载.我们通常在head里面写脚本的时候需要等待文档加载在进行处理,js是这么写的 windo ...