我使用的是一个Red Hat tomcat7容器(与docker hub上的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
问题时使用的内存比1892MB(19839…)多得多
Tomcat应该为所有应用程序使用一个JVM。这确实使用了1892MB(1983905792B/10242),这里的问题可能是:
- 您有内存泄漏-您保留了对正在使用的对象的引用,这些引用导致VM无法通过垃圾收集释放内存。这里解释得更好。试着通过查看
jmap -histo <javaPID>
的输出来弄清楚为什么会发生这种情况 - 您的应用程序运行正常,确实需要更多的堆内存。您可以通过设置
set CATALINA_OPTS= -Xmx2g
来增加内存
尽管你的问题并没有像@Razvan那样真正解决你的问题:
pd乘积或乘积的含义是什么?[打印标志最终]
这意味着该标志可用于"产品"(已发布)构建,而不是用于开发、QA、诊断或实验pd表示依赖于平台(Solaris与Linux与Windows等)。
最大堆大小=java、应用程序或整个tomcat的最大内存消耗量吗?因为经过一些调查,我发现这个容器使用的内存比1892MB(19839…)多得多,当时它有内存不足的问题。
运行中的Java进程将内存用于堆之外的许多事情。您可以在Linux上的/proc/$pid/maps
或jmap
(默认格式)中看到这一点,如果您在任何操作系统上安装了完整的JDK:
-
JVM本身的代码,包括解释器和JIT编译器HotSpot,以及各种库,再加上通过JNI或JNA访问的任何"本机"代码和"本地"数据。通常,代码可以与其他进程共享,但我不确定在docker容器中是否仍然如此。
-
"Metaspace"(在Java 8中,在早期版本中为"PermGen")和"CodeCache",其中包含加载的类和它们的JITted代码
-
线程堆栈;Tomcat使用了相当多的线程,即使Java代码没有,JVM也有一些内置线程,也许还有本地线程
-
如果使用"直接"NIO缓冲区(我认为Tomcat至少有时可以)
但只有堆中的对象是垃圾收集的,所以其他区域与GC失败无关。
此外,我不确定docker内存测量是否包括进程本身之外的任何内容。您可以将其与top
或ps -F
进行比较。