小游戏java源码-GC不是也进入了一个安全点吗?这个关于安全点的JVM源代码有点有趣

如果你熟悉并发编程,你觉得下面这段代码的执行结果怎么样?

如果我说,执行过程是:t1 线程

和 t2 线程仍然执行 num 累加操作,即

主线程休眠 1 秒、1 秒,此时唤醒复制 num 值,t1 线程和 t2 线程继续执行 add 1 操作,直到完成 2 亿次累加操作

你赞成吗?

我的猜测似乎没问题,但实际的运行效果证明我错了,这是运行 GIF:

从运行图片中可以看到,运行代码后,你会发现实际的执行结果是这样的:

1 秒后,主线程不会立即复制 num,而是等待 t1 和 t2 分别执行 2 亿次累加操作退出循环,然后再复制 num 的值。

这个结果不是想象的。我基于 JDK1.8 运行,你也可以试试。

为什么?

答案是:

JVM 希望执行一个操作,使所有线程单步进入安全点,但由于 JIT 对可数循环的转换优化,t1 和 t2 线程必须等到循环运行后才能单步进入安全点,因此主线程仍然等待 t1 和 t2,无法输出 num 的值。

可数循环:(int i = 0; i < 100000000; i++) {...} 的形式 的循环称为可数循环

简单地说:主线程正在等待 t1 和 t2 线程进入安全状态

本文从我当时的一个问题开始:JVM做了什么来使线程安全?

GC发生了吗?

GC发生了吗?

首先,在代码上方没有创建要申请视频内存的对象。

其次,加上 -XX:-PrintGC 也没有复制 GC 日志。

第三,执行 jstat 命令,通过输出日志可以看到,在 JVM 运行过程中各个内存区域没有变化,没有发生 GC。

因此,排除了由于发生GC而进入安全点的需要。

问题变成了:GC 没有发生,当所有线程安全时,您需要所有线程做什么?

安全点日志

添加 -XX:+打印安全点统计参数,以便在程序执行时复制安全点的相关日志。

可以看出,这段代码的执行一共进行了三次到安全点。

其中第二个,EnableBiasedLock,是JVM延迟开放偏置锁的操作,也比较有意思,但不是本文的重点,下次再讲。

我们的重点是第一个无 VM 操作操作。单独取出此日志,并在参数说明中添加英文说明:

总结一下:

JVM不想执行任何虚拟机操作小游戏java源码,此操作需要线程单步进入安全点,有一个整个周期共 12 个线程,有 2 个正在运行的线程,等待这两个线程步入安全点需要

5037 毫秒,等待这 2 个线程步入安全点并阻塞。

找到这两个线程也很简单,单步进入安全点是不是需要超过 5000 微秒,我会添加参数,让单步进入安全点需要 5000 毫秒以上的线程超时。

然后添加 -XX

:+SafePointTimeout 和 -XX:SafepointTimeoutDelay=5000 个参数来执行代码。

哦,是的,这不是 t1 和 t2 线程吗?这个

结果也是意料之中的,我们的重点是这个没有虚拟机操作到底是什么?为什么主线程等了这么久?

源代码定位此 VM 操作的名称称为 no VM 操作,翻译成英文不是 VM 操作

,连接到 不是 VM 操作 VM 操作?

不是 VM 操作的操作如何将全局移动到安全点?

那么它到底是什么呢?知识盲点!

Microsoft百度上的一顿饭没有找到更令人信服的答案。

所以,我决定看看JVM的源代码。

全局搜索 JVM 源代码上没有虚拟机操作小游戏java源码,发现只有 safepoint.cpp 具有此信息。

点击看了看,果然会突然找到复制日志所在的位置,就是这个SafepointSync::p rint_statistics()方法。

有一行关键代码:

_vmop_type == -1 ? 
    "no vm operation" : 
    VM_Operation::name(sstats->_vmop_type)

