如何正确使用ulimit与java?

前端之家收集整理的这篇文章主要介绍了如何正确使用ulimit与java?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的 java程序必须在内存受限于指定数量的环境中运行.当我运行我的java服务时,它在启动期间耗尽了内存.

这是我正在使用的命令和我正在设置的值的示例:

ulimit -Sv 1500000
java \
    -Xmx1000m -Xms1000m \
    -XX:MaxMetaspaceSize=500m \
    -XX:CompressedClassSpaceSize=500m \
    -XX:+ExitOnOutOfMemoryError \
    MyClass

从理论上讲,我已经考虑了所有可以找到文档的内容.堆(1000m)和元空间(500m).但是在初始化JVM时它仍然会耗尽内存.直到我将ulimit设置为比堆元空间大600mib时才会发生这种情况.

我错过了什么类型的记忆,以便我可以适当地设置ulimit?

使用案例:我在内存有限的Docker容器中运行任务.这意味着linux cgroups正在进行限制.当超出内存限制时,cgroup只能暂停或终止超出其范围的进程.我真的希望java进程在出现问题时优雅地失败并且它使用太多内存以便包装bash脚本可以向任务启动器报告错误.

我们使用java 8所以我们需要担心Metaspace而不是permgen.

更新:它不会因OutOfMemoryError而死亡.这是错误

Error occurred during initialization of VM
Could not allocate Metaspace: 524288000 bytes

解决方法

实际上很难有效地限制java.许多池都是无限制的,当分配尝试失败时,JVM会发生灾难性故障.并非所有内存都是实际提交的,但其中大部分都是保留的,因此计入ulimit强加的虚拟内存限制.

经过大量调查,我发现了许多不同类型的内存java使用.此答案适用于64位系统上的OpenJDK和Oracle 8.x:

这是JVM内存中最容易理解的部分.它是使用大部分程序存储器的地方.它可以使用-Xmx和-Xms选项进行控制.

元空间

这似乎包含有关已加载的类的元数据.我无法确定这个类别是否会向操作系统释放内存,或者它是否只会增长.默认最大值似乎为1g.它可以使用-XX:MaxMetaspaceSize选项进行控制.注意:如果不指定Compressed类空间,指定它可能不会执行任何操作.

压缩类空间

这似乎与Metaspace有关.我无法确定这个类别是否会向操作系统释放内存,或者它是否只会增长.默认最大值似乎为1g.它可以使用’-XX:CompressedClassSpaceSize`选项进行控制.

垃圾收集器开销

根据所选的垃圾收集器,似乎存在固定的开销量,以及基于堆大小的额外分配.观察表明,此开销约为堆大小的5%.没有已知的限制此选项(除了选择不同的GC算法).

主题

每个线程为其堆栈预留1米. JVM似乎预留了额外的50米内存作为防止堆栈溢出的安全措施.可以使用-Xss选项控制堆栈大小.安全尺寸无法控制.由于无法强制执行最大线程数,并且每个线程都需要一定量的内存,因此这个内存池在技术上是无限制的.

Jar文件(和zip文件)

默认的zip实现将使用内存映射来进行zip文件访问.这意味着访问的每个jar和zip文件都将被内存映射(需要一定量的保留内存等于文件大小的总和).可以通过设置sun.zip.disableMemoryMapping系统属性来禁用此行为(如-Dsun.zip.disableMemoryMapping = true)

NIO Direct Buffers

任何直接缓冲区(使用allocateDirect创建)都将使用该堆的堆外内存.最好的NIO性能带有直接缓冲区,因此很多框架都会使用它们.

JVM无法限制NIO缓冲区允许的总内存量,因此该池在技术上是无限制的.

此外,对于接触缓冲区的每个线程,此内存在堆上重复.有关详细信息,请参见this.

库分配的本机内存

如果您使用的是任何本机库,则它们分配的任何内存都将在堆外.一些核心java库(如java.util.zip.ZipFile)也使用消耗堆内存的本机库.

JVM无法限制本机库分配的内存总量,因此该池在技术上是无限制的.

malloc竞技场

JVM对许多这些本机内存请求使用malloc.为避免线程争用问题,malloc函数使用多个预分配池.默认池数等于8 x cpu,但可以通过设置环境变量MALLOC_ARENAS_MAX来覆盖它.即使不是全部使用,每个池也会保留一定量的内存.

对于java,通常建议将MALLOC_ARENAS_MAX设置为1-4,因为最常见的分配是从堆完成的,较低的竞技场计数将防止浪费的虚拟内存向ulimit计数.

此类别在技术上不是它自己的池,但它解释了额外内存的虚拟分配.

猜你在找的Linux相关文章