GCRoots
JVM面试汇总
JVM垃圾回收的时候如何确定垃圾?是否知道什么是GC Roots
什么是垃圾
简单来说就是内存中已经不再被使用的空间就是垃圾
如何判断一个对象是否可以被回收
引用计数法
Java中,引用和对象是有关联的。如果要操作对象则必须用引用进行。
因此,很显然一个简单的办法就是通过引用计数来判断一个对象是否可以回收。简单说,给对象中添加一个引用计数器
每当有一个地方引用它,计数器值加1
每当有一个引用失效,计数器值减1
任何时刻计数器值为零的对象就是不可能再被使用的,那么这个对象就是可回收对象。
那么为什么主流的Java虚拟机里面都没有选用这个方法呢?其中最主要的原因是它很难解决对象之间相互循环引用的问题。
该算法存在但目前无人用了,解决不了循环引用的问题,了解即可。

枚举根节点做可达性分析
根搜索路径算法
为了解决引用计数法的循环引用个问题,Java使用了可达性分析的方法:

所谓 GC Roots 或者说 Tracing Roots的“根集合” 就是一组必须活跃的引用
基本思路就是通过一系列名为 GC Roots的对象作为起始点,从这个被称为GC Roots的对象开始向下搜索,如果一个对象到GC Roots没有任何引用链相连,则说明此对象不可用。也即给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,没有被遍历到的对象就被判定为死亡

必须从GC Roots对象开始,这个类似于linux的 / 也就是根目录
蓝色部分是从GC Roots出发,能够循环可达
而白色部分,从GC Roots出发,无法到达
一句话理解GC Roots
假设我们现在有三个实体,分别是 人,狗,毛衣
然后他们之间的关系是:人 牵着 狗,狗穿着毛衣,他们之间是强连接的关系
有一天人消失了,只剩下狗狗 和 毛衣,这个时候,把人想象成 GC Roots,因为 人 和 狗之间失去了绳子连接,
那么狗可能被回收,也就是被警察抓起来,被送到流浪狗寄养所
假设狗和人有强连接的时候,狗狗就不会被当成是流浪狗
那些对象可以当做GC Roots
- 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中的引用对象
- 方法区中的类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中的JNI(Native方法)的引用对象
代码说明
/**
* 在Java中,可以作为GC Roots的对象有:
* - 虚拟机栈(栈帧中的局部变量区,也叫做局部变量表)中的引用对象
* - 方法区中的类静态属性引用的对象
* - 方法区中常量引用的对象
* - 本地方法栈中的JNI(Native方法)的引用对象
*/
public class GCRootDemo {
// 方法区中的类静态属性引用的对象
// private static GCRootDemo2 t2;
// 方法区中的常量引用,GC Roots 也会以这个为起点,进行遍历
// private static final GCRootDemo3 t3 = new GCRootDemo3(8);
public static void m1() {
// 第一种,虚拟机栈中的引用对象
GCRootDemo t1 = new GCRootDemo();
System.gc();
System.out.println("第一次GC完成");
}
public static void main(String[] args) {
m1();
}
}
GCRoots的更多相关文章
- 【JVM】GCRoots和JVM的参数配置
如何理解GCRoots? 为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法.GC Roots是一组活跃的引用,通过一系列名为GC Roots的对象作为起始点,沿着该对象向下搜索,如果一 ...
- GCRoots 对象
GC Roots 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中的类静态属性引用的对象 方法区中的常量引用的对象 原生方法栈(Native Method Stack)中 JNI 中引用的对象 可 ...
- JVM内存垃圾回收方法
1.概述 1.1.为什么要回收? 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断地分配内存空间而不进行回收.除非内存无限大,我们可以任性地分配而不回收,但是事实并非如此.所以,垃圾回收是必须 ...
- 【JVM】JVM系列之垃圾回收(二)
一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收.除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此.所以,垃圾回收是必须的. 二. ...
- WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 系列博文 <WinDbg 命令三部曲:(一)WinDbg 命令手册> <WinDb ...
- 深入理解JVM-3垃圾收集器与内存分配策略
在上面一篇文章中,介绍了java内存运行时区域,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程生灭:栈中的栈帧随着方法的进入和退出而有条不紊的执行着进栈出栈的操作,每一个栈帧中分配着多少内存基本上 ...
- 使用AndroidStudio dump heap,再用 Eclipse MAT插件分析内存泄露
1.eclipse mat插件的安装 Help->Install new software,如下图,一直下一步即可 2.AndroidStudio dump heap 3.AndroidStud ...
- 从sample来学习Java堆(转)
1)Java堆 所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示: public class HeapOOM { static class OOMOb ...
- JAVA GC之标记 第五节
JAVA GC之标记 第五节 OK,我们继续昨天最后留下的问题,什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方 ...
随机推荐
- Maybatis的一些总结(二:基本使用过程)
理清一下使用需要做的步骤 建项目,导入mybatis(3.5.2)和mysql(5.1.47)进pom.xml pom.xml需配置build时过滤器,否则会出现xml文件导出不了的问题 resour ...
- Flutter 吐血整理组件继承关系图
老孟导读:前几天一个读者和我说能不能整理一个各个控件之间的继承关系,这2天抽时间整理了一下,不整理不知道,一整理真的吓一跳啊,仅仅Widget的子类(包括间接子类)就高达353个,今天发群里给大家浏览 ...
- 学习笔记分享之汇编---3. 堆栈&标志寄存器
前言: 此文章收录在本人的<学习笔记分享>分类中,此分类记录本人的学习心得体会,现全部分享出来希望和大家共同交流学习成长.附上分类链接: https://www.cnblogs.c ...
- skynet启动流程及调用服务
3.基本原理 3.1启动流程 1.skynet-src/skynet_main.c 这个是main()函数所在,主要就是设置一下lua的环境.默认的配置.打开config配置文件,并修改默认配置. ...
- EOS基础全家桶(八)jungle测试网的使用
简介 前面我们已经学习了一些EOS的基础知识了,但是在EOS主网上的很多操作(比如:抵押.赎回.买卖内存)都是需要EOS链被正式激活后才可使用,而激活EOS链还需要很多的准备操作,我打算在单独的一篇文 ...
- Java中常用的七个阻塞队列第二篇DelayQueue源码介绍
Java中常用的七个阻塞队列第二篇DelayQueue源码介绍 通过前面两篇文章,我们对队列有了了解及已经认识了常用阻塞队列中的三个了.本篇我们继续介绍剩下的几个队列. 本文主要内容:通过源码学习De ...
- 苹果登录服务端JWT算法验证-PHP
验证参数 可用的验证参数有 userID.authorizationCode.identityToken,需要iOS客户端传过来 验证方式 苹果登录验证可以选择两种验证方式 具体可参考这篇文章 htt ...
- 使用pthread进行编程
使用pthread进行并行编程 进程与线程 进程是一个运行程序的实例:线程像一个轻量级的进程:在一个共享内存系统中,一个进程可以有多个线程 POSIX® Threads: 即 Pthreads,是一个 ...
- php的echo 和 return的区别
来源:https://blog.csdn.net/ljfphp/article/details/76718635 项目中碰到的问题,本来是想在控制器直接return $xml的($xml是一段xml格 ...
- 列表按钮功能的设置和DOM的使用
HTML: <foreach name="fulltime_list" item="v"> <tr> <td></td ...