目录

  • JVM 的内存划分
  • 类加载的过程
  • JVM中的垃圾回收机制(GC)

JVM 的内存划分

JVM从操作系统申请到内存,然后将其划分为以下区域

  • 程序计数器

    • 用来保存下一条要执行的指令在哪
    • 当一个程序想要运行,JVM就得把指令(字节码)加载到内存中,然后程序从内存中一条条取出指令,放到CPU上执行
    • 我们知道CPU是并行加并发执行的,当CPU执行了一段时间别的进程指令后,再回来接着执行该进程,就需要知道该进程目前执行到哪里了,程序计数器就能记录。(每个线程都有一个程序计数器)
    • 用来存放 局部变量方法调用信息
    • 每次调用一个方法,该方法就会入栈,每一个方法执行完,该方法就会出栈
    • 栈中存放每个方法的信息就叫做 栈帧 ,遵循先进后出的原则
    • 站空间比较小,如果递归次数多,条件没写好,很有可能就会栈溢出
    • 每个线程就有一个单独的栈空间
    • 成员变量、new出来的对象都是在堆中
    • 每个进程只有一份,多个线程共用一份
  • 方法区
    • 方法区放的就是 类对象 ,类对象就描述了一个类长什么样(里面的成员、方法、成员类型、方法类型、方法里的指令…)

类加载的过程

  • 类加载: 把.class文件加载到内存中,然后被JVM构造成类对象

    • 类加载的过程
  • 双亲委派模型: JVM中的类加载器找 .class文件的过程
    • 默认的类加载器有以下3个
    • BootStrapClassLoader: 负责加载标准库中的类(String、ArrayList…)
    • ExtensionClassLoader:负责加载JDK扩展的类
    • ApplicationClassLoader:负责加载自己项目中的类(自己自定义的类)
  1. 加载java.lang.String的过程

    a. 程序启动,进入ApplicationClassLoader

    b. ApplicationClassLoader 检查他的父类加载器是否加载过了,没有则先加载

    c. ExtensionClassLoader 检查他的父类加载器是否加载过了,没有则先加载

    d. BootStrapClassLoader发现没有父类加载器,就自己扫描自己的目录,找到java.lang.String这个类,直接由BootStrapClassLoader负责后续的加载过程,查找环节结束

  2. 加载自定义的类 Animal

    a. 程序启动,进入ApplicationClassLoader

    b. ApplicationClassLoader 检查他的父类加载器是否加载过了,没有则先加载

    c. ExtensionClassLoader 检查他的父类加载器是否加载过了,没有则先加载

    d. BootStrapClassLoader发现没有父类加载器,就自己扫描自己的目录,未找到,则回到子类加载器

    e. ExtensionClassLoader 扫描自己的目录,未找到,则回到子类加载器

    f. ApplicationClassLoader 扫描自己的目录,找到该类,直接由其负责后续的加载过程,查找环节结束(如果也没找到,则会抛出类找不到的异常)

JVM中的垃圾回收机制(GC)

垃圾回收主要是回收的是 上的实例对象

  • 垃圾回收的基本单位是 对象

垃圾的判定:

  • 基于引用计数

当此处的引用计数为0时,就认为该对象是垃圾。

void func(){Test t = new Test();Test t2 = t;
}

当该方法执行完毕后,t 和 t2 跟着栈帧一起释放,对应的引用实例对象的引用计数就 -1

缺点:

  1. 空间利用率低,每次创建一个对象都需要搭配一个计数器
  2. 会有 循环引用的问题

假设再加上 a1.a = a2; a2.a = a1;

接下来执行 a1 = null ; a2 = null;

此时两个对象的引用计数为0,无法释放,外界也没有代码访问这两个对象,这就造成了 “内存泄漏” 问题(申请了内存却没有释放)

  • 基于可达性分析: 通过额外的线程,定期针对整个内存空间的对象进行扫描
    有以下结构:

    对于A来说,F就是访问不到的节点,F就是不可达的,就被认定为垃圾,应该被回收

垃圾的回收:

  • 标记 - 清除

    标记:就是对对象进行可达性分析,如果是垃圾则标记为垃圾

    清除:这里的垃圾都是不连续的,当释放掉这些资源后,会产生很多的 内存碎片 ,内存碎片过多,则空间利用率会下降(比如内存碎片加起来有500M,要申请200M的内存可能会申请失败,因为可能没有连续的200M的内存)

  • 复制算法
    为了解决上述的内存碎片的问题, 又引入了复制算法

    将不是垃圾的内存中的数据,拷贝到没有使用的另一半内存中,然后将之前的一半空间完全释放掉

    缺点:

    1. 内存空间利用率低,每次只用一半
    2. 如果要保留的对象相对于垃圾来说比较多,则复制的开销较大
  • 标记 - 整理
    类似于顺序表的删除操作,将要保留的前移,然后释放掉后半部分的空间

实际JVM是将多种方案结合 – 分代回收 (根据对象的“年龄”分类,熬过一轮GC扫描,年龄就大了一岁)

  1. 对于刚创建的对象,都会被放到伊甸区
  2. 伊甸区的对象熬过一轮扫描,就被拷贝到 幸存区(大部分对象都熬不过一轮GC就被回收了)(复制算法)
  3. 在后续的几轮GC中, 幸存区的对象就再两个幸存区来回拷贝 (复制算法)
  4. 若干轮之后,进入老年代
  5. 老年代的GC扫描频率大大小于新生代 (标记 – 整理 的方式进行回收)
  6. 例外:比较大的对象最初就会被放到老年代区,因为对象比较大,不适合用复制算法一直复制下去

