JVM学习到这里,终于到学习最兴奋的地方了---垃圾回收,在学习它之前还得对JVM垃圾回收相关理论知识进行了解,然后再通过实践来加深对理论的理解,下面直接开始了解相关的理论:

JVM运行时内存数据区域:

这个在之前其实已经介绍过了,对于JVM的垃圾回收一定是回收内存里面的内容,所以如果不对内存区域的划分,区域存放的内容有所了解,那何谈垃圾回收呢?所以看一下下图对内存区域的划分描述:

其这以上区域在上一次【https://www.cnblogs.com/webor2006/p/10618362.html】都已经讲过了,下面再来整体回顾一下。

方法区域:

其中它是数据是线程共享的:

那所谓方法区域是线程共享的是指的啥意思呢?比如说一个类的class元信息就会映射到方法区域当中,那么这个元信息会被所有的线程所访问,因为只有一份,所以该区域是线程共享的。

下面再来阐述一下它:

  • 存放了每个Class的结构信息,包括常量池、字段描述、方法描述。
  • GC的非主要工作区域。

Java虚拟机栈(JVM Stack):

下面再对其进行一些阐述:

  • Java虚拟机描述的是Java方法的执行模型:每个方法执行的时候都会创建一个帧(Frame),栈用于存放局部变量表,操作栈,动态链接,方法出口等信息。一个方法的执行过程,就是这个方法对于栈帧的入栈出栈过程。
  • 它是线程隔离的,如图上所示。

本地方法栈:

堆:

它里面的数据也是线程共享的:

下面再来阐述一下它:

  • 堆里存放的是对象的实例。
  • 是Java虚拟机管理内存中最大的一块。
  • GC主要的工作区域,为了高效的GC,会把堆细分更多的子区域。【这个在之后会细说】
  • 它是线程共享的,如图所示。

程序计数器:

JVM运行时数据区域例子:

对于这样一个方法代码:

以上方法在执行之后在内存中发生的变化如下:

  • 生成了2部分的内存区域:1、obj这个引用变量,因为是方法内的变量,放到JVM Stack里面;2、真正Object class的实例对象,放到Heap里面。
  • 上述的new语句一共消耗12个bytes,JVM规定引用占4个bytes(在JVM Stack),而空对象是8个bytes(在Heap)。
  • 方法结束后,对应Stack中的变量马上回收,但是Heap中的对象要等到GC来回收。

JVM垃圾回收(GC)模型:

