微信公众号:我其实目前没有耶
我是一个互联网公司的螺丝钉;
魔术师耿

JVM启动参数解析

  1. 疑问1 :生产环境上常用哪些JVM参数进行设置;

  2. 疑问2 :sh 启动jar 包并配置JVM参数样例怎么写;

  3. 疑问3 :dockerfile 怎么配置(seata 源码的 distribution中有他们的Dockerfile配置)

  4. 疑问4 :怎样在IDEA中搜索 jdk中的源码中的关键字

今天以seata服务的启动脚本seata-server.sh为例,进行分析 疑问1和疑问2

exec "$JAVACMD" $JAVA_OPTS -server -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="$BASEDIR"/logs/java_heapdump.hprof -XX:+DisableExplicitGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -Xloggc:"$BASEDIR"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced \-classpath "$CLASSPATH" \-Dapp.name="seata-server" \-Dapp.pid="$$" \-Dapp.repo="$REPO" \-Dapp.home="$BASEDIR" \-Dbasedir="$BASEDIR" \io.seata.server.Server \"$@"

其中

  • exec “$JAVACMD” $JAVA_OPTS -server -Xmx2048m -Xms2048m -Xmn1024m -Xss512k
  1. -server 第一个参数

  2. -Xmx2048m heap最大值

  3. -Xms2048m 堆初始值

  4. -Xmn1024m 不是堆最小值,而是新生代的大小(Sun官方推荐配置为整个堆的3/8)
    -Xss512k Stack Space栈空间的大小 设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。

    -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m

  5. -XX:SurvivorRatio=10 新生代分为Eden ,两块Survivor;计算Survivor大小, Eden:Survivor = 10,总大小为1024,10x+x+x=1024 x=85

  • -XX:-OmitStackTraceInFastThrow

    1、jvm启动参数中没有配置-XX:-OmitStackTraceInFastThrow,
    参数:OmitStackTraceInFastThrow字面意思是省略异常栈信息从而快速抛出。
    会引起error日志显示不全的问题
    该文章贴上了JDK那一段源码: https://blog.csdn.net/diaoliwei2/article/details/95966266

    2、OmitStackTraceInFastThrow和StackTraceInThrowable都默认为true。
    所以条件 (!StackTraceInThrowable || OmitStackTraceInFastThrow)为true,即JVM默认开启了Fast Throw优化。

    如果想关闭这个优化,配置-XX:-OmitStackTraceInFastThrow,StackTraceInThrowable保持默认配置-XX:+OmitStackTraceInFastThrow即可。JVM只对几个特定类型异常开启了Fast Throw优化,这些异常包括:
    
    : NullPointerException
    ArithmeticException
    ArrayIndexOutOfBoundsException
    ArrayStoreException
    ClassCastException

    3、下面写个循环调用空指针异常测试一下:在循环了2800多次后,还是能正常打出堆栈信息。再之后就简化了异常输出。

    4、修改JVM 启动参数,添加OmitStackTraceInFastThrow后。循环7000次异常信息还是正常输出。

  • -XX:-UseAdaptiveSizePolicy

    https://www.jianshu.com/p/7414fd6862c5
    AdaptiveSizePolicy(自适应大小策略) 是 JVM GC Ergonomics(自适应调节策略) 的一部分。
    如果开启 AdaptiveSizePolicy,则每次 GC 后会重新计算 Eden、From 和 To 区的大小,
    计算依据是 GC 过程中统计的 GC 时间、吞吐量、内存占用量。
    JDK 1.8 默认使用 UseParallelGC 垃圾回收器,该垃圾回收器默认启动了 AdaptiveSizePolicy。
    由 AdaptiveSizePolicy 引发的 GC 问题

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath="$BASEDIR"/logs/java_heapdump.hprof

  • -XX:+DisableExplicitGC ##禁止代码中显示调用GC

    java nio中的direct memory,那么使用-XX:+DisableExplicitGC一定要小心,存在潜在的内存泄露风险
    最佳编程实践是:暴露出释放资源的接口,程序员使用完成后,显示释放,这样就能够避免堆内存和非堆内存资源的同步释放的难题。
    RevisedObjectInHeap类中通过finalize()方法来释放堆外内存的,阅读源码可以发现,NIO中direct memory的释放并不是通过finalize(),
    而是通过sun.misc.Cleaner实现的
    cleaner = Cleaner.create(this, new Deallocator(base, cap));
    为什么不用finalize呢?因为finalize不安全,也非常影响性能。什么是sun.misc.Cleaner?这是个幽灵引用PhantomReference

-XX:+CMSParallelRemarkEnabled ## 并行标记

-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=75 ##设定CMS在对内存占用率达到75%的时候开始GC