这是一个三目操作:如果_vmop_type等于 -1,则打印的安全点日操作类型列将输出任何 VM 操作。

此_vmop_typen是结构 SafePointStats 的成员,该结构具体表示触发安全点的 VM 操作类型。

那么哪些操作类型将_vmop_type设置为 -1?

我在打开安全点的方式上方找到了答案:

如果不是 VM 操作触发的安全点风暴,则此时_vmop_type将设置为 -1。

也就是说,还有其他情况也可以触发安全点风暴,让所有线程步入安全点。

然后,我们只需要找到安全点风暴触发点对应的代码即可。一个

个找个文件太难了,改变思路,要想踏入安全点,一定要叫路步入安全点。

到达安全点的方法是 safeSync::begin() 方法在 safepoint.cpp。

我们只需要全局搜索调用 SafeSync::begin() 的位置,它应该能够找到与安全点风暴触发器对应的代码。

全局搜索发现,只有 vmThread .cpp 中有调用,而 vmThread .cpp封装了与 VMThread 相关的技能。

VM读取

什么是VMThread?

VMThread 是由 JVM 本身启动的内部线程,主要用于协调其他线程到达安全点并执行 VM 操作。

VM操作的概念在整篇文章中已经多次提到,那么究竟什么是VM操作呢?

我们比较熟悉的CMS的初始和最终标签是虚拟机操作,线程转储、线程挂起、偏置锁吊销等都是虚拟机操作。

虚拟机操作的类型很多,JVM对应的源代码在vm_operations.hpp定义的宏VM_OPS_DO中。

宏VM_OPS_DO中的每个 VM 操作基本上都有一个单独的泛型来实现。

VMThread 有一个 VMOperationQueue 队列,用于存储逐个连接的 VM 操作。

VM的方式读取

循环 VM 操作称为 VMThread::loop() 方法。

loop() 方法是 VMThread 的核心技术,它不断从 VMOperationQueue 队列中获取挂起的 VM 操作,然后为每个 VM 操作调用特定于实现的 evaluate() 方法来执行不同的逻辑。

这里用的是策略模式,VMThread执行逻辑是固定的,只负责调度,每个虚拟机操作都需要根据需求实现evaluate()方法。

答案出现了

我们寻找没有 vm 操作的原因是 VMThread 的 loop() 方法。

从源码可以看出,当虚拟机操作为空时,只要满足以下3个条件,也会步入安全点:

VMThread 处于正常状态,专为单步进入安全点之间的间隔而设计,无论 SafepointALot 为真还是需要清除

VMThread 肯定会正常运行,因此可以满足条件 1。

使用 java -XX:+UnlockDiagnostics VMOptions -XX:+PrintFlagsFinal 2>&1 | grep Safepoint 命令查看 JVM 的安全点缺省参数,并发现缺省情况下保证安全间隔为 1 秒,因此也可以满足条件 2。

对于条件 3,

SafepointALot 默认为 false,因此如果满足条件 3,则 SafepointSynchronize::is_cleanup_needed() 必须为 true。

单击内部以查看其运行情况:

通过跟踪代码,您可以看到 SafeSync::is_cleanup_needed() 确定 StubQueue 中是否存在存根缓存。

那么什么是存根队列?什么是存根?

这涉及到JVM的模板类库和编译器,由于篇幅所限,下次有机会我会继续深入挖掘。

我可以用一句话来概括就是JVM执行过程中的编译解释代码缓存。

清理存根可以简单地理解为清除代码缓存。

那就是

比如说,当 JVM 正常运行时,如果设置了一个间隔进入安全点,它将确定是否有代码缓存需要每隔一段时间清除,如果有,它将步入安全点。

此触发条件不是 VM 操作,因此_vmop_type将是

设置为 -1,输出日志将被复制到对应的 no VM 操作中,也就是我们看到的安全点日志。

文章开头的代码执行效果,主线程还在等待 t1 和 t2 进入安全点,触发了这个条件。

