47 VM.maxDirectMemory() 来自于哪里
创始人
2024-04-06 23:25:34
0

前言 

最近在 记一次 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

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...