我有一个在服务器环境中按需运行的Jar文件,我想限制它使用的内存量,以便多个同时发送的实例可以轻松运行。但是,在设置-Xmx512M
参数后,似乎Java仍在使用更多内存。我使用以下命令:
java -Xmx512M -jar Reporter.jar /tmp/REPmKLs8K
但是我可以看到该过程使用的不仅仅是:
Resource: Virtual Memory Size
Exceeded: 1657 > 400 (MB)
Executable: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91.x86_64/jre/bin/java
Command: java -Xmx512M -jar Reporter.jar /tmp/REPmKLs8K
我不确定为什么会这样,并且它可能是内存报告软件(ConfigServer Firewall)的问题。有没有人经历过类似的事情?
答案 0 :(得分:0)
-Xmx
是最大堆大小,而不是进程大小。
答案 1 :(得分:0)
-Xmx
用于指定最大堆分配,但java需要更多内存用于JVM,pergem空间(Java 7及以下版本)等...您可以看到这post for memory structure
您可以使用JVisualVM之类的工具来分析JVM中的实际内存使用情况。
答案 2 :(得分:0)
-Xmx
无法控制您认为它控制的内容。它只控制JVM堆,而不是JVM堆中的所有内容,并且堆占用了您为管理和簿记指定的更多本机内存。
您无法控制您想要控制的内容,-Xmx
仅控制Java堆,它不控制JVM对本机内存的消耗,这种消耗完全不同基于实施。 JVM以完全不同的方式使用本机内存,它依赖于每个JVM实现及其运行的操作系统。
来自以下文章Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )
维护堆和垃圾收集器使用您无法控制的本机内存。
需要更多的本机内存来维护状态 内存管理系统维护Java堆。数据结构 必须分配以跟踪免费存储并记录进度 收集垃圾。这些数据结构的确切大小和性质 随实施而变化,但许多与大小成正比 堆。
并且JIT编译器使用本机内存,就像javac
字节码编译使用本机内存(与静态内存相同) 编译器如gcc需要内存运行),但两者都是输入( 字节码)和JIT的输出(可执行代码)也必须 存储在本机内存中。包含许多的Java应用程序 JIT编译的方法比较小的应用程序使用更多的本机内存。
然后你有使用本机内存的类加载器
Java应用程序由定义对象结构的类组成 和方法逻辑。它们还使用Java运行时类中的类 库(如java.lang.String)并可能使用第三方 库。只要这些类需要存储在内存中 他们正在被使用。如何存储类因实现而异。
我甚至不会开始引用关于线程的部分。
类加载器和应用程序可以有多个,占用大量内存,而这些内存很难记录。 JIT消耗内存,交易时间空间,这在大多数时间是一个很好的交易。
上面的一些链接可能指的是较旧的Java版本; Java 8以不同方式处理垃圾收集和内存分配,但上述一般规则适用。