上篇文章我们介绍了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. InfluxDB学习之InfluxDB连续查询(Continuous Queries)

    在上一篇:InfluxDB学习之InfluxDB数据保留策略(Retention Policies) 中,我们介绍了 InfluxDB的数据保留策略,数据超过保存策略里指定的时间之后,就会被删除. 但 ...

  2. InfluxDB学习之InfluxDB的基本概念

    InfluxDB与传统数据库在概念上有许多的不同,本文就给大家介绍下InfluxDB中的一些基本概念,更多InfluxDB详细教程请看:InfluxDB系列学习教程目录 InfluxDB技术交流群:5 ...

  3. Spring4学习笔记 - 配置Bean - 自动装配 关系 作用域 引用外部属性文件

    1 Autowire自动装配 1.1 使用:只需在<bean>中使用autowire元素 <bean id="student" class="com.k ...

  4. React Canvas:高性能渲染 React 组

    React Canvas 提供了使用 Canvas 渲染移动 Web App 界面的能力,替代传统的 DOM 渲染,具有更接近 Native App 的使用体验.React Canvas 提供了一组标 ...

  5. React Native 常见问题集合

    在使用React Native时候,我记录下比较常遇到的问题,分为以下几类: 1. 调试问题 2. 写法问题 3. 疑难问题 4. 奇怪问题 调试问题 1. 在react-native run-and ...

  6. AngularJS结合RequireJS做文件合并压缩的那些坑

    我在项目使用了AngularJS框架,用RequireJS做异步模块加载(AMD),在做文件合并压缩时,遇到了一些坑,有些只是解决了,但不明白原因. 那些坑 1. build.js里面的paths必须 ...

  7. JavaScript中的各种变量提升(Hoisting)

    首先纠正下,文章标题里的 “变量提升” 名词是随大流叫法,“变量提升” 改为 “标识符提升” 更准确.因为变量一般指使用 var 声明的标识符,JS 里使用 function 声明的标识符也存在提升( ...

  8. iOS音频开发之`AudioStreamBasicDescription`

    这个类提供了对于音频文件的描述 An audio stream is a continuous series of data that represents a sound, such as a so ...

  9. Android jni开发中的常见错误

    错误1:java.lang.UnsatisfiedLinkError: Native method not found: 本地方法没有找到 1.本地函数名写错 2.忘记加载.so文件 没有调用Syst ...

  10. iOS 检查更新

    注意:苹果官方是不允许app具有检查更新提示! //直接跳转到AppStore - (void)setUpAppUpdate {    [ServerData queryGetURL:@{@" ...