垃圾判断算法:

  • 引用计数算法(Reference Counting)
    ①、给对象添加一个引用计数器,当有一个地方引用它,计数器加1,当引用失效,计数器减1,任何时刻计数器为0的对象就是不可能再被使用的,比较好理解。
    ②、引用计数算法无法解决对象循环引用的问题。啥意思,下面用图来说明一下:

    JVM中存在A、B两个对象,而A、B是相互引用着的,也就是A里面持有B的引用,而B里面又持有A的引用,如下:

    而开始这两对象是被其它地方所引用着的,比如方法栈中,如下:


    而之后虚拟机栈的这两个引用消失了,也就是整个虚拟机中就只有这两个相互引用的对象了,而这两对象不被任何对象所引用着了:

    而根据引用计数器的定义规则,A和B的引用计数器都是1,但是实际这俩都是孤立的对象,所以如果采用引用计数来进行垃圾回收,则这俩对象永远不会被回收。

  • 根搜索算法(GC Roots Tracing) 
    既然引用计数算法存在对象循环引用的问题,所以此算法出现了,下面具体看下该算法:
    ①、在实际的生产语言中(Java、C#等),都是使用根搜索算法判断对象是否存活。
    ②、算法基本思路就是通过一系列的称为“GC Roots”的点作为超始进行向下搜索,当一个对象到GC Roots没有任何引用链(Reference Chain)相连,则证明此对象是不可用的。 
    ③、在Java语言中,GC Roots包括【也就是什么是GC Roots?】:
         a、在vm栈(帧中的本地变量)中的引用。
              所以根据根搜索算法,由于目前没有栈中的引用指向A和B对象,所以这个算法规则这俩对象是可以被回收的了,如下:
              
         b、方法区中的静态引用。
         c、JNI(既一般说的Native方法)中的引用。

方法区:

  • Java虚拟机规范表示可以不要求虚拟机在这区域实现GC,这区域GC的“性价比”一般比较低。
  • 在堆中,尤其是在新生代,常规应用进行一次GC一般可以回收70%~80%的空间,而方法区的GC效率远小于此。
  • 当前的商业JVM都有实现方法区的GC,主要是回收两部分内容:废弃常量与无用类。
  • 类加收需要满足如下3个条件【条件是极其苛刻的】:
    1、该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例。
    2、加载该类的ClassLoader已经被GC。
    3、该类对应的java.lang.Class对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法。
  • 在大量使用反射、动态代理、CGLib等字节码框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要JVM具备类卸载的支持以保证方法区不会溢出。

JVM常见GC算法:

  • 标记-清除算法(Mark-Sweep)
  • 标记-整理算法(Mark-Compact)
  • 复制算法(Copying)
  • 分代算法(Generational)

具体每个算法下次继续再来学习~~

JVM垃圾回收重要理论剖析【纯理论】的更多相关文章

  1. JVM垃圾回收机制总结:调优方法

    转载: JVM垃圾回收机制总结:调优方法 JVM 优化经验总结 JVM 垃圾回收器工作原理及使用实例介绍

  2. JVM内存管理和JVM垃圾回收机制

    JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...

  3. JDK分析工具&JVM垃圾回收(转)

    转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...

  4. 老李分享:jvm垃圾回收

    老李分享:jvm垃圾回收   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478 ...

  5. jvm - 垃圾回收

    jvm - 垃圾回收 注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注 垃圾回收的意义 它使得java程序员不再时时刻刻的关注内存管理方面的工作. 垃圾回 ...

  6. JVM垃圾回收机制概述

    JVM垃圾回收机制概述 1.定义 是指JVM用于释放那些不再使用的对象所占用的内存. 2.方式 2.1引用计数(早期) 当引用程序创建引用以及引用超出范围时,JVM必须适当增减引用数.当某个对象的引用 ...

  7. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  8. JVM基础系列第8讲:JVM 垃圾回收机制

    在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...

  9. Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法

    在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...

随机推荐

  1. 淡sqlserver对like '%关键词%' 处理时的索引利用问题

    说法一:百分号%通配符前置会让SQL查询不走索引,改走全表扫描.这种说法很流行 结论是错误的 事实上这种说法不太准确 通配符%前置会让SQL查找索引时效率极速下降,但在大多数情况下还是会走索引(不需要 ...

  2. 逸鹏说道公众号福利:逆天常用的一些谷歌浏览器插件V1.3

    插件导出:http://www.cnblogs.com/dunitian/p/5426552.html 插件导入:https://www.cnblogs.com/dotnetcrazy/p/97537 ...

  3. POJ 1014 Dividing(入门例题一)

    Time Limit: 1000MS Memory Limit: 10000K Total Submissions: Accepted: Description Marsha and Bill own ...

  4. npm包的语义版本控制(Semantic Versioning of Packages)

    本文删改自Node.js 8 the Right Way Part I Chapter 3 npm 使用语义版本控制(SemVer)来寻找包的最佳可用兼容版本. 以安装测试框架mocha为例 $ ​​ ...

  5. LeetCode 653. 两数之和 IV - 输入 BST(Two Sum IV - Input is a BST)

    653. 两数之和 IV - 输入 BST 653. Two Sum IV - Input is a BST 题目描述 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定 ...

  6. 使用nohup命令编写shell脚本启动java应用,并使用外挂配置文件

    nohup nohup命令:如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令.该命令可以在你退出帐户/关闭终端之后继续运行相应的进程. 在缺省情况下该作业的所 ...

  7. 函数的练习1——python编程从入门到实践

    8-1 消息: 编写一个名为display_message()的函数,它打印一个句子指出你在本章学的是什么.调用这个函数,确认显示的消息正确无误. def display_message(): pri ...

  8. quartz2.3.0(四)JobDataMap—带状态集合的定时器内置集合

    任务类 package org.quartz.examples.example4; import java.util.Date; import org.quartz.DisallowConcurren ...

  9. .NET Core 中三种模式依赖注入的生命周期。

    注入模式 同一个请求作用域 不同的请求作用域 AddSingleton 同一个实例 同一个实例 AddScoped 同一个实例 新实例 AddTransient 新实例 新实例

  10. H3C S3600V2 通过CONSOLE配置端口镜像

    前24口为百兆口 对应序号为 Ethernet 1/0/(0~24) 25 26为千兆口 对应序号为 GigabitEthernet 1/0/(25~26) 以下是通过25号千兆口监听1号百兆口的例子 ...