垃圾回收器

Serial收集器、Serial Old收集器: 串行收集,产生严重的STW
ParNew收集器、Parallel Old收集器、Parallel Scavenge: 并发收集,引入多线程扫描
CMS收集器: 尽可能使得STW时间短1
1. 初始标记,速度很快,会引起短暂的STW
2. 并发标记,速度慢,但可以和业务线程并发执行
3. 重新标记,针对2进行微调
4. 回收内存,并发
G1收集器: 将整个内存划分为很多个小的区域,一次扫描若干个区域(分多次扫描)

JVM内存管理及垃圾回收机制相关推荐

  1. 详解JVM内存管理与垃圾回收机制2 - 何为垃圾

    随着编程语言的发展,GC的功能不断增强,性能也不断提高,作为语言背后的无名英雄,GC离我们的工作似乎越来越远.作为Java程序员,对这一点也许会有更深的体会,我们不需要了解太多与GC相关的知识,就能很 ...

  2. 详解JVM内存管理与垃圾回收机制5 - Java中的4种引用类型

    在Java语言中,除了基础数据类型的变量以外,其他的都是引用类型,指向各种不同的对象.在前文我们也已经知道,Java中的引用可以是认为对指针的封装,这个指针中存储的值代表的是另外一块内存的起始地址(对 ...

  3. JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)

    转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...

  4. visual studio内存溢出检测工具_详解JVM内存管理与垃圾回收机制2 何为垃圾

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 随着编程语言的发展,GC的功能不断增强,性能也不断提高,作为语言背 ...

  5. 详解JVM内存管理与垃圾回收机制3 - JVM中对象的内存布局

    在Java语言层面,可以通过Class类来描述普通的Java类,当JVM创建对象的同时,会生成对应的Class对象,用来描述此对象的大致模型,这也是反射的基础.那么在JVM的内部是如何描述一个普通的对 ...

  6. Python内存管理以及垃圾回收机制

    垃圾回收:用通俗点的语言解释就是内存管理和垃圾回收的过程. 大管家refchain 在Python的C源码中有一个名为refchain的环状双向链表,这个链表就比较厉害了,因为Python程序中一旦创 ...

  7. python内存的回收机制_python的内存管理和垃圾回收机制详解

    简单来说python的内存管理机制有三种 1)引用计数 2)垃圾回收 3)内存池 接下来我们来详细讲解这三种管理机制 1,引用计数: 引用计数是一种非常高效的内存管理手段,当一个pyhton对象被引用 ...

  8. Python的内存管理与垃圾回收机制

    在使用真格量化时,一些用户希望了解如何来提高系统性能.通过了解Python的内存管理和垃圾回收机制,我们可以有针对性地去提高策略代码性能. Python内存管理机制 Python的内存管理机制:引入计 ...

  9. JVM——内存管理和垃圾回收

    1.  何为GC Java与C语言相比的一个优势是,可以通过自己的JVM自动分配和回收内存空间.垃圾回收机制是由垃圾收集器Garbage Collection来实现的,GC是后台一个低优先级的守护进程 ...

  10. java基础(一):谈谈java内存管理与垃圾回收机制

    看了很多java内存管理的文章或者博客,写的要么笼统,要么划分的不正确,且很多文章都千篇一律.例如部分地方将jvm笼统的分为堆.栈.程序计数器,这么分太过于笼统,无法清晰的阐述java的内存管理模型: ...

最新文章

  1. Ubuntu16.04下Mongodb官网卸载部署步骤(图文详解)(博主推荐)
  2. 数据中心的敏捷运维之路
  3. weblogic启动失败案例(root启动引起的权限问题)
  4. python调用系统_python 执行系统命令
  5. 以毒攻毒Fight Fire with Fire: Towards Robust Recommender Systems via Adversarial Poisoning Training论文解读
  6. 对int array进行排序
  7. 如何将先验知识注入推荐模型
  8. 【转】用Microsoft Ajax Minifier帮你的Javascript瘦身
  9. 使用idea开发SpringBoot应用,添加@SpringBootApplication注解时,不能自动提示
  10. Java之JavaBean
  11. pic单片机c语言 程序,PIC单片机C语言编程教程(1)
  12. 小爱同学指令大全_小爱同学有趣的命令分享给大家
  13. 关于深圳商事登记招商ukey签名无效
  14. Are We Evaluating Rigorously? Benchmarking Recommendation for Reproducible Evaluation and Fair Compa
  15. CC00229.CloudKubernetes——|KuberNetes细粒度权限控制.V13|——|Ratel.v01|k8s资源管理平台部署|
  16. VC版DoEvents/处理事件
  17. Ubuntu安装之,硬盘分区
  18. 剧本翻译之メンアットワーク!4 ~ハンター達よ永遠に~猎人们的永远(序章2)
  19. AndroidX TabLayout使用、扩展及解析All In One,跪了
  20. html网页关键字批量替换,织梦(DEDECMS)批量替换文章,标题,关键字,标签等等内容的SQL命令...

热门文章

  1. Revit二次开发——HelloRevitApp
  2. 关于《训练指南》中的“翻棋子游戏”
  3. extmail 发送邮件附件大小限制修改
  4. centos7.2下搭建postfix++dovecot+courier-authlib+extmail邮件收发系统
  5. 色情版“微信”背后的秘密
  6. 蓝牙低功耗音频技术 -- 1 背景和遗产
  7. kindle我的剪帖文件整理脚本
  8. 查看数据库实例名的方法:
  9. Bluetooth以及音频协议 基础知识学习
  10. dbfs和dbm的换算_功率W与dBm的对照表及关系(转)