UseCMSInitiatingOccupancyOnly如果不指定, 只是用设定的回收阈值CMSInitiatingOccupancyFraction,
则JVM仅在第一次使用设定值,后续则自动调整会导致上面的那个参数不起作用由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,
因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,
需要预留一部分空间提供并发收集时的程序运作使用

-Xloggc:"$BASEDIR"/logs/seata_gc.log ##
-verbose:gc

jvm参数-verbose:gc和-XX:+PrintGC有区别?
在官方文档中有说明:两者功能一样,都用于垃圾收集时的信息打印。
-verbose:gc
稳定版本
-XX:+PrintGC
非稳定版本,可能在未通知的情况下删除,在下面官方文档中是-XX:-PrintGC。
参见:http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html
因为被标记为manageable,所以可以通过如下三种方式修改:
1、com.sun.management.HotSpotDiagnosticMXBean API
2、JConsole
3、jinfo -flag
参见:http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

-Dio.netty.leakDetectionLevel=advanced

这句话报告有泄漏的发生,提示你用-D参数,把防漏等级从默认的simple升到advanced,
具体看到被泄漏的ByteBuf创建的地方和被访问的地方。https://www.iteye.com/news/30866Netty里四种主力的ByteBuf,
其中UnpooledHeapByteBuf 底下的byte[]能够依赖JVM GC自然回收;
而UnpooledDirectByteBuf底下是DirectByteBuffer,如Java堆外内存扫盲贴所述,除了等JVM GC,
最好也能主动进行回收;而PooledHeapByteBuf 和 PooledDirectByteBuf,则必须要主动将用完的byte[]/ByteBuffer放回池里,
否则内存就要爆掉。所以,Netty ByteBuf需要在JVM的GC机制之外,有自己的引用计数器和回收过程。一下又回到了C的冰冷时代,自己malloc对象要自己free。 但和C时代又不完全一样,内有引用计数器,外有JVM的GC,情况更为复杂。2. 引用计数器常识
计数器基于 AtomicIntegerFieldUpdater,为什么不直接用AtomicInteger?因为ByteBuf对象很多,如果都把int包一层AtomicInteger花销较大,而AtomicIntegerFieldUpdater只需要一个全局的静态变量。
所有ByteBuf的引用计数器初始值为1。
调用release(),将计数器减1,等于零时, deallocate()被调用,各种回收。
调用retain(),将计数器加1,即使ByteBuf在别的地方被人release()了,在本Class没喊cut之前,不要把它释放掉。
由duplicate(), slice()和order(ByteOrder)所创建的ByteBuf,与原对象共享底下的buffer,也共享引用计数器,所以它们经常需要调用retain()来显示自己的存在。
当引用计数器为0,底下的buffer已被回收,即使ByteBuf对象还在,对它的各种访问操作都会抛出异常。3.谁来负责Release在C时代,我们喜欢让malloc和free成对出现,而在Netty里,因为Handler链的存在,ByteBuf经常要传递到下一个Hanlder去而不复还,所以规则变成了谁是最后使用者,谁负责释放。另外,更要注意的是各种异常情况,ByteBuf没有成功传递到下一个Hanlder,还在自己地界里的话,一定要进行释放。3.1 InBound Message
在AbstractNioByteChannel.NioByteUnsafe.read() 处,配置好的ByteBufAllocator创建相应ByteBuf并调用 pipeline.fireChannelRead(byteBuf) 送入Handler链。根据上面的谁最后谁负责原则,每一个Handler对消息可能有三种处理方式对原消息不做处理,调用 ctx.fireChannelRead(msg)把原消息往下传,那不用做什么释放。
将原消息转化为新的消息并调用 ctx.fireChannelRead(newMsg)往下传,那必须把原消息release掉。
如果已经不再调用ctx.fireChannelRead(msg)传递任何消息,那更要把原消息release掉。
假设每一个Handler都把消息往下传,Handler并也不知道谁是启动Netty时所设定的Handler链的最后一员,所以Netty会在Handler链的最末补一个TailHandler,如果此时消息仍然是ReferenceCounted类型就会被release掉。
不过如果我们的业务Hanlder不再把消息往下传了,这个TailHandler就派不上用场。
3.2 OutBound Message
要发送的消息通常由应用所创建,并调用 ctx.writeAndFlush(msg) 进入Handler链。在每一个Handler中的处理类似InBound Message,最后消息会来到HeadHandler,再经过一轮复杂的调用,在flush完成后终将被release掉。3.3 异常发生时的释放
多层的异常处理机制,有些异常处理的地方不一定准确知道ByteBuf之前释放了没有,可以在释放前加上引用计数大于0的判断避免异常;有时候不清楚ByteBuf被引用了多少次,但又必须在此进行彻底的释放,可以循环调用reelase()直到返回true。4. 内存泄漏检测所谓内存泄漏,主要是针对池化的ByteBuf。ByteBuf对象被JVM GC掉之前,没有调用release()去把底下的DirectByteBuffer或byte[]归还到池里,会导致池越来越大。而非池化的ByteBuf,即使像DirectByteBuf那样可能会用到System.gc(),但终归会被release掉的,不会出大事。Netty担心大家一定会不小心就搞出个大新闻来,因此提供了内存泄漏的监测机制。Netty默认就会从分配的ByteBuf里抽样出大约1%的来进行跟踪。如果泄漏,会有如下语句打印:
引用LEAK: ByteBuf.release() was not called before it's garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option '-Dio.netty.leakDetectionLevel=advanced' or call ResourceLeakDetector.setLevel()这句话报告有泄漏的发生,提示你用-D参数,把防漏等级从默认的simple升到advanced,具体看到被泄漏的ByteBuf创建的地方和被访问的地方。
禁用(DISABLED) - 完全禁止泄露检测,省点消耗。
简单(SIMPLE) - 默认等级,告诉我们取样的1%的ByteBuf是否发生了泄露,但总共一次只打印一次,看不到就没有了。
高级(ADVANCED) - 告诉我们取样的1%的ByteBuf发生泄露的地方。每种类型的泄漏(创建的地方与访问路径一致)只打印一次。
偏执(PARANOID) - 跟高级选项类似,但此选项检测所有ByteBuf,而不仅仅是取样的那1%。在高压力测试时,对性能有明显影响。实现细节
每当各种ByteBufAllocator 创建ByteBuf时,都会问问是否需要采样,Simple和Advanced级别下,就是以113这个素数来取模(害我看文档的时候还在瞎担心,1%,万一泄漏的地方有所规律,刚好躲过了100这个数字呢,比如都是3倍数的),命中了就创建一个Java堆外内存扫盲贴里说的PhantomReference。然后创建一个Wrapper,包住ByteBuf和Reference。Simple级别下,wrapper只在执行release()时调用Reference.clear()把Reference清理掉,Advanced级别下则会记录每一个创建和访问的动作。当GC发生,还没有被clear()的Reference就会被JVM放入到之前设定的ReferenceQueue里。在每次创建PhantomReference时,都会顺便看看有没有因为忘记执行release()把Reference给clear掉,在GC时被放进了ReferenceQueue的对象,有则以 "io.netty.util.ResourceLeakDetector”为logger name,写出前面例子里的Error级别的日日志。顺便说一句,Netty能自动匹配日志框架,先找Slf4j,再找Log4j,最后找JDK logger