再次验证推测

返回并查看本文开头的代码,并设置单步执行到安全点之间的间隔

通过添加 -XX:保证安全点间隔 = 0 到 0,即关闭单步进入安全点的计时,并查看代码如何运行。-XX

:保证安全点间隔是一个诊断参数,需要通过添加 -XX:+解锁诊断 VMOptions 参数来解锁确定参数。

从运行结果可以看出,关闭设置步入安全点一段时间后,主线程休眠 1 秒后,不再需要等待 T1 和 T2 线程完成循环,休眠后立即复制此时的 num 值。

这个运算结果也再次验证了我们的结论。

每隔1秒步入安全点的设置仍然有其效果,建议您不要触摸它。

-XX:保证安全点间隔是一个确认参数,不建议在线使用。

从网上的文献来看,关闭这个参数还可能导致一些未知的错误,我没有遇到过,也不知道是真是假。简而言之,对

在线环境保持谨慎总是正确的,如果你不熟悉底层的JVM,我建议不要接触它。

有趣的笔记

知识点的分享到此结束,分享一件有趣的事情。

当我追踪到时

JVM源代码,我注意到编译StubQueue的作者留下了这样的评论:

我会润色和翻译:当你无法证明你没事时,不要用我的代码到处跑,这比你想象的要好得多。见

不见,这就是师傅的骄傲和自信!

另一方面,平时给代码写注释的时候,我只敢写进去:如果你发现我的代码有bug,请帮我修复,谢谢。

从写笔记的自豪和自信中,你可以看到我和前辈们有多么不同。

一定要来,以后还能写出这么帅气的笔记!

游戏C源代码下载

是一个非常热门的话题,随着游戏行业的不断发展,越来越多的游戏开发者和游戏爱好者开始关注游戏C源码下载。在本文中,我们将解释游戏C源码下载的相关问题,包括游戏C源码下载的意义,游戏C源码的下载方式,以及游戏C源码下载的注意事项。

一、游戏C源码下载的意义游戏C源代码

下载对于游戏开发者来说极为重要,因为游戏C源代码是游戏开发的基础。游戏C源代码包含游戏的核心代码,游戏开发者可以学习游戏C源代码,深入了解游戏的运行原理,从而更好地开发游戏。此外c游戏源码下载,游戏C源码也是游戏爱好者学习游戏***的重要资源,通过学习游戏C源码c游戏源码下载,游戏爱好者可以了解游戏的流程,提高自己的游戏***能力。

二、下载游戏C源代码的方式

下载游戏 C 源代码的方法有很多种,下面我们将介绍几种常用方法。

1. 游戏官方网站

很多游戏开发者会在游戏官方上发布游戏C源代码

网站,所以游戏官网是下载游戏C源代码最常见的方式之一。如果要下载一款游戏的C源码,可以先去游戏官网查找相关信息。

2. 开源社区

开源社区是下载游戏C源代码

小游戏java源码-GC不是也进入了一个安全点吗?这个关于安全点的JVM源代码有点有趣

非常重要的方式,许多游戏开发者会在开源社区发布他们的游戏C源代码,供其他开发者和爱好者学习和使用。目前比较有名的开源社区有Github、SourceForge等。

3. 游戏峰会

游戏峰会也是下载游戏C源码

小游戏java源码-GC不是也进入了一个安全点吗?这个关于安全点的JVM源代码有点有趣

的好方法,很多游戏开发者会在游戏峰会上发布自己的游戏C源码,供其他开发者和爱好者下载学习。如果要下载游戏的C源码,可以在相关游戏峰会上查找。

3. 下载游戏C源代码的注意事项

下载游戏C源代码时,需要注意以下几点。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 游戏源码 小游戏java源码-GC不是也进入了一个安全点吗?这个关于安全点的JVM源代码有点有趣 https://www.wkzy.net/game/131970.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务