47 VM.maxDirectMemory() 来自于哪里

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了47 VM.maxDirectMemory() 来自于哪里相关的知识,希望对你有一定的参考价值。

前言 

最近在 记一次 netty 内存泄露 中有还有一些问题 

比如 java.nio.ByteBuffer 中分配空间的时候, 直接内存 受限于 Bits.maxMemory 

在 netty 中的 PlatformDependent 中分配空间的时候, 直接内存 受限于 PlatformDependent.DIRECT_MEMORY_LIMIT 

然后 这两个 maxMemory 均是来自于 VM.maxDirectMemory, 那么 这个 VM.maxDirectMemory 又是怎么来的呢? 

这个问题之所以要探究一下, 是因为我之前配置 MaxDirectMemorySize 似乎是不生效 还是怎么的?, 但是 今天试了一下 又可以了 

以下代码截图基于 jdk8 

调试不到的代码?

来看一下 VM.maxDirectMemory, 取自于 属性 directMemory 

然后 我们看一下 这个字段初始化的地方 

1. 它是有一个默认值 

2. 是 VM.saveAndRemoveProperties 里面的初始化代码 

然后 我们打上断点查看, 发现 初始化部分的代码 这里居然断点停不了? 这是一个很神奇的事情 

但是 获取 maxMemorty 的时候, maxMemory 已经是一个正常的我们期望的数值了 

但是 它是在哪里初始化的? 难道还有其他地方 ? 

基于 HotspotVM 的调试  

呵呵 java 层面看不到什么情况, 只能来 vm 调试一下了 

可以看到 System.initPhase1 里面某一个步骤调用了 Runtime.maxMemory 

System.initPhase1 是 jdk9 中的初始化方法, 对应于 jdk8 是 System.initializeSystemClass 

输出一下当前线程的堆栈信息 

	at java.lang.Runtime.maxMemory(java.base/Native Method)
	at jdk.internal.misc.VM.saveAndRemoveProperties(java.base/VM.java:190)
	at java.lang.System.initPhase1(java.base/System.java:1949)

jdk 的 VM 里面 190 行对应于初始化 directMemory, 这个就证明了 上面我们不确定的东西 

VM.maxMemorty 的初始化确实是在 VM.saveAndRemoveProperties 里面初始化的 

另外我们看一下 默认值, 取自 Runtime.maxMemorty 

Runtime.maxMemorty 的实现是取自 堆空间的大小 

为什么 VM.saveAndRemoveProperties 调试不到? 

调试的文章, 可以参考 调试启动 suspend=y 的情况下, jps 得到 -- main class information unavailable

我们看一下 jvmti 暴露 jdwp 服务初始化的地方, 这里 bagEnumrateOver 是 bind 端口, 接受 jdwp 服务的地方 

仔细看 这里是在 Threads::create_vm 3800 行的地方, 而上面调用 System.initPhase1/initializeSystemClass 是在 Threads::create_vm 3700 行的地方 

此时 jdwp 相关服务尚未暴露, 因此是 客户端是感知不到的 

如何配置 VM.maxDirectMemory ?

从上面 VM 的代码里面我们可以看到 读取的配置是 sun.nio.MaxDirectMemorySize 

那么可以直接配置 sun.nio.MaxDirectMemorySize 嘛? 答案是否定的  

VM.saveAndRemoveProperties 传入的 properties 来自于这里 

1. Arguments::system_properties 里面是没有 "sun.nio.MaxDirectMemorySize" 属性的

2. 另外 下面有一段关于 sun.nio.MaxDirectMemorySize 和 MaxDirectMemorySize 的特殊处理, 检查是否有 MaxDirectMemorySize 参数, 如果没有, 设置 sun.nio.MaxDirectMemorySize 为 -1, 否则 设置 MaxDirectMemorySize 的值到 sun.nio.MaxDirectMemorySize

本地内存使用可以超过 VM.maxMemorty 配置的吗?

这个答案是 肯定的 

不管是 java.nio.DirectBuffer 分配空间, 还是 PlatformDependent 分配空间 

对于 maxMemorty 的限制都是逻辑上的限制 

如果 我设置 MaxDirectMemorySize 为 32M, java.nio.DirectBuffer 分配 29M, PlatformDependent 分配 29M, 也是可以的 

呵呵 算是 tricks 吧 

 参考 

  记一次 netty 内存泄露   调试启动 suspend=y 的情况下, jps 得到 -- main class information unavailable

以上是关于47 VM.maxDirectMemory() 来自于哪里的主要内容,如果未能解决你的问题,请参考以下文章

Netty-DirectByteBuffery源码分析

async/await 来处理异步/同步

如何基于这个请求http://www.webxml.com.cn/WebServices/WeatherWebService.asmx所提供的接口来获取东西?

使用ffmpeg能否将rtsp的流转成rtmp流发出来?就如:ffmpeg -i rtsp://localhost/live -c copy -f flv rtm

为啥血型有A/B/AB/O四种,怎么来的

表格/长表格/表格的布局