-classpath “KaTeX parse error: Undefined control sequence: \ at position 12: CLASSPATH" \̲ ̲ -Dapp.name="s…KaTeX parse error: Undefined control sequence: \ at position 3: " \̲ ̲ -Dapp.repo="REPO”
-Dapp.home=“KaTeX parse error: Undefined control sequence: \ at position 10: BASEDIR" \̲ ̲ -Dbasedir="BASEDIR”
io.seata.server.Server
“$@”

怎么优化tomcat的jvm参数

#修改JVM参数不直接修改 catalina.bat 和catalina.sh
在catalina.sh同级目录创建setenv.sh文件
在里面修改jvm参数

参看 https://www.iteye.com/blog/tdcq-1990666

#!/bin/sh
# ==================================================================
echo "start set env"
echo "$CATALINA_BASE"export CATALINA_OPTS="$CATALINA_OPTS -Xmx6144m -Xms4096m -Xmn2048m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$CATALINA_BASE/logs/ir_heapdump.hprof -XX:+DisableExplicitGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -Xloggc:$CATALINA_BASE/logs/ir_gc.log -verbose:gc "

以seata 的dockerfile 为例 分析疑问3

以检索 case Deoptimization::Reason_null_check: 为例

直接ctrl + h 搜索不到

请教博文作者DreamTHT , 说是在 这个文件里 https://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/share/opto/graphKit.cpp ,

牛掰, 我真不懂 c++

参看这篇博文https://blog.csdn.net/daerzei/article/details/79717717

  • 修改 点击菜单File --> Project Structure --> SDKs --> Sourcepath ,添加上本地源码解压吧路径C:\dev\jdk\jdk_source
    此时可以编辑源码添加注释

  • 修改 点击Setting --> Build,Execution,Deployment --> Debugger --> Stepping
    把Do not step into the classes中的ajva.*,javax.*取消勾选,其他的随意
    此时可以debug对源码打断点
    你好,大神

总结:

​ seata的这些参数设置还真是挺有讲究的呀…不愧是大厂的专家呀!!!

接下来任务很重呀,我要把自己之前学会了,又丢掉的东西写个博客记录下来了。

