Red Hat Tomcat 7 容器上 java 的 Heapsize 和其他内存配置
Heapsize and other memory configuration of java on Tomcat 7 container of Red Hat
我正在使用 Red Hat tomcat7 容器(与 docker 集线器上的 tomcat7 非常相似):
registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat7-openshift:1.2-12
我已经在其中部署了一些 .wars,但是在执行了很多过程之后我得到了以下错误:
GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded
所以我想研究最大堆大小和其他内存设置:
命令:
java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'
Output:
Picked up JAVA_TOOL_OPTIONS: -Duser.home=/home/jboss -Duser.name=jboss
intx CompilerThreadStackSize = 0
{pd product}
uintx ErgoHeapSizeLimit = 0
{product}
uintx HeapSizePerGCThread = 87241520
{product}
uintx InitialHeapSize = 125829120
{product}
uintx LargePageHeapSizeThreshold = 134217728
{product}
uintx MaxHeapSize = 1983905792
{product}
intx ThreadStackSize = 1024
{pd product}
intx VMThreadStackSize = 1024
{pd product}
openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
我不知道该如何解释这些信息。
我考虑过增加堆大小。
- pd产品或产品是什么意思?
- 最大堆大小是否 = java 或您的应用程序或整个 tomcat 的最大内存消耗?因为经过一些调查,我发现容器在出现
outofmemory
问题时使用的内存比 1892 MB (19839...) 多得多。
Tomcat 应该为所有应用程序使用一个 JVM。这确实使用了 1892 MB ( 1983905792 B / 10242 ),这里的问题可能是:
- 您有内存泄漏 - 您保留了对正在使用的对象的引用,它们导致您的 VM 无法通过垃圾回收释放内存。解释得更好 here。
尝试通过查看
jmap -histo <javaPID>
的输出来弄清楚为什么会发生这种情况
- 您的应用运行正常,您确实需要更多堆内存。您可以通过设置
set CATALINA_OPTS= -Xmx2g
来增加内存
尽管您的问题并没有像@Razvan 那样真正解决您的问题:
What is the meaning of pd product or product? [in PrintFlagsFinal]
这意味着该标志可用于 'product'(已发布)构建,而不是用于开发、QA、诊断或实验用途的构建。 'pd' 表示依赖于平台(Solaris vs Linux vs Windows 等)。
Is the max heapsize = the max memory consumption of java or of your application or of your whole tomcat? Because after some investigation I saw the container was using a lot more memory than 1892 MB (19839...) when it had the outofmemory issue.
运行 Java 进程将内存用于除堆之外的许多事情。如果在任何 OS 上安装了完整的 JDK,您可以在 Linux 上使用 /proc/$pid/maps
或 jmap
(默认格式)看到它:
JVM 本身的代码,包括解释器和 JIT 编译器 HotSpot,以及各种库,加上通过 JNI 或 JNA 访问的任何 'native' 代码,以及 'native' 数据。一般来说,代码可能会与其他进程共享,但我不确定这在 docker 容器中是否仍然如此。
'Metaspace'(在 Java 8 中,'PermGen' 在早期版本中)和 'CodeCache' 包含加载的 类 和 JITted 代码为他们
线程堆栈; Tomcat 使用了相当多的线程,即使 Java 代码没有,JVM 也有一些内置线程,也许还有本机线程
'direct' 如果使用 NIO 缓冲区(我认为 Tomcat 至少有时可以)
但是只有堆中的对象被垃圾回收,所以其他区域与GC失败无关。
此外,我不确定 docker 内存测量是否包括进程本身之外的任何内容。您可以与 top
或 ps -F
.
进行比较
我正在使用 Red Hat tomcat7 容器(与 docker 集线器上的 tomcat7 非常相似):
registry.access.redhat.com/jboss-webserver-3/webserver30-tomcat7-openshift:1.2-12
我已经在其中部署了一些 .wars,但是在执行了很多过程之后我得到了以下错误:
GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded
所以我想研究最大堆大小和其他内存设置:
命令:
java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'
Output:
Picked up JAVA_TOOL_OPTIONS: -Duser.home=/home/jboss -Duser.name=jboss
intx CompilerThreadStackSize = 0
{pd product}
uintx ErgoHeapSizeLimit = 0
{product}
uintx HeapSizePerGCThread = 87241520
{product}
uintx InitialHeapSize = 125829120
{product}
uintx LargePageHeapSizeThreshold = 134217728
{product}
uintx MaxHeapSize = 1983905792
{product}
intx ThreadStackSize = 1024
{pd product}
intx VMThreadStackSize = 1024
{pd product}
openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)
我不知道该如何解释这些信息。 我考虑过增加堆大小。
- pd产品或产品是什么意思?
- 最大堆大小是否 = java 或您的应用程序或整个 tomcat 的最大内存消耗?因为经过一些调查,我发现容器在出现
outofmemory
问题时使用的内存比 1892 MB (19839...) 多得多。
Tomcat 应该为所有应用程序使用一个 JVM。这确实使用了 1892 MB ( 1983905792 B / 10242 ),这里的问题可能是:
- 您有内存泄漏 - 您保留了对正在使用的对象的引用,它们导致您的 VM 无法通过垃圾回收释放内存。解释得更好 here。
尝试通过查看
jmap -histo <javaPID>
的输出来弄清楚为什么会发生这种情况
- 您的应用运行正常,您确实需要更多堆内存。您可以通过设置
set CATALINA_OPTS= -Xmx2g
来增加内存
尽管您的问题并没有像@Razvan 那样真正解决您的问题:
What is the meaning of pd product or product? [in PrintFlagsFinal]
这意味着该标志可用于 'product'(已发布)构建,而不是用于开发、QA、诊断或实验用途的构建。 'pd' 表示依赖于平台(Solaris vs Linux vs Windows 等)。
Is the max heapsize = the max memory consumption of java or of your application or of your whole tomcat? Because after some investigation I saw the container was using a lot more memory than 1892 MB (19839...) when it had the outofmemory issue.
运行 Java 进程将内存用于除堆之外的许多事情。如果在任何 OS 上安装了完整的 JDK,您可以在 Linux 上使用 /proc/$pid/maps
或 jmap
(默认格式)看到它:
JVM 本身的代码,包括解释器和 JIT 编译器 HotSpot,以及各种库,加上通过 JNI 或 JNA 访问的任何 'native' 代码,以及 'native' 数据。一般来说,代码可能会与其他进程共享,但我不确定这在 docker 容器中是否仍然如此。
'Metaspace'(在 Java 8 中,'PermGen' 在早期版本中)和 'CodeCache' 包含加载的 类 和 JITted 代码为他们
线程堆栈; Tomcat 使用了相当多的线程,即使 Java 代码没有,JVM 也有一些内置线程,也许还有本机线程
'direct' 如果使用 NIO 缓冲区(我认为 Tomcat 至少有时可以)
但是只有堆中的对象被垃圾回收,所以其他区域与GC失败无关。
此外,我不确定 docker 内存测量是否包括进程本身之外的任何内容。您可以与 top
或 ps -F
.