精华内容
下载资源
问答
  • Stop the World

    2020-09-02 07:34:44
    Stop the World package com.atguigu.java; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * @author shkstart shkstart@126.com * @create 2020 15:50 */ public ...

    Stop the World

    在这里插入图片描述
    在这里插入图片描述

    package com.atguigu.java;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    /**
     * @author shkstart  shkstart@126.com
     * @create 2020  15:50
     */
    public class StopTheWorldDemo {
        public static class WorkThread extends Thread {
            List<byte[]> list = new ArrayList<byte[]>();
    
            public void run() {
                try {
                    while (true) {
                        for(int i = 0;i < 1000;i++){
                            byte[] buffer = new byte[1024];
                            list.add(buffer);
                        }
    
                        if(list.size() > 10000){
                            list.clear();
                            System.gc();//会触发full gc,进而会出现STW事件
                        }
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    
        public static class PrintThread extends Thread {
            public final long startTime = System.currentTimeMillis();
    
            public void run() {
                try {
                    while (true) {
                        // 每秒打印时间信息
                        long t = System.currentTimeMillis() - startTime;
                        System.out.println(t / 1000 + "." + t % 1000);
                        Thread.sleep(1000);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            WorkThread w = new WorkThread();
            PrintThread p = new PrintThread();
            w.start();
            p.start();
        }
    }
    
    
    展开全文
  • 1. 辣么多组合到底哪些是stop the world呢?答案:大部分都stw。包括1.1 Young GC类算法:Serial Young GC(DefNew)、Parallel Young GC、ParNew GC;1.2 Full GC类算法:Serial Old GC、PS MarkSweep GC / Para...

    先安利一个我的回答,里面大致介绍了Hotspot JVM里的几款GC算法组合。

    1. 辣么多组合到底哪些是stop the world呢?

    答案:大部分都stw。

    包括

    1.1 Young GC类算法:Serial Young GC(DefNew)、Parallel Young GC、ParNew GC;

    1.2 Full GC类算法:Serial Old GC、PS MarkSweep GC / Parallel Old GC、Full GC for CMS算法、Full GC for G1 GC算法;

    1.3 G1 GC算法:Young GC/Mixed GC 是stw的;

    2. CMS算法是怎么回事呢?

    2.1 CMS(Old)GC算法只在初始标记(initial mark)和再标记(remark)阶段stw一下;

    2.2 类似的,G1 GC算法在其标记阶段某几个时段是stop the world的,比如初始标记(initial mark)、再标记(remark)、清理(cleanup)阶段;

    展开全文
  • jvm-Stop the world

    2020-07-29 19:55:29
    Stop the world 介绍 什么是Stop the world? Java中Stop-The-World机制简称STW,Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互。 等待所有用户线程进入安全点后并...

    Stop the world 介绍

    什么是Stop the world?

    Java中Stop-The-World机制简称STW,Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互。

    等待所有用户线程进入安全点后并阻塞,做一些全局性操作的行为。

    在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外)。Stop-The-World对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World”的时间。不同垃圾收集器的Stop-The-World情况,Serial、Parallel和CMS收集器均存在不同程度的Stop-The-Word情况;而即便是最新的G1收集器也不例外。

    Gc为什么要进行stw?

    类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让大家停止活动了,才能将房间打扫干净。当gc线程在处理垃圾的时候,其它java线程要停止才能彻底清除干净,否则会影响gc线程的处理效率增加gc线程负担,特别是在垃圾标记的时候。

    当jvm运行对象存活判定算法的时候,如果当前环境下,对象之间的引用还在发生变化,那么这个算法几乎没法执行,所以常常需要STW来维持秩序。

     

    安全点

    JVM进行垃圾回收是一个非常复杂的过程,如何进行垃圾标记、什么时候进行垃圾、如果进行垃圾回收等等都非常复杂,当前主流测JVM在垃圾回收时都会进行STW(stop the world),即使宣称非常快的CMS垃圾回收期早期也会STW标记垃圾状态。那么这里有个问题,什么时候进行标记对象是否可以被回收呢?

    CPU在执行运算过程时需要把数据从内存中载入到寄存器,运算完后再从寄存器中载入到内存中,Java中对象地址也是这么个过程,设想如果一个Java线程分配一个对象,此时对象的地址还在寄存器中,这时候这个线程失去了CPU 时间片,而此时STW GC发现没有任何GC ROOTS与该对象关联起来,此时这个对象呗认为是垃圾并被回收了,之后CPU重新获得时间片后发现此时对象已经不存在了这时候程序就GG了。

    因此不是在任何时候都可以随便GC的,复杂的JVM早就考虑到这个问题,在JVM里面引入了一个叫安全点(Safe Point)的东西来避免这个问题。GC的目的是帮助我们回收不再使用的内存,在多线程环境下这种回收将会变得非常复杂,要安全地回收需要满足一下两个条件:

    1.堆内存的变化是受控制的,最好所有的线程全部停止。

    2.堆中的对象是已知的,不存在不再使用的对象很难找到或者找不到即堆中的对象状态都是可知的。

    为了准确安全地回收内存,JVM是在Safe Point点时才进行回收,所谓Safe Point就是Java线程执行到某个位置这时候JVM能够安全、可控的回收对象,这样就不会导致上所说的回收正在使用的对象。

    既然达到Safe Point就可以安全准确的GC,name如何到达Safe Point。

    说到这里就要提到如何使线程中断,一般有两种方式:主动式和被动式。主动式JVM设置一个全局变量,线程去按照某种策略检查这个变量一旦发现是Safe Point就主动挂起,被动式就是发个信号,例如关机、Control+C,带来的问题就是不可控,发信号的时候不知道线程处于什么状态。这里HostSop虚拟机采用的是主动式使线程中断。

    既然JVM使用的是主动性主动到达安全点,那么应该在什么地方设置全局变量呢?显然不能随意设置全局变量,进入安全点有个默认策略那就是:“避免程序长时间运行而不进入Safe Point”,程序要GC了必须要等线程进入安全点,如果线程长时间不进入安全点这样就比较糟糕了,因此安全点主要咋以下位置设置:

    1. 循环的末尾

    2. 方法返回前

    3. 调用方法的call之后

    4. 抛出异常的位置

    安全区域

    安全点完美的解决了如何进入GC问题,实际情况可能比这个更复杂,但是如果程序长时间不执行,比如线程调用的sleep方法,这时候程序无法响应JVM中断请求这时候线程无法到达安全点,显然JVM也不可能等待程序唤醒,这时候就需要安全区域了。

    安全区域是指一段代码片中,引用关系不会发生变化,在这个区域任何地方GC都是安全的,安全区域可以看做是安全点的一个扩展。线程执行到安全区域的代码时,首先标识自己进入了安全区域,这样GC时就不用管进入安全区域的线层了,线层要离开安全区域时就检查JVM是否完成了GC Roots枚举,如果完成就继续执行,如果没有完成就等待直到收到可以安全离开的信号。

    stw执行流程:

    Stop-The-Word说明:

    配置 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 参数,虚拟机会打印如下日志文件:

    日志分析:

    1. vmop:引发STW的原因,以及触发时间,本例中是GC。该项常见的输出有:<u>RevokeBias、BulkRevokeBias、Deoptimize、G1IncCollectionPause</u>。数字306936.812是虚拟机启动后运行的秒数。GC log可以根据该项内容定位Total time for which application threads…引发的详细信息。

    2. total :STW发生时,JVM存在的线程数目。

    3. initially_running :STW发生时,仍在运行的线程数,这项是Spin阶段的 时间来源

    4. **wait_to_block : **STW需要阻塞的线程数目,这项是block阶段的时间来源

    5. sync = spin + block + 其他。

    safepoint的执行分为四个阶段:

    1. Spin阶段。因为jvm在决定进入全局safepoint的时候,有的线程在安全点上,而有的线程不在安全点上,这个阶段是等待未在安全点上的用户线程进入安全点。

    2. Block阶段。即使进入safepoint,用户线程这时候仍然是running状态,保证用户不在继续执行,需要将用户线程阻塞。

    3. Cleanup。这个阶段是JVM做的一些内部的清理工作。

    4. VM Operation. JVM 执行的一些全局性工作,例如 GC, 代码反优化

    https://wiki.openjdk.java.net/display/HotSpot/PerformanceTechniques

    什么时候会触发Stop-The-Word?

    换句话说什么时候会触发进入安全点?

    • Garbage collection pauses(垃圾回收)

    • JIT相关,比如Code deoptimization, Flushing code cache

    • Class redefinition (e.g. javaagent,AOP代码植入的产生的instrumentation)

    • Biased lock revocation 取消偏向锁

    • Various debug operation (e.g. thread dump or deadlock check) dump 线程

    我们常见的一些比较直观的场景?

    Gc的一些场景如:

    1.老年代空间不足。

    2.永生代(jdk7)或者元数据空间(jdk8)不足。

    3.System.gc()方法调用。

    4.CMS GC时出现promotion failed和concurrent mode failure。

    5.YoungGC时晋升老年代的内存平均值大于老年代剩余空间。

    6.有连续的大对象需要分配。

    其他场景:

    • 1.Dump线程--人为因素。

    • 2.死锁检查。

    • 3.堆Dump--人为因素。

     

    JIT:

    Deoptimization

    这个世界是平衡的,有阴就有阳,有优化就有反优化。

    为什么优化了之后还要反优化呢?这样对性能不是下降了吗?

    通常来说是这样的,但是有些特殊的情况下面,确实是需要进行反优化的。

    下面是比较常见的情况:

    1. 需要调试的情况

    如果代码正在进行单个步骤的调试,那么之前被编译成为机器码的代码需要反优化回来,从而能够调试。

    2.代码废弃的情况

    当一个被编译过的方法,因为种种原因不可用了,这个时候就需要将其反优化。

    3.优化之前编译的代码

    有可能出现之前优化过的代码可能不够完美,需要重新优化的情况,这种情况下同样也需要进行反优化。

    代码反优化过程,如果不进行stw,线程继续执行,改变了变量的值,这时候进行反优化的值就有可能是错误的,所以要进行Stop the world;

    codeCache是什么?

    Java代码在执行时一旦被编译器编译为机器码,下一次执行的时候就会直接执行编译后的代码,也就是说,编译后的代码被缓存了起来。缓存编译后的机器码的内存区域就是codeCache,一块独立于Java堆之外的内存区域。除了JIT编译的代码之外,Java所使用的本地方法代码(JNI)也会存在codeCache中。

     

    怎么看codeCatch已满,满了怎么处理?

    jvm日志出现如下内容:

    Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled.

    此时的后果是:

    JIT编译器被停止了,并且不会被重新启动,此时会回归到解释执行;

    被编译过的代码仍然以编译方式执行,但是尚未被编译的代码就 只能以解释方式执行了。

     

    怎么解决上面的问题?

    获取当前codeCache的最大: jinfo -flag ReservedCodeCacheSize pid,通常在64 bit机器上默认是48m。

    设置codeCache的空间更大:

    -XX:ReservedCodeCacheSize= 更大空间

    启用codeCache的的回收机制:

    通过在启动参数上增加:-XX:+UseCodeCacheFlushing 来启用;

    打开这个选项,在JIT被关闭之前,也就是CodeCache装满之前,会在JIT关闭前做一次清理,删除一些CodeCache的代码;

    如果清理后还是没有空间,那么JIT依然会关闭。这个选项默认是关闭的;

     

    code cache调优:

    以client模式或者是分层编译模式运行的应用,由于需要编译的类更多(C1编译器编译阈值低,更容易达到编译标准),所以更容易耗尽codeCache。当发现codeCache有不够用的迹象时,可以通过启动参数来调整codeCache的大小。

    -XX:ReservedCodeCacheSize=256M

    那具体应该设置为多大合适呢? 根据监控数据估算,例如单位时间增长量、系统最长连续运行时间等。如果没有相关统计数据,一种推荐的设置思路是设置为当前值(或者默认值)的2倍。

    需要注意的是,这个codeCache的值不是越大越好。

    对于32位JVM,能够使用的最大内存空间为4g。这个4g的内存空间不仅包括了java堆内存,还包括JVM本身占用的内存、程序中使用的native内存(比如directBuffer)以及codeCache。如果将codeCache设置的过大,即使没有用到那么多,JVM也会为其保留这些内存空间,导致应用本身可以使用的内存减少。

    对于64位JVM,由于内存空间足够大,codeCache设置的过大不会对应用产生明显影响。

    在JDK 8中,提供了一个启动参数 -XX:+PrintCodeCache 在JVM停止的时候打印出codeCache的使用情况。其中max_used就是在整个运行过程中codeCache的最大使用量。可以通过这个值来设置一个合理的codeCache大小,在保证应用正常运行的情况下减少内存使用。

    Flushing code cache的时候,你不知道影响那部分代码的编译,如果不进行stw,代码被判定走jit,但是code cache被清理了,就没法继续编译;如果关闭jit,就是解释执行,效率很低,qps较大的时候,不能满足;

    我们一般debug程序的时候,只是关注其中的一部分代码,而且大部分情况下是设置断点,然后单步执行,而JIT的编译单位是class,只要我们执行了class里面的代码,JIT就会对整个class进行编译,而我们实际执行的代码一般都是其中的一部分代码,所以从整个时间效率上来看,采用JIT反而更费时间。也就是说在JVM远程调试这个事情上,禁用JIT(只使用转译器,解释一行执行一条)更合理,所以通过-Djava.compiler=NONE来禁止JIT。

     

    Biased lock revocation:

     

    https://segmentfault.com/a/1190000017408847

     

    http://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html#Thread%20Management|outline

    锁撤销

    由于偏向锁失效了,那么接下来就得把该锁撤销,锁撤销的开销花费还是挺大的,其大概的过程如下:

    1. 在一个安全点停止拥有锁的线程。

    2. 遍历线程栈,如果存在锁记录的话,需要修复锁记录和Markword,使其变成无锁状态。

    3. 唤醒当前线程,将当前锁升级成轻量级锁。所以,如果某些同步代码块大多数情况下都是有两个及以上的线程竞争的话,那么偏向锁就会是一种累赘,对于这种情况,我们可以一开始就把偏向锁这个默认功能给关闭

     

    Class redefinition (e.g. javaagent)

     

    javaagent: https://segmentfault.com/a/1190000016601560

    Java 动态调试技术原理及实践:https://www.ctolib.com/topics-142967.html

     

    Gc的时候,哪里用到STW?

    目前所有的新生代gc都是需要STW的

    Serial:单线程STW,复制算法

    ParNew:多线程并行STW,复制算法

    Parallel Scavange:多线程并行STW,吞吐量优先,复制算法

    G1:多线程并发,可以精确控制STW时间,整理算法

    CMS:里面有一个并发标记阶段是不需要stw的,和用户线程一起执行,但是初始标记和重新标记需要stw。

     

     

    在新生代进行的GC叫做minor GC,在老年代进行的GC都叫major GC,Full GC同时作用于新生代和老年代。在垃圾回收过程中经常涉及到对对象的挪动(比如上文提到的对象在Survivor 0和Survivor 1之间的复制),进而导致需要对对象引用进行更新。为了保证引用更新的正确性,需要stw;

    G1收集器运作过程

       

    G1 GC Phase

    Type

    Initial Mark

    Stop the world Phase

    Root Region Scanning

    Concurrent Phase

    Concurrent Marking

    Concurrent Phase

    Cleanup

    Stop the world Phase

    Remark

     

    Stop the world Phase

    不计算维护Remembered Set的操作,可以分为4个步骤(与CMS较为相似)。

    (A)、初始标记(Initial Marking)

    仅标记一下GC Roots能直接关联到的对象;

    且修改TAMS(Next Top at Mark Start),让下一阶段并发运行时,用户程序能在正确可用的Region中创建新对象;

    需要"Stop The World",但速度很快;

    (B)扫描(Root Region Scanning)、并发标记(Concurrent Marking)

    进行GC Roots Tracing的过程;

    刚才产生的集合中标记出存活对象;

    耗时较长,但应用程序也在运行;

    并不能保证可以标记出所有的存活对象;

    (C)、最终标记(Final Marking)

    为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录;

    上一阶段对象的变化记录在线程的Remembered Set Log;

    这里把Remembered Set Log合并到Remembered Set中;

     

    需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短;

    采用多线程并行执行来提升效率;

    (D)、筛选回收(Live Data Counting and Evacuation)

    首先排序各个Region的回收价值和成本;

    然后根据用户期望的GC停顿时间来制定回收计划;

    最后按计划回收一些价值高的Region中垃圾对象;

     

    回收时采用"复制"算法,从一个或多个Region复制存活对象到堆上的另一个空的Region,并且在此过程中压缩和释放内存;

    可以并发进行,降低停顿时间,并增加吞吐量;

    G1收集器运行示意图如下:

    CMS收集器:

    并发标记清理(Concurrent Mark Sweep,CMS)收集器也称为并发低停顿收集器(Concurrent Low Pause Collector)或低延迟(low-latency)垃圾收集器;

       

    CMS GC Phase

    Type

    Initial Mark

    Stop the world Phase

    Concurrent Mark

    Concurrent Phase

    Concurrent Preclean

    Concurrent Phase

    Concurrent Abortable Preclean

    Concurrent Phase

    Final Remark

    Stop the world Phase

    Concurrent Sweep

    Concurrent Phase

    Concurrent Reset

    Concurrent Phase

    (A)、初始标记(CMS initial mark)

    仅标记一下GC Roots能直接关联到的对象;

    速度很快;

    但需要"Stop The World";

    (B)、并发标记(CMS concurrent mark)

    进行GC Roots Tracing的过程;

    刚才产生的集合中标记出存活对象;

    应用程序也在运行;

    并不能保证可以标记出所有的存活对象;

    (C)、重新标记(CMS remark)

    为了修正并发标记期间因用户程序继续运作而导致标记变动的那一部分对象的标记记录;

    需要"Stop The World",且停顿时间比初始标记稍长,但远比并发标记短;

    采用多线程并行执行来提升效率;

    (D)、并发清除(CMS concurrent sweep)

    回收所有的垃圾对象;

     

     

    GC日志,查看stw耗时时间:

    Full GC:

    2020-06-12T16:39:37.728-0800: 88.808: [Full GC [PSYoungGen: 116544K->12164K(233024K)[PSOldGen: 684832K->699071K(699072K)] 801376K->711236K(932096K)[PSPermGen: 2379K->2379K(21248K)], 3.4230220 secs] [Times: user=3.40 sys=0.02, real=3.42 secs]

    Major GC:

    Phase 1: Initial Mark.

    2020-06-12T16:23:07.321-0200: 64.425: [GC (CMS Initial Mark) [1 CMS-initial-mark: 10812086K(11901376K)] 10887844K(12514816K), 0.0001997 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

    Phase 2: Concurrent Mark.

    2020-06-12T16:23:07.357-0200: 64.460: [CMS-concurrent-mark: 0.035/0.035 secs] [Times: user=0.07 sys=0.00, real=0.03 secs]

    Phase 3: Concurrent Preclean.

    2020-06-12T16:23:07.373-0200: 64.476: [CMS-concurrent-preclean: 0.016/0.016 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

    Phase 4: Concurrent Abortable Preclean.

    2020-06-12T16:23:08.446-0200: 65.550: [CMS-concurrent-abortable-preclean: 0.167/1.074 secs] [Times: user=0.20 sys=0.00, real=1.07 secs]

    Phase 5: Final Mark.

    2020-06-12T16:23:08.447-0200: 65.550: [GC (CMS Final Remark) [YG occupancy: 387920 K (613440 K)]65.550: [Rescan (parallel) , 0.0085125 secs]65.559: [weak refs processing, 0.0000243 secs]65.559: [class unloading, 0.0013120 secs]65.560: [scrub symbol table, 0.0008345 secs]65.561: [scrub string table, 0.0001759 secs][1 CMS-remark: 10812086K(11901376K)] 11200006K(12514816K), 0.0110730 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]

    Phase 6: Concurrent Sweep.

    2020-06-12T16:23:08.485-0200: 65.588: [CMS-concurrent-sweep: 0.027/0.027 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]

    Phase 7: Concurrent Reset.

    2020-06-12T16:23:08.497-0200: 65.601: [CMS-concurrent-reset: 0.012/0.012 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

    Minor GC:

    2020-06-12T11:10:34.831+0530:0.208 [ GC(AllocationFailure) 0.208 [ParNew:33280K->4160K(37440K), 0.0627725 secs]33280K->18152K(120768K), 0.0628398 secs] [Times: user=0.18 sys=0.01, real=0.07 secs]

     

    • Real is wall clock time (time from start to finish of the call). This is all elapsed time including time slices used by other processes and time the process spends blocked (for example if it is waiting for I/O to complete).

    • User is the amount of CPU time spent in user-mode code (outside the kernel) within the process. This is only actual CPU time used in executing the process. Other processes, and the time the process spends blocked, do not count towards this figure.

    • Sys is the time spent in OS calls or waiting for system event i,e the amount of CPU time spent inside the kernel within the process (kernel-mode). This means executing CPU time spent in system calls within the kernel, as opposed to library code, which is still running in user-space. Like user, this is only CPU time used by the process.

    time nc -z www.java2depth.com

    user time 是指程序使用的用户态的时间,一般是不变的。sys time是程序使用的内核态的时间,如果同时运行多个程序,系统会花时间在来回调度和切换进程。运行多个副本时,会出现sys time增加的现象。

     

    stw带来的问题,以及相关优化的方式?

    1.分析 -XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1 产生的日志信息基本上STW的原因都是RevokeBias或者BulkRevokeBias。这个是撤销偏向锁操作,虽然每次暂停的 时间很短,但是特别频繁出现也会很耗时。

    一些高并发的系统中,禁掉JVM偏向锁优化,可以提升系统的吞吐量。禁用偏向锁的参数为: -XX:-UseBiasedLocking

     

    源码看撤销偏向锁的过程:https://cloud.tencent.com/developer/article/1460325

    Hotspot 偏向锁BiasedLocking 源码解析:https://blog.csdn.net/qq_31865983/article/details/105003612

     

    展开全文
  • 虚拟机的解决方法就是在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和...

    小伙伴还记得上一篇中我们留下的一个问题吗?什么是停顿类型!经过上几章的学习,我们知道垃圾回收首先是要经过标记的。对象被标记后就会根据不同的区域采用不同的收集方法。看上去很完美的一件事情,其实并不然。

    大家有没有想过一件事情,当虚拟机完成两次标记后,便确认了可以回收的对象。但是,垃圾回收并不会阻塞我们程序的线程,他是与当前程序并发执行的。所以问题就出在这里,当GC线程标记好了一个对象的时候,此时我们程序的线程又将该对象重新加入了“关系网”中,当执行二次标记的时候,该对象也没有重写finalize()方法,因此回收的时候就会回收这个不该回收的对象。

    虚拟机的解决方法就是在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和清除。

    这些特定的指令位置主要在:

    1、循环的末尾

    2、方法临返回前 / 调用方法的call指令后

    3、可能抛异常的位置

    找到“GC Roots”也是要花很长的时间,然而这里又有新的解决方法,就是通过采用一个OopMap的数据结构来记录系统中存活的“GC Roots”,在类加载完成的时候,虚拟机就把对象内什么偏移量上是什么类型的数据计算出来保存在OopMap,通过解释OopMap就可以找到堆中的对象,这些对象就是GC Roots。而不需要一个一个的去判断某个内存位置的值是不是引用。这种方式也叫准确式GC。

    回到最开始的问题,那个停顿类型就是刚刚所说的STW,至于有GC和Full GC之分,还有Full GC (System)。个人认为主要是Full GC时STW的时间相对GC来说时间很长,因为Full GC针对整个堆以及永久代的,因此整个GC的范围大大增加;还有就是他的回收算法就是我们之前说过的“标记--清楚--整理”,这里也会损耗一定的时间。所以我们在优化JVM的时候,减少Full GC的次数也是经常用到的办法。

    本文篇幅较短,为下一章要讲的收集器打下基石,各位只要知道GC之前还有STW这一步骤和知道OopMap以及安全点的存在即可。

    展开全文
  • stop the world

    2019-01-07 18:26:30
    危害
  • Stop the world

    千次阅读 2018-03-02 14:53:16
    我们都知道,在虚拟机进行GC的时候会需要让所用的线程都停止工作,等待他GC完成,那么他是如何保证所有线程全部都停止工作的呢? 只有当所有线程都跑到了安全点,或者进入安全区域之后,才会进行GC ...
  • 展开全部JVM有个叫做“安全点”和“32313133353236313431303231363533e4b893e5b19e31333433623136安全区域”的东西,在发生GC时,所有的线程都会执行到“安全点”停下来。在需要GC的时候,JVM会设置一个标志,当线程...
  • 虚拟机的解决方法就是在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和...
  • Stop The World

    2017-04-07 23:56:00
    import java.util.HashMap;/** * Created by wb-xxd249566 on 2017/4/5. * -Xmx1g -Xms1g -Xmn512k -XX:+UseSerialGC -Xloggc:gc.log -XX:+PrintGCDetails */public class StopWorldTest { public static class M...
  • JVM stop the world

    2020-04-24 09:50:18
    Total time for which application threads were stop 超级长时间,这行日志代表什么,以及为什么时间会这么长 ? 二、日志的含义 Total time for which application threads were stopp 2.81 seconds,Stopping ...
  • 每日一面 - JVM 何时会 Stop the world

    万次阅读 2021-01-17 08:22:49
    这个定时主要是为了一些没必要立刻 Stop the world 的任务执行,可以设置-XX:GuaranteedSafepointInterval=0关闭这个定时,我推荐是关闭。 由于 jstack,jmap 和 jstat 等命令,也就是 Signal Dispatcher 线程要处理...
  • 什么是 STOP THE WORLD

    2020-03-25 20:14:28
    当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记和清除。 在执行垃圾收集算法时,Java应用程序的其他所有线程都...
  • JVM进阶(八)——Stop The World

    万次阅读 多人点赞 2017-01-21 17:30:49
    JVM进阶(八)——Stop The World  小伙伴还记得上一篇中我们留下的一个问题吗?什么是停顿类型!经过前几章的学习,我们知道垃圾回收首先是要经过标记的。对象被标记后就会根据不同的区域采用不同的收集方法。看...
  • 一、遇到的问题Total time for which application threads were stop 超级长时间,这行日志代表什么,以及为什么时间会这么长 ?二、日志的含义Total time for which application threads were stopp 2.81 seconds,...
  • 这些问题一般和 SafePoint 还有 Stop the World 有关。 什么是 SafePoint?什么是 Stop the world?他们之间有何关系? 我们先来设想下如下场景: 当需要 GC 时,需要知道哪些对象还被使用,或者已经不被使用可以...
  • JAVA Stop The World

    2018-08-16 16:37:14
     虚拟机的解决方法就是在一些特定指令位置设置一些“安全点”,当程序运行到这些“安全点”的时候就会暂停所有当前运行的线程(Stop The World 所以叫STW),暂停后再找到“GC Roots”进行关系的组建,进而执行标记...
  • Stop-The-World对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World”的时间。 不同垃圾收集器的Stop-The-World情况,Serial、Parallel和CMS收集器均存在不同程度的Stop-The-Word情况;而即便是...
  • 1 SafePoint 1.1 什么是SafePoint Safepoint是java代码中一个线程可能暂停执行的一个...在接收到JVM的进入Stop The World 的信息,在safepoint上,用户线程会被挂起。如果JNI代码想要访问在安全点上的用户线程,...
  • "stop the world" assertion

    2021-01-10 02:05:17
    - jshint running in testsuite could stop any further tests from running - enviroment test could prevent tests to run, e.g. don't run anything if page is loaded via file: protocol</p><p>该提问来源...
  • JVM GC中Stop the world案例实战

    万次阅读 2016-08-31 00:00:34
    GC中Stop the world案例实战
  • Stop-The-World

    2020-08-05 10:36:02
    Stop-The-World对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World”的时间。 不同垃圾收集器的Stop-The-World情况,Serial、Parallel和CMS收集器均存在不同程度的Stop-The-Word情况;而即便是...
  • stop the world 安全点

    2019-04-09 20:09:37
    查看停顿–安全点停顿日志 要查看安全点停顿,可以打开安全点日志,通过设置JVM参数 -XX:+PrintGCApplicationStoppedTime 会打出系统停止的时间,添加-XX:+PrintSafepointStatistics -XX:...
  • 在某些垃圾回收器算法中,“停止世界”(Stop the World: STW,下同)是跟踪内存使用最重要的阶段,它会停止程序的执行,以扫描内存使用,并添加写障碍。让我们回顾一下它在内部如何工作,以及它可能面临的潜在问题...
  • Stop The World(STW)

    2017-05-02 13:14:24
    "stop-the-world" 机制简称STW,即,在执行垃圾收集算法时,Java应用程序的其他所有除了垃圾收集帮助器线程之外的线程都被挂起 Java中一种全局暂停的现象 全局停顿,所有Java代码停止,native代码可以执行,但...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,643
精华内容 1,457
关键字:

stopworld