我说我是一个入行快10年的程序员,你敢新?该死该死。

在此把我珍藏了多年的第一篇博文,献给各位吧。 后续会不停更新。每周至少一篇吧。保底

我是魔术师耿,一个IT行业的搬砖人。

seata之jvm参数解析相关推荐

  1. JVM启动参数解析(转)

    JVM启动参数解析(转) (2010-03-17 19:45:19) 转载 标签: jvm 启动参数 it 分类:他山之石攻己之玉 dk1.4.2 JVM官方地址:http://java.sun.co ...

  2. JVM的内存结构,Eden和Survivor比例;JVM中一次完整的GC流程,对象如何晋升到老年代,说说你知道的几种主要的JVM参数;CMS 常见参数解析;.你知道哪几种垃圾收集器,各自的优缺点

    47.JVM的内存结构,Eden和Survivor比例 49.JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代,说说你知道的几种主要的JVM参数 50.-XX:+CMSScavengeBefo ...

  3. Tomcat 调优及 JVM 参数优化

    Tomcat 本身与 JVM 优化 Tomcat:调整Server.xml JVM:bat启动服务方式的话修改catalina.bat 服务式启动的话参考:http://www.cnblogs.com ...

  4. SpringMVC源码之参数解析绑定原理

    摘要 本文从源码层面简单讲解SpringMVC的参数绑定原理 SpringMVC参数绑定相关组件的初始化过程 在理解初始化之前,先来认识一个接口 HandlerMethodArgumentResolv ...

  5. JVM参数这样配置会让你的程序更快更强

    Java代码的编译,大家都知道是将.java代码编译成.class文件,这个过程是我们常说的编译,也称为前端编译.实际上Java程序的编译和运行不仅仅是将代码编译成.class文件就可以的,因为机器无 ...

  6. [Java]jvm参数选项中文文档

    本文是基于最新的SUN官方文档Java SE 6 Hotspot VM Options 编写的译文.主要介绍JVM中的非稳态选项及其使用说明.  为了让读者明白每个选项的含义,作者在原文基础上补充了大 ...

  7. python getopt使用_Python命令行参数解析模块getopt使用实例

    这篇文章主要介绍了Python命令行参数解析模块getopt使用实例,本文讲解了使用语法格式.短选项参数实例.长选项参数实例等内容,需要的朋友可以参考下 格式 getopt(args, options ...

  8. GC参数解析 UseSerialGC、UseParNewGC、UseParallelGC、UseConcMarkSweepGC

    参数解析 XX:+UseSerialGC -XX:+UseParNewGC -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseConcMarkSweep ...

  9. Java JVM参数调优配置

    JVM参数调优配置 Java虚拟机原理 Java内存结构 堆.栈.方法区概念区别 Java堆 Java栈 Java方法区 虚拟机参数配置 什么是虚拟机参数配置 堆的参数配置 设置最大堆内存 设置新生代 ...

最新文章

  1. FPGA内部电源管理详解
  2. 一些很酷的.Net技
  3. UITableView 局部刷新
  4. gitlab安装_Gitlab安装和配置教程(包括邮箱配置)
  5. NYOJ_269_VF
  6. 从DataTable高效率导出数据到Excel
  7. wpf 设置滑动条不能划到头_改善移动用户体验的7条原则
  8. jsp在mysql中删除数据_如何在jsp页面中删除数据库中的数据
  9. APIO2010巡逻(树上带权直径)
  10. audio.js – 随时随地,播放 HTML5 的声音
  11. python做excel自动化-python操作excel让工作自动化
  12. 搜寻Linux软件实用指南
  13. 【截屏篇】系统PrtSc
  14. 1237 -- 地盘划分
  15. gcc不是一个人在战斗,了解EFF文件格式
  16. python mpi4py multiprocessing_python基于multiprocessing的多进程创建方法
  17. Springboot集成百度地图实现定位打卡功能
  18. 图机器学习——5.9 图神经网络:图的增广
  19. iOS App处于后台/被杀死的状态仍可进行语言播报的实现 (适配iOS12.1 ,iOS15的本地通知功能)
  20. 关于JAVA的CLASSPATH

热门文章

  1. bcdedit添加linux引导,bcdedit修改uefi启动顺序
  2. 子平格局——戊癸化火格
  3. AE关键帧动画基础概念
  4. 如何使用启动盘PE桌面工具安装原版win7系统?
  5. Ubuntu 安装微信客户端
  6. 上网代理设置会被自动清空_关于代理被自动设置问题的排查
  7. 无线电通信相关重要指标测试
  8. 2022年1~8月语音合成(TTS)和语音识别(ASR)论文月报
  9. 成功在虚拟机里面安装MAC苹果系统
  10. 苹果放弃Intel基带应是大概率事件