精华内容
下载资源
问答
  • JVM的划分jvm面分为 方法区 Java栈 堆 本地方法区、程序...因此所有的加载请求都应该传送启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下找不所需要加载的Class),子类加载...
    JVM的划分jvm面分为 方法区  Java栈  堆  本地方法区、程序计数器

    f766110a6868b7df18418f919e081df7.png

    类加载机制

    b0f0b64053f11ed195aa71c4f4d8a6b9.png

    双亲委派  沙箱安全机制

    3ca048dd08b55c1185ce3454d863e4eb.png

    双亲委派机制当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下找不到所需要加载的Class),子类加载器才会尝试自己去加载。采用双亲委派的一个好处是,比如家在位于tr.jar包中的类java.object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器,最终得到的都是同样一个Object对象。

    Java栈

    栈也叫栈内存,主管java程序的运行,是在线程创建时创建,他的生命周期是跟随线程的生命周期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收的问题,只要线程一结束该栈就over,生命周期和线程一致,是线程私有的,8种基本类型变量+对象的引用变量+实例方法都是在函数的栈内存中分配栈帧中主要保存3类数据本地变量:输入参数和输出参数以及方法内的变量栈操作:记录出栈、入栈的操作栈帧数据:包括类文件、方法等java.lang.StackOverflowErrorSOF 栈溢出错误

    程序计数器

    pc程序计数器每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向下一条命令的地址,也即将要执行的指令代码),由于执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。它是当前线程执行的字节码的行号指示器。供各线程共享的运行时的内存区域。它存储了每一个类的结构信息,例如运行时的常量池、字段和方法数据、构造函数和普通方法的字节码内容。在不同虚拟机里实现是不一样的,最典型的就是永久代和元空间。实例变量存放在堆内存中,和方法区无关。

    ed4d22c68f009ca3f2ce802a5fb18ef1.png轻GC的过程复制-->清除--->互换新生区占堆内存的1/3,新生区中伊甸区和幸存1区和幸存2区占比8:1:1,老年代占堆区的2/3Jdk1.7是永久存储区,JDK8之后改为元空间,这是一个逻辑存在的,堆中物理上存在的是新生代和老年代Java8中永久代被移除,被元空间所取代,元空间和永久代的区别在于:永久代使用的JVM堆内存,但是Java8以后,元空间并不在虚拟机中,而是使用本机物理内存JVM默认所占的内存是本机内存的四分之一
    JVM调优
    出现内存溢出的异常,说明java虚拟机的内存不够(OOM),原因有:1.java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整2.代码中创建了大量的对象,并且长时间不能被垃圾收集器收集(存在引用)-Xmx 内存和-Xms内存保持一致(即初始内存和最大内存设置成一样),原因是防止GC和应用程序争抢内存,造成内存忽高忽低产生停顿。eg:-Xmx10m -Xms10m -XX:+PrintGCDetails

    c8b6b1e5f6d1545ce9c06e3445775d32.png

    4ef7d9b7922977e70a72ca14444aa806.png

    如上表所示,目前主要有串行、并行和并发三种,对于大内存的应用而言,串行的性能太低,因此使用到的主要是并行和并发两种。并行和并发 GC 的策略通过 UseParallelGCUseConcMarkSweepGC 来指定,还有一些细节的配置参数用来配置策略的执行方式。例如:XX:ParallelGCThreadsXX:CMSInitiatingOccupancyFraction 等。通常:Young 区对象回收只可选择并行(耗时间),Old 区选择并发(耗 CPU)。
    项目中常用配置
    备注:在Java8中永久代的参数-XX:PermSize-XX:MaxPermSize已经失效。

    6e97bd12a712e0d7737d3ffdf5dc1c89.png

    c8b6b1e5f6d1545ce9c06e3445775d32.png

    常用 GC 调优策略

    1. GC 调优原则;
    2. GC 调优目的;
    3. GC 调优策略;

    GC 调优原则

    在调优之前,我们需要记住下面的原则:
    多数的 Java 应用不需要在服务器上进行 GC 优化;多数导致 GC 问题的 Java 应用,都不是因为我们参数设置错误,而是代码问题;在应用上线之前,先考虑将机器的 JVM 参数设置到最优(最适合);减少创建对象的数量;减少使用全局变量和大对象;GC 优化是到最后不得已才采用的手段;在实际使用中,分析 GC 情况优化代码比优化 GC 参数要多得多。

    GC 调优目的

    将转移到老年代的对象数量降低到最小;减少 GC 的执行时间。

    GC 调优策略

    策略 1:将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。策略 2:大对象进入老年代,虽然大部分情况下,将对象分配在新生代是合理的。但是对于大对象这种做法却值得商榷,大对象如果首次在新生代分配可能会出现空间不足导致很多年龄不够的小对象被分配的老年代,破坏新生代的对象结构,可能会出现频繁的 full gc。因此,对于大对象,可以设置直接进入老年代(当然短命的大对象对于垃圾回收来说简直就是噩梦)。-XX:PretenureSizeThreshold 可以设置直接进入老年代的对象大小。策略 3:合理设置进入老年代对象的年龄,-XX:MaxTenuringThreshold 设置对象进入老年代的年龄大小,减少老年代的内存占用,降低 full gc 发生的频率。策略 4:设置稳定的堆大小,堆大小设置有两个参数:-Xms 初始化堆大小,-Xmx 最大堆大小。策略5:注意:如果满足下面的指标,则一般不需要进行 GC 优化:
    MinorGC 执行时间不到50ms;Minor GC 执行不频繁,约10秒一次;Full GC 执行时间不到1s;Full GC 执行频率不算频繁,不低于10分钟1次。

    垃圾回收机制

    GC回收特性:
    • 次数上频繁手机Young区
    • 次数上较少收集Old区
    • 基本不动元空间

    28006b8f0b2d4dca329d4b0ab1a6cad3.png

    JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的多是指新生代。因此GC按照回收的区域分又分了两种类型:一种时普通GC(minor GC),一种时全局GC(major GC or full GC)轻GC和重GC的区别:普通GC:只针对新生代区域的GC,只发生在新生代的垃圾收集动作,因为大多数Java对象存活率都不高,所以minor GC非常频繁,一般回收速度也比较快。全局GC:指发生在老年代的垃圾收集动作,出现了major GC,经常伴随至少一次的普通GC(但并不绝对),major GC的速度一般比普通GC慢了10倍以上

    GC的算法

    引用计数法
    当一个对象,每被引用一起,就标记加一,当引用标记变成0的时候,就是等待回收的垃圾了。缺点:
    • 每次对对象赋值时均要维护引用计数器,且计数器本身也有一定的消耗
    • 较难处理循环引用
    JVM的实现一般不采用这种方式
    复制算法
    年轻代中使用的是minor GC, 这种GC算法采用的就是复制算法复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一快上面,复制算法不会产生时间碎片。从根集合(GC root )开始,通过Tracing从From中找到存活对象,拷贝到To中;从From、To交换身份,夏促内存分配从To开始
    标记清除

    当堆中的有效内存空间(available memory)被耗尽的时候,就会停止整个程序(也被称为stop the world),即STW,然后进行两项工作,第一项则是标记,第二项则是清除。

    缺点

    • 效率不算高

    • 在进行GC的时候,需要停止整个应用程序,导致用户体验差

    • 这种方式清理出来的空闲内存是不连续的,产生内存碎片。需要维护一个空闲列表

    标记压缩

    其分为两个阶段标记阶段,和压缩阶段.其中标记阶段和标记清除算法的标记阶段是一样的.

    • 对压缩算法来说,他的工作就是移动所有的可达对象到堆内存的同一区域中,使它们紧凑的排列在一起,从而将所有非可达对象释放出来的空闲内存集中在一起,以防出现标记清除算法的弊端.

    在压缩阶段,由于要移动可达对象,那么就要考虑移动对象时候的顺序问题,一般分为一下三种:

    1. 任意顺序,不考虑原先对象的排列顺序,也不考虑对象之间的引用关系,随意移动可达对象,这样可能会有内存访问的局部性问题.

    2. 线性顺序,在重新排列对象时,会考虑到对象之间的引用关系,例如对象A引用了对象V,那么就会尽量将对象A,B排列在一起.

    3. 滑动排序,按照原先的排列顺序滑动到堆的另一端.
      现在大部分垃圾回收算法都是按照任意顺序或者是滑动顺序去实现的.

    CPU暴增怎么处理

    可能存在频繁的GC或者内存泄漏、或者对象过大回收时间较长,导致线程一致被占用,排查处理的两种情况,第一种是业务线程,第二种是GC线程,如果是业务线程,就找到对应的业务进行优化处理,如果是GC线程,使用jmap命令进行观察,使用 heap down on out of  memeary error 保存文件,使用MAT对日志文件进行分析处理。
    展开全文
  • JVM系列之GC

    2020-06-23 17:04:01
    JVM,大家都知道GC(Garbage Collection),GC这个话题说浅了就一句话--JVM自动垃圾收集,说深了就无止尽了,回收算法,各种收集器,gc类型,gc触发点....等等,作者也是略懂皮毛,这里给大家推荐一个知乎上比较活跃...

    谈到JVM,大家都知道GC(Garbage Collection),GC这个话题说浅了就一句话--JVM自动垃圾收集,说深了就无止尽了,回收算法,各种收集器,gc类型,gc触发点....等等,作者也是略懂皮毛,这里给大家推荐一个知乎上比较活跃的JVM大牛,RednaxelaFX,是专门做JVM开发的,业界号称"R大"。放
    鉴于作者才学疏浅,这篇博文还是准备用通熟易懂的话把作者自己对GC这一块的理解做陈述,概要如下:

    文章结构

    1. 哪些内存需要回收(Which)
    2. 各种GC的触发时机(When)
    3. 如何回收(How)
      3.1 回收算法
      3.2 HotSpot的具体实现-各种收集器
    4. GC日志

    1. 哪些内存需要回收(Which)

    大多数没干过C或者C++的Javaer是幸福的,因为没有体会过那种自己new delete内存的感觉,创建对象就是new,不管内存的回收问题。其实我们的内存是JVM的GC机制来帮我们回收的。那么问题来了。到底哪些内存需要回收呢?
    答案:可达性分析算法,说白了,就是JVM预先确定一组GC roots引用变量,如Student stu =new Student();这个stu就可以作为GC roots,当进行垃圾回收时,JVM通过GC Roots找到能够引用到的所有活对象,然后把剩下的对象标记为"无用",即可回收状态
    能够作为GC roots的引用如下:

    • 所有Java线程当前活跃的栈帧里指向GC堆里的对象的引用;换句话说,当前 所有正在被调用的方法的引用类型的参数/局部变量/临时值。
    • VM的一些静态数据结构里指向GC堆里的对象的引用,例如说HotSpot VM里的Universe里有很多这样的引用。
    • JNI handles,包括global handles和local handles(看情况)所有当前被加载的Java类(看情况)Java类的引用类型静态变量(看情况)Java类的运行时常量池里的引用类型常量(String或Class类型)(看情况)String常量池(StringTable)里的引用

    2. 各种GC的触发时机(When)

    2.1 GC类型

    说到GC类型,就更有意思了,为什么呢,因为业界没有统一的严格意义上的界限,也没有严格意义上的GC类型,都是左边一个教授一套名字,右边一个作者一套名字。为什么会有这个情况呢,因为GC类型是和收集器有关的,不同的收集器会有自己独特的一些收集类型。所以作者在这里引用R大关于GC类型的介绍,作者觉得还是比较妥当准确的。如下:

    • Partial GC:并不收集整个GC堆的模式
      • Young GC(Minor GC):只收集young gen的GC
      • Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式
      • Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式
    • Full GC(Major GC):收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。

    2.2 触发时机

    上面大家也看到了,GC类型分分类是和收集器有关的,那么当然了,对于不同的收集器,GC触发时机也是不一样的,作者就针对默认的serial GC来说:

    • young GC:当young gen中的eden区分配满的时候触发。注意young GC中有部分存活对象会晋升到old gen,所以young GC后old gen的占用量通常会有所升高。
    • full GC:当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC(因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都会同时收集整个GC堆,包括young gen,所以不需要事先触发一次单独的young GC);或者,如果有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC;或者System.gc()、heap dump带GC,默认也是触发full GC。

    3. 如何回收(How)

    3.1 回收算法

    由于网上已经拥有非常多的优秀博文来详细介绍关于回收算法这块,所以这块作者将引用其他博客的介绍并加上自己的一些描述:
    3.1.1 标记清除算法(Mark-Sweep)

     


    3.1.2复制算法(Coping)(绝大部分收集器的新生代使用的算法)

     

     

    复制算法在JVM新生代垃圾回收中的运用:

     

     

    Eden:From:TO =8:1:1
    由于新生代中90%的对象都是"朝生夕死",采用复制算法是比较合理的,首先只移动了存活下来的对象(比较少数),其次,内存在移动到To区域后是有顺序的,不存在内存碎片。
    值得一提的是,假如在一次MinorGC时,Eden中存活的对象+From中存活的对象>To的剩余空间,则会通过担保机制将对象直接转移到Old gen ,如果Old gen的内存空间也不够,则进行一次Full gc .
    当对象的年龄到达15岁时会转移到Old gen (可通过参数配置,一般不建议更改。)

    3.1.3标记-整理算法(Mark-Compact):

     

     

    由于Old gen 的大部分对象都是年龄很大的对象,所以存活率比较高,采用复制算法肯定是行不通的(较多的对象复制操作),所以才大部分收集器的old gen采用 Mark-Compact算法,避免了空间碎片。

    3.1.4三种算法比较:

     

     

    稍微解释一下常见的关于GC时间的问题:
    为什么FGC的时间比MinorGC长很多?
    答:FGC进行了old gen的gc,由于算法上采用Mark-Sweep或者Mark-Compact,进行了很多对象(老年代存活率很低)的移动,当然很耗时了!其实就是空间换时间,时间换空间的问题。

    3.2 HotSpot的具体实现-各种收集器

    关于收集器这块,由于本人也是JVM初学者,加上很少有在生产环境做收集器参数调整,搭配使用的机会。所以可以说对于一些HotSpot收集器只是停留在

    谈到JVM,大家都知道GC(Garbage Collection),GC这个话题说浅了就一句话--JVM自动垃圾收集,说深了就无止尽了,回收算法,各种收集器,gc类型,gc触发点....等等,作者也是略懂皮毛,这里给大家推荐一个知乎上比较活跃的JVM大牛,RednaxelaFX,是专门做JVM开发的,业界号称"R大"。放个传送门:R大
    鉴于作者才学疏浅,这篇博文还是准备用通熟易懂的话把作者自己对GC这一块的理解做陈述,概要如下:

     

    4 GC日志

    -XX:+PrintGCDateStamps
    -XX:+PrintGCDetails
    -Xloggc:/Users/zdy/Desktop/dump/gclog.txt

    当服务器出现卡顿比较频繁时,尝试看下自己的GC日志,注意Full gc 频率。

    最后,稍微说一下作者的心得:

    • 如果是服务器一次卡顿时间比较长,一般是full gc时间过长,而应用最求的是卡顿(STW)时间短,可以接受多次卡顿,那么可以考虑调整加大young gen的比例,和提高进入老年代的年龄(默认15岁)来尽量避免FGC.
    • 选择合适的收集器很重要。要根据应用的特点。是追求吞吐量,还是追求最小停顿。
    • 经常对照gc日志观察现实的情况,如多长时间一卡顿,多久一卡顿,然后来调整自己的收集器或者相关的内存比例来达到自己想要的效果。
    • 在有限的物理资源条件下,要避免让用户接受过多的STW,可以考虑在半夜自动进行gc(System.gc()),虽然不一定生效,但可以观察下效果。多数情况下是会触发full gc 的。
    • 大多数应用是可以接受频繁的mgc,但却不能接受full gc 的长时间卡顿,所以在观察gc日志时一定要注意自己full gc的频率和触发条件(是由于内存担保,还是年龄到了,还是TO内存太小,导致每次都fgc.).


     

     

    展开全文
  • 网抑云二面虽然难偏怪,但是复盘下来,确实能学很多。 也感谢很多大佬跟我分享他们学习的思路和思考的方向,才写了这一篇文章,后续的有缘更新吧。 阅读前必看: 如果你只是想知道这个问题的答案,请出门左转找...

    网抑云二面面经

    网抑云二面虽然难偏怪,但是复盘下来,确实能学到很多。
    也感谢很多大佬跟我分享他们学习的思路和思考的方向,才写了这一篇文章,后续的有缘更新吧。

    阅读前必看:
    如果你只是想知道这个问题的答案,请出门左转找别人的博客,我这里并没有放出答案,而是以「就问题本身该怎么去思考」提供了自己的想法。

    那么现在我们回到正题。


    Java GC中使用引用计数法所存在的缺点

    首先是Javaer人尽皆知的循环依赖,然后呢?

    说实话,面试时因为【突如其来的没有自我介绍就直入主题 和 跳表刚讲了一句就被示意下一题】这种第一次遇见的情况,我自己也有点慌乱,毕竟面试经验还不够,当然了这都并不妨碍我想不出来回答,但是心态确确实实被影响了一下,需要及时调整。

    那么回到正题,在没有明确答案的时候,应该怎么去思考这个问题?从什么方面来思考?

    说白了就是得在空白的大脑里装点东西。

    如果是刚起步,可以说个大概,如果是思路清晰,那就可以结构化的去讲。

    引用一个牛油跟我说的话(这简直就是我求职路上的指路明灯啊)

    对于现在的互联网来说,其实无非是在追求两个东西,一个是更安全,一个是更快速,在这两个基础上在追求相互之间的边界性和联系性。

    所以其实很好发现,在我们平时学的一些东西的时候,他们的设计者无非是围绕着这两点去做的设计和优化。

    —— 双非也有梦想

    所以接下来,我们分别从安全速度来说。


    首先,「安全」。

    (还是引用他的话,因为太精辟了

    任何技术的操作,无非都是落脚到对于内存的操作,这也是我们为什么要费劲去研究操作系统和计算机基础的原因,对于内存的操作其实也就是对于数据的操作。

    —— 双非也有梦想

    所以我们可以进一步去想:引用计数法与「内存」之间的干系

    那么,我们平时编程中,有遇到内存相关的问题吗?
    有的。内存泄漏内存溢出。(这也是面试的一个常考知识点,内存溢出与内存泄漏的区别。

    我们知道引用计数法的实现,无非就是在对象上安一个计数器,每当有额外的对象引用该对象,或丢弃了对该对象的引用,就需要修改计数器。

    那么这个实现,与内存问题有关吗?

    不如先想想看

    内存泄露是什么?
    —— Memory Leak,无法释放已经申请的内存空间。

    内存溢出是什么?
    —— OOM,给对象分配内存时,内存不够。

    那么,引用计数法会导致内存泄露吗?
    详细来说,他会导致已申请的内存空间无法释放吗?

    如果还没有眉目,那换个问法,他会导致对象不会被回收吗? 也即,会不会存在对象的引用计数永不为0呢?

    这下应该恍然大悟了,我们“人尽皆知”的循环依赖的问题,无非就是对象的引用计数永远减少不到0。
    这其实就是带来了「安全」上的问题,细化来说,即是存在「内存泄漏」的问题。

    (虽然看起来是知道答案而在倒推答案的感觉吧。😂

    现在再来看看,引用计数法会导致内存溢出吗?
    会导致给对象分配内存时出现内存不足的情况吗?

    好像不会,当然你也可以说:给每个对象都安一个计数器难道不会占用很多内存吗?
    我觉得你完全可以跟面试官说出来,因为我也有这个想法。🤣


    走到现在,「安全」方面好像考虑得差不多了?
    (我这里的思路也主要只是从「内存问题」上来找,完全可以拓开自己的思路,因为我水平不高,只能想到这些。

    接下来,我们试试走「速度」这条路。

    我们知道,引用计数法本身的作用,是为了找到可以回收的对象。那么判断可回收对象的算法,就会对他有「速度」的要求。

    显然,引用计数法判断对象是否可回收只要与0做对比就好了,非常快,这也是他最大的优点。
    那我为什么要给「判断」加粗呢?

    想想看,GC除了判断是否可回收快,还要考虑什么方面的速度?

    如果没有思路,你想想看,「引用」是一个对象之间的事吗?

    显然,A引用B,那必然是牵扯到双方的事。
    假设现在,A对B的引用失效了,B需要做什么?更新

    想到了吗?

    我们不仅要求判断要快,更新也不能慢。

    假设现在存在一条链式引用,A引用B,B引用C,…,Y引用Z,现在万恶之源A丢弃了对B的引用,或者A被回收了。
    接下来会发生什么?链式效应的更新,与回收。
    那如果不是链式的,是网状的呢?洪泛效应的更新,与回收。

    而在实际项目中,对象的引用链通常是七通八达十分复杂的,任意一个引用的失效可能都会触发整个对象图的计数器的更新(个人觉得有点类似路由算法ospf)。

    现在假设在一个高并发的情况下,诸多对象的引用发生了变化,会带来什么问题?要解决什么问题?如何解决?
    个人认为其实这些就是如果jvm采用引用计数法时所需要解决的问题(中的其中一小部分)。

    开放性思路,你会怎么解决?


    其实这也只是如果让我再来重新思考这个问题,我会去采取的一个思考方式,当然了正式面试的时候还得看脑子空不空白了233333

    其实还能想很多,还可以去和可达性分析来做对比找不足等等,思考方式是多样化的。

    另外中间如果有错误还请指出,一起学习,谢谢。

    展开全文
  • 所以,我决定今天讲一下如何搭建你自己GC Server。(目前还没有一个人成功,请量力而行,如果成功了记得在评论区告诉我~) 步骤 1. 系统配置 本文仅适用于Windows系统,支持Win7及以后的大部分版本,Win10最佳。...
  • description: 最近开始着手JVM的学习,在这里把自己学习过程中的笔记分享出来,希望能帮一些小伙伴,同时也是对自己的学习的一个梳理。 GC概述 其实GC主要就是思考以下三件事情: 哪些内存需要回收? 什么时候...

    title: JVM学习笔记——GC概述
    date: 2018/9/2 12:05:00
    description: 最近开始着手JVM的学习,在这里把自己学习过程中的笔记分享出来,希望能帮到一些小伙伴,同时也是对自己的学习的一个梳理。

    GC概述

    其实GC主要就是思考以下三件事情:

    • 哪些内存需要回收?
    • 什么时候回收?
    • 如何回收?

    • 哪些内存需要回收

      主要针对Java堆和方法区,程序计数器、虚拟机栈、本地方法栈内存分配与回收具有确定性,所以不需要过多考虑GC的问题。
      其中方法区的回收主要针对以下两种:
      • 回收常量
        没有任何地方引用到该常量时,该常量将会被回收。
      • 回收无用类
        同时满足以下几个条件则视为“无用类”。
        • Java堆中不存在任何该类的实例
        • 加载该类的ClassLoader已经被回收
        • 该类的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问到该类。
    • 什么时候回收(判断对象是否“死去”)

      • 引用计数算法
        为对象增加一个引用计数器,每有一次引用则计数器+1,失去一个引用则计数器-1。这种算法效率很高,实现也很简单,但是在相互引用的情况下,会出现无法回收的情况。例如:a.instance = b; b.instance = a;
      • 可达性分析算法

        使用GC Roots作为起始点,当一个对象到GC Roots没有引用链路时(即不可达),则此时对象视为“死亡”。此方法也是现有JVM中常用的算法。
        GC Roots包括下面几种:

        • 虚拟机栈(栈帧中的本地变量表)中引用的对象
        • 本地方法栈中Native方法引用的对象
        • 方法区中类静态属性引用的对象
        • 方法区中常量引用的对象

        换句话来说,以上4中类型其实就是:类成员变量,类静态变量,常量,局部变量,只要某个对象不被以上4种类型关联到,那么该对象就是“已死”的,gc时就会被回收内存空间。

    • 如何回收(垃圾收集算法)

      • 标记-清除算法(Mark-Sweep)
        Mark-Sweep
        它是最基础的算法,后续的算法都是针对它的缺点改进而生。它存在两个缺点:
        • 效率问题。标记与清除这两个过程效率都不高。
        • 空间问题。如图所示,清除后的内存空间是不规整的,会产生大量的内存碎片。大量的碎片会导致分配大对象时,找不到连续的内存空间而提前触发另一次GC。

      • 复制算法(Copying)

        Copying
        针对标记-清除的效率问题,复制算法将内存分为两块空间,每次只使用其中一块。当这块的内存空间用完时,将存活的对象移到另一块中,然后将已使用的内存空间一次性清理掉。这样做的好处是不会产生碎片,清除也是针对连续的空间做处理,只要移动堆指针就行。
        实际上在现在的虚拟机中,将这种算法应用在新生代。按照8:1:1的比例将内存分为三块,每次使用一块较大的与较小的其中一块,清理时将存活对象移到剩下的一块中,这样每次只会浪费10%的内存,由于新生代中的内存一般都是“朝生夕死”的,使用这种算法可以极大的提升效率。但是,不能保证每次清理时,剩下的一块空间能够存放所有的存活对象,所以这里会依赖其他内存空间(一般指老年代)进行分配担保(Handle Promotion)。

      • 标记-整理算法(Mark-Compact)

        Mark-Compact
        复制算法在对象存活率较高时,效率就会变低,所以针对高对象存活率的情况,就有人提出了该算法。标记的过程并没有变化,但标记后并不是进行“清除”,而是将存活的对象向一端进行移动整理,然后清除掉其余的空间。现代虚拟机常将这种算法在老年代中使用。

      • 分代收集算法(Generational Collection)

        分代收集算法是根据对象的存活时间,将内存划分几块(一般分为新生代和老年代),这样就可以根据不同的内存区域特点采用不同的算法。针对新生代,使用复制算法,用少量的内存空间换来更大的效率;针对老年代,使用标记-整理或标记-清除来处理。

    转载于:https://www.cnblogs.com/qbzf-Blog/p/9573334.html

    展开全文
  • JVM的划分jvm面分为 方法区 Java栈 堆 本地方法区、程序...因此所有的加载请求都应该传送启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下找不所需要加载的Class),子类加载...
  • 比如,在系统A中生成了一个对象,这个对象会应用系统B,此时你需要将系统A迁移系统B。我们知道生成的对象是存储在虚拟机的堆内存中,如果碰到程序停止或者对象被GC等等情况都会使对象丢失,此时我们需要将对象...
  • Java程序员面试的时候一定会被问及许多Java基础类的问题。 正如昨天本人被问道Java GC介个问题。...java语言并不要求jvm有gc,也没有规定gc如何工作。不过常用的jvm都有gc,而且大多数gc都使用类似的算
  • 一、学习JVM内部原理和Java性能调优我跟多名高级Java开发人员了解,他们其中一项技能就是缺乏JVM内部原理、GC行为和Java性能调优方面的知识和理解。随着你java经验的积累,需要对虚拟机的基本原理和技术细节有一些...
  • 我们先来问下自己如何判介绍了断一个对象可以被回收。答案很简单也很直白。这个对象再也不会被调用了 ,那么就可以被回收了。那么怎么判断一个对象再也不会被别人调用呢?答案也很简单,只要其他的对象再也不...
  • 如果有些东西自己不亲身经历一下,看再多的理论知识也只能算是纸上谈兵,真正碰到问题的时候还是不知道该怎么分析。 本文包括以下内容: 提出问题 分析问题:掌握 GC 日志、线程、内存等维度的分析技巧,知道排查...
  • 首先,您的需求建议直接用Unsafe来做,这样手动管理更精细...默认实现是通过注册了一个Cleaner持有自己的幽灵引用,当幽灵引用探测到GC可以释放Java堆内的DirectByteBuffer对象时,通过回调来执行释放堆外内存的逻...
  • 浅谈对java-GC的理解

    2019-06-21 16:10:00
    但我还是想站在我的角度,对这件事发表一下自己的观点。 内存溢出,多发生在项目上线后,而且在系统开发阶段和单元测试阶段几乎不被发现。这其实是和开发者习惯有关。譬如一些空的引用,就会占着茅厕不拉屎等等 而...
  • 3. 面试中哪些问题会被经常问、面试中自己如何回答。 4. 自己的简历该如何写。 “80%的offer掌握在20%的人手中” 这句话也不是不无道理的。决定你面试能否成功的因素中实力固然占有很大一部
  • 首先,服务器要安装nginx和mysql,网站文件建议放在/usr/...本项目名称:loginOrRegister对于小白来说首先我们需要干的一件事情就是安置与配置nginx下面就是nginx的配置1.nginx配置安装nginx# gcc 安装yum install gc...
  • 上一篇文章我们已经初步分析了一次Young GC的日志,相信已经掌握了如何结合GC日志去分析一次Young GC执行的全过程。这篇文章我们接着之前的案例继续来做实验,动手体验一下对象是如何从新生代进入老年代的。动态年龄...
  • 将bilibili视频信息,用户信息或用户时间轴供稿嵌入自己的网页中 什么是嵌入?| 该项目实现了以下开源软件: 。 。 如何使用 就像将所有内容都放入您的webroot并在浏览器中打开index.html文件一样简单。 ...
  • cpu上加入了高速缓存这样做解决了处理器和内存的矛盾(一快一慢),但是引来的新的问题 - 缓存一致性在多核cpu中,每个处理器都有各自的高速缓存...如何保证多个处理器运算涉及同一个内存区域时,多线程场景下会存...
  • cpu上加入了高速缓存这样做解决了处理器和内存的矛盾(一快一慢),但是引来的新的问题 - 缓存一致性在多核cpu中,每个处理器都有各自的高速缓存...如何保证多个处理器运算涉及同一个内存区域时,多线程场景下会存...
  • 当执行 new 指令时,”一个以此为类型的对象将会分配 GC 堆中,并且所有的实例变量都会进行初始化为响应类型的初始值。“此时实例完成了默认初始化,之后虚拟机调用类的 方法进行《Thinking in Java》所说的指定...
  • 03 如何快速提升自己,通过面试? 写在开头 成长背景: 先说一下个人的一个成长背景吧。出身江南小镇,大学没有出省,毕业之后就去了上海,在一家互联网金融工作,去年年底整整两个年头。辞职之后运气不太好,...
  • 我本来是没想太多的,但有次无意中了解公司对于GC次数时间的监控居然是自己写程序解析JVM的gc日志,这让我有点大吃一惊,我虽然知道JVM对外提供了接口获取各种信息,但当时又一下子想不起来叫什么名字,怎么用,...
  • 如果你参加过一些大厂面试,还会问一些开放性的问题:1、写一段程序,让其运行时的表现为触发了5次Young GC、3次Full GC、然后3次Young GC;2、如果一个Java进程突然消失了,你会怎么去排查这种问...
  • Pinterest的发展,服务器也从数百个增加数千个,每秒产生数百万个数据点,而且这个数字还在继续增长。虽然OpenTSDB在功能上运行良好,但其性能随着Pinterest的增长而降低,导致运营开销(例如严重的 GC问题和HBase...
  • 回想到自己刚开始学习的时候,也是因为学习方法的不对,而耗费了太多的学习的时间。下面,就给大家直观的介绍一下jvm。 1.约见JVM 大多数人没能够直观的认识jvm是因为我们认识他的时候都是通过模型图(如下),...
  • 或者拿自己期待的薪资待遇?还是你仍在继续找工作的路上? 众所周知,2020年是不平凡的一年,几乎各行各业都在缩减编制。在这个大环境下,尤其是程序员,将会面临更大的挑战。而如何才能脱颖而出,就是小编今天...
  • 或者拿自己期待的薪资待遇?还是你仍在继续找工作的路上? 众所周知,2020年是不平凡的一年,几乎各行各业都在缩减编制。在这个大环境下,尤其是程序员,将会面临更大的挑战。而如何才能脱颖而出,就是小编今天...
  • 常量所在位置,不同版本jdk有什么区别,full gc的垃圾回收算法,及原理,标记-清理算法如何标记的,如何判断是否被引用。 6.正则如何使用 7.spring boot 和spring框架的异同点,spring boot用的时候踩的坑 8...
  • 仅代表个人观点 java基础 介绍一下什么时候使用=...通过了解内存模式和gc 说说自己的理解(>9) 说说java的反射,private的类或方法是否能反射(>8) 介绍一下bigdecimal(>7) integer使用什么比较数值(..

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 156
精华内容 62
关键字:

如何自己到gc