java 如何计算(并指定)java进程允许的总内存空间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3513903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:11:29  来源:igfitidea点击:

How to calculate (and specify) the total memory space allowed for java process?

javajvmmemory-management

提问by Dimitri Uwarov

I have a system which cannot provide more than 1.5 Gb for Java process. Thus i need an exact way to specify java process settings, including all memory kinds inside java and possible fork.

我有一个系统,它不能为 Java 进程提供超过 1.5 Gb 的容量。因此,我需要一种确切的方法来指定 java 进程设置,包括 java 中的所有内存类型和可能的 fork。

One specific java process and system to illustrate my problem:

一个特定的java进程和系统来说明我的问题:

My current environment is java 1.6.0_18 under Ubuntu Linux 9.10.

我当前的环境是 Ubuntu Linux 9.10 下的 java 1.6.0_18。

I start large java server process with following JVM Options: "-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m"

我使用以下 JVM 选项启动大型 Java 服务器进程:“-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m”

Now, "top" command reports that the process uses 1.6gb memory...

现在,“top”命令报告该进程使用 1.6GB 内存......

Questions:

问题:

1 - how the maximal space used by java process is calculated? Please provide exact formula if possible. ( Smth. Like: max.heap + max.perm + stack + jvm space = maximal space )

1 - 如何计算java进程使用的最大空间?如果可能,请提供准确的公式。( Smth. Like: max.heap + max.perm + stack + jvm space = maximal space )

2 - what is the infamous fork behavior under linux in my case? Will the forked JVM occupy extra 1.6 gb (resulting in total 3.2 Gb of used memory)?

2 - 就我而言,Linux 下臭名昭著的分叉行为是什么?分叉的 JVM 会占用额外的 1.6 GB(导致总共 3.2 Gb 的已用内存)吗?

3 - Which options must be used to absolutely ensure that no more than 1.5gb is used at any time?

3 - 必须使用哪些选项才能绝对确保任何时候使用的内存不超过 1.5GB?

thank you

谢谢

@rancidfishbreath: "ulimit" will ensure that java cannot take more than specified amount of memory. My purpose is to ensure that java doesn't ever try to do that.

@rancidfishbreath:“ulimit”将确保java不能占用超过指定数量的内存。我的目的是确保 java 永远不会尝试这样做。

采纳答案by SiCN

topreports 1.6GB because PermSize is ON TOP of the heap-size maximum heap size. In your case you set MaxPermSize to 512m and Xmx to 1024m. This amounts to 1536m. Just like in other languages, an absolutely precise number can not be calculated unless you know precisely how many threads are started, how many file handles are used, etc. The stack size per thread depends on the OS and JDK version, in your case its 1024k (if it is a 64bit machine). So if you have 10 threads you use 10240k extra as the stack is not allocated from the heap (Xmx). Most applications that behave nicely work perfectly when setting a lower stack and MaxPermSize. Try to set the ThreadStackSize to 128k and if you get a StackOverflowError (i.e. if you do lots of deep recursions) you can increase it in small steps until the problem disappears.

top报告 1.6GB,因为 PermSize 是堆大小最大堆大小的顶部。在您的情况下,您将 MaxPermSize 设置为 512m,将 Xmx 设置为 1024m。这相当于1536m。就像在其他语言中一样,除非您确切地知道启动了多少线程、使用了多少文件句柄等,否则无法计算出绝对精确的数字。每个线程的堆栈大小取决于操作系统和 JDK 版本,在您的情况下1024k(如果是 64 位机器)。因此,如果您有 10 个线程,您将额外使用 10240k,因为堆栈不是从堆 (Xmx) 中分配的。在设置较低的堆栈和 MaxPermSize 时,大多数表现良好的应用程序都能完美运行。尝试将 ThreadStackSize 设置为 128k,如果出现 StackOverflowError(即,如果您进行大量深度递归),您可以逐步增加它,直到问题消失。

So my answer is essentially that you can not control it down to the MB how much the Java process will use, but you come fairly close by setting i.e. -Xmx1024m -XX:MaxPermSize=384m and -XX:ThreadStackSize=128k -XX:+UseCompressedOops. Even if you have lots of threads you will still have plentyof headroom until you reach 1.5GB. The UseCompressedOops tells the VM to use narrow pointers even when running on a 64bit JVM, thus saving some memory.

所以我的答案基本上是你不能控制它到 MB 多少 Java 进程将使用多少,但你通过设置 ie -Xmx1024m -XX:MaxPermSize=384m 和 -XX:ThreadStackSize=128k -XX:+ 来相当接近使用CompressedOops。即使您有很多线程,在达到 1.5GB 之前,您仍然有足够的空间。UseCompressedOops 告诉 VM 即使在 64 位 JVM 上运行时也使用窄指针,从而节省一些内存。

回答by Anil Vishnoi

At high level JVM address space is divided in three main parts:

在高层 JVM 地址空间分为三个主要部分:

  1. kernel space:~1GB, also depends on platform, windows its more than 1GB
  2. Java Heap:Java heap specified by user using the -Xmx, -XX:MaxPermSize, etc...
  3. Rest of virtual address space goes to native usage of JVM, to accomodate the malloc/calloc done by JVM, native threads stack: thread respective the java threads and addition JVM native threads for GC, etc...
  1. 内核空间:~1GB,也取决于平台,windows 超过 1GB
  2. Java堆:使用用户指定的Java堆-Xmx-XX:MaxPermSize等...
  3. 其余的虚拟地址空间用于 JVM 的本机使用,以容纳由 JVM 完成的 malloc/calloc,本机线程堆栈:线程各自的 Java 线程和用于 GC 的附加 JVM 本机线程等......

So you have (4GB - kernel space 1-1.25GB) ~2.75GB to play with,so you can set your java/native heap accordingly. But generally we should keep atleast 500MB for JVM native heap else there is a chances that you get native OOM. So we need to do a trade off here based on your application's java heap utilization.

所以你有(4GB - 内核空间 1-1.25GB)~2.75GB 可以玩,所以你可以相应地设置你的 java/native 堆。但是通常我们应该为 JVM 原生堆保留至少 500MB 的空间,否则你可能会得到原生的 OOM。因此,我们需要根据您的应用程序的 Java 堆利用率在此处进行权衡。