BTrace 和 Byteman
BTrace 和 Byteman 都支持运行时注入, BTrace 底层是 JVM Agent 字节码注入. Byteman 还没用过. 这里记录一些常用的东西.
BTrace 的官方例子: https://github.com/btraceio/btrace/tree/master/btrace-dist/src/main/resources/samples
Byteman 官方网站:
https://byteman.jboss.org/
BTrace 和 Byteman 都支持运行时注入, BTrace 底层是 JVM Agent 字节码注入. Byteman 还没用过. 这里记录一些常用的东西.
BTrace 的官方例子: https://github.com/btraceio/btrace/tree/master/btrace-dist/src/main/resources/samples
Byteman 官方网站:
https://byteman.jboss.org/
对于 Java 应用, 对于内存的占用, 主要是Java堆, 通常我们为了性能考虑, 会对堆设置最大值, 否则 JVM 就会根据它锁了解的系统参数, 设置一个可能的最大值. 除了堆之外, 其实还有好几部分, 也可能占用不少内存. 比如元数据区(老年代), 线程栈, 编译后的代码, GC 程序, 编译器, JVM符号表之类的. 这里可以通过添加启动参数: -XX:NativeMemoryTracking=summary or -XX:NativeMemoryTracking=detail 来追踪原生内存的占用. 比如: 
比如上面的截图中, kiyomi 看到 Thread 部分 reserve 了 1052M, 已经提交占用了 1052M, 查看 thread dump, 发现现在大概有 1003 个线程, 基本每个线程占用 1M.
另外我们知道, 可以使用 Xss 参数设置每个线程栈的大小, 比如:
-Xss1m
-Xss1024k
-Xss1048576
上面的参数等同于:
-XX:ThreadStackSize
在 Linux 64 bit 上, 默认是 1MB. 从 Oracle 的官方文档: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
可以看到具体的说明.
从上面的文档可以看出, 每个栈在 64bit 的 Linux 上使用 1M, 可是我从另外一个机器上看到大概有 20K 个线程, 可是占用的内存并不是 20G. 于是我们看到 对于 IBM JDK 和 OpenJ9 JDK 它们都用 3 个参数:
更新:
根据这个 Bug 描述: https://bugs.openjdk.java.net/browse/JDK-8191369
应该是最大值, 之前的 NMT 简单的把 reserved 和 commited 置成 线程数 * Xss. 其实真正的 committed 可能并么有这么多, 虽然声明使用 1M 虚拟内存, 可能实际使用的物理内存页比较少. 所以 commited 比较少.
比如下面这个例子, 该 JVM 在一个 container 里面, 设置的最大可用内存是 16G, 已经使用 13.58G. 当前线程数是 11266 个, 堆大小设置的是 8G, 可以看到 Thread 通过 NMT 显示的是大概 10G, 总的 commit 已经大约 20G. 其实这个 Thread 占用的都是根据线程数 * Xss 算出来的, 都是根据最大值算出来的, 所以其实最后算出的 commit 是不准的. 根据 top 可得到该进程的 RSS 大概是 10G. 所以可以推算 Thread 占用少于 2 个 G.

修复之后的版本: 


异步 retry, 一开始 retry 的渐渐增多,到达 retry max 值之后, 渐渐较少
同数据中心agg, 共振从频率相同到不同:

内部推荐 联系 内部邮箱(base64 encoding): eGlhdGlhbkBlYmF5LmNvbQ==
以下是最新(2021/01/21)的职位列表:

