You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yudao/JVM_OPTIMIZATION_GUIDE.md

3.9 KiB

JVM 本地内存不足问题解决指南

问题分析

错误信息

Native memory allocation (mmap) failed to map X bytes for G1 virtual space

根本原因

  1. 地址空间冲突

    • Windows 7GB 内存系统,Java Heap 默认占用 2GB
    • Compressed Oops 模式将 Heap 放在前 4GB 地址空间
    • 本地内存(OpenCV、ONNX、相机库等)也需要地址空间
    • 结果:地址空间不足,导致本地内存分配失败
  2. 系统配置

    • 总内存:7GB
    • Java Heap:2GB
    • 剩余:5GB(用于操作系统、其他库、本地内存)

受影响的应用

  • yudao-server.jar
  • LxCameraApi-1.0.1-SNAPSHOT.jar(加载了 OpenCV、海康相机、ONNX)

解决方案

关键参数

# 1. 减小堆内存,为本地内存预留空间
-Xms1g -Xmx2g

# 2. 将 Java Heap 放在 4GB 地址空间以上(最重要!)
-XX:HeapBaseMinAddress=0x100000000

# 3. 增加 JIT 代码缓存
-XX:ReservedCodeCacheSize=512m

# 4. 使用 G1 垃圾回收器
-XX:+UseG1GC

使用方法

方式 1:直接运行(推荐用于开发测试)

yudao-server:

cd d:\git\lpNewgit\yudao-server
start.bat

LxCameraApi:

cd d:\git\lpNewgit
LxCameraApi-start.bat

通用模板(适用于其他应用):

cd d:\git\lpNewgit
optimized-jvm-start-template.bat

编辑 optimized-jvm-start-template.bat 修改:

  • JAR_PATH:你的 JAR 包路径
  • APP_NAME:应用名称
  • LOG_PATH:日志路径

方式 2:作为 Windows 服务运行(推荐用于生产环境)

yudao-server:

cd d:\git\lpNewgit\yudao-server
install-service.bat

卸载服务:

uninstall-service.bat

监控和验证

检查堆地址

启动后查看日志,确认堆地址已移到 4GB 以上:

Heap address: 0x0000000100000000  # 应该是 0x100000000 或更高

查看崩溃日志

如果仍然崩溃,查看:

D:\sy_software\application-app\logs\hs_err_pid*.log

性能监控

使用以下命令监控内存使用:

# 查看 JVM 进程
tasklist | findstr java.exe

# 查看内存使用
wmic process where "name='java.exe'" get ProcessId,WorkingSetSize,PageFileUsage

其他优化建议

1. 如果还有内存问题

进一步减小堆内存:

-Xms512m -Xmx1.5g

2. 禁用 JIT 编译(极端情况)

-Xint
# 这会显著降低性能,但能解决 JIT 相关的内存问题

3. 增加 Windows 虚拟内存

  1. 右键"此电脑" → 属性 → 高级系统设置
  2. 性能 → 设置 → 高级 → 虚拟内存
  3. 增加页面文件大小到 8GB 或更大

4. 升级硬件

最佳解决方案是增加物理内存到 16GB 或更高。

常见问题

Q1: 为什么之前运行正常,现在才崩溃?

A: 应用运行时间越长,内存碎片越严重,最终导致无法分配大块连续内存。

Q2: 减小堆内存会影响性能吗?

A: 轻微影响,但比崩溃要好。对于 7GB 系统,2GB 堆是合理的平衡点。

Q3: -XX:HeapBaseMinAddress 参数安全吗?

A: 安全。这是官方推荐的解决方案,专门用于解决 Compressed Oops 和本地内存冲突问题。

Q4: 为什么需要增加 CodeCache?

A: JIT 编译器需要本地内存来存储编译后的代码,增加缓存大小可以减少编译频率。

文件说明

  • optimized-jvm-start-template.bat - 通用 JVM 优化启动模板
  • LxCameraApi-start.bat - LxCameraApi 专用启动脚本
  • yudao-server/install-service.bat - yudao-server 服务安装脚本
  • yudao-server/uninstall-service.bat - 服务卸载脚本
  • yudao-server/start.bat - yudao-server 直接启动脚本

联系支持

如果问题仍然存在,请提供以下信息:

  1. hs_err_pid*.log 文件内容
  2. 应用运行的 JAR 包名称
  3. 加载了哪些第三方库(DLL)
  4. 系统配置(CPU、内存、Windows 版本)