- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
java.lang.OutOfMemoryError:Metaspace表示为java类元数据分配的本机内存量已过测试。让我们看看如何在独立应用程序和云应用程序中解决这个问题。
在Java 8及更高版本中,默认情况下为Java类分配的最大内存量(MaxMetaspaceSize)是无限,因此在大多数情况下无需更改此设置。另一方面,如果要限制为Java类分配的内存量,可以按如下方式设置:
java -XX:MaxMetaspaceSize=3200m
问题是-XX:MaxMetaspaceSize只是一个上限。当前的元空间大小(即已提交)将更小。事实上,有一个名为MaxMetaspaceFreeRatio的设置(默认为70%),这意味着实际的metaspace大小永远不会超过其占用率的230%。
要使其增长,首先必须填满,强制垃圾收集以释放对象,只有当它无法达到其MinMetaspaceFreeRatio(默认40%)目标时,才会扩展当前的元空间。然而,这不能超过GC循环后占用率的230%。
通过增加属性MaxMetaspaceSize的上限,您很可能解决这个问题。如果您可以在应用程序启动时看到错误,那么这是正确的。
另一方面,如果您在运行时看到此错误,建议在盲目增加MaxMetaspaceSize之前调查问题的根本原因。
为了找到根本原因,我们建议您遵循以下步骤:
1.了解JVM如何管理MetaSpace数据
1.了解如何在运行的Java应用程序中监视MetaSpace
1.检查应用程序的堆转储以查找有问题的类
Java热点按如下方式管理元数据空间:首先,JVM向操作系统请求一定数量的空间。然后,这个空间被划分为块。类加载器从其块中为元数据分配空间。
类元数据在卸载相应的Java类并回收其块以供重用或返回给操作系统时被释放。Java类作为垃圾收集的结果被卸载,为了卸载类和释放类元数据,可能会触发垃圾收集。当为类Metadata提交的空间达到某个阈值(高水位线)时,就会发生垃圾回收。
垃圾收集之后,高水位线可能会根据类Metadata释放的空间量而变化。
监视MetaSpace大小的最简单方法是使用JDK中提供的jstat工具。与选项**-gcmetacapacity**一起使用时,它提供以下信息:
jstat -gcmetacapacity (PID)
例如:
MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT CGC CGCT
0.0 374784.0 140360.0 0.0 253952.0 21168.0 23 0 0.000 6 0.046
以下是标签说明:
其他有趣的选项包括参数**-gcutil**:
$ jstat -gcutil (PID) | awk '{print($5)}'
这将以空间当前容量的百分比打印元空间利用率。
监控MetaSpace使用情况的另一个选项是JVM参数NativeMemoryTracking,您可以将其添加到启动参数中。例如:
-XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=detail -XX:+PrintNMTStatistics
启用本机内存跟踪时,可以使用以下命令请求JVM内存使用情况报告:
$ jcmd <pid> VM.native_memory
如果检查jcmd输出,您将在底部的Internal(committed)部分中找到已提交的本机内存量
Total: reserved=1334532KB, committed=369276KB
- Java Heap (reserved=524288KB, committed=132096KB)
(mmap: reserved=524288KB, committed=132096KB)
- Class (reserved=351761KB, committed=112629KB)
(classes #19111)
( instance classes #17977, array classes #1134)
(malloc=3601KB #66765)
(mmap: reserved=348160KB, committed=109028KB)
( Metadata: )
( reserved=94208KB, committed=92824KB)
( used=85533KB)
( free=7291KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=253952KB, committed=16204KB)
( used=12643KB)
( free=3561KB)
( waste=0KB =0.00%)
在以Metaspace开头的行中,查找used值。这是JVM用于加载类的空间量。committed值是可用于块的空间量。reserved值是为元数据保留(但不一定提交)的空间量。
要深入了解MetaSpace错误,您应该检查Java应用程序的堆。您可以使用jmap命令行触发堆转储:
jmap -dump:format=b,file=dump.hprof <PID>
然后,使用您喜爱的工具打开堆转储。例如Eclipse MAT:
从堆转储中,可以查找重复的类,尤其是那些加载应用程序类的类。
最简单的方法是使用OQL控制台在OQL控制台中,您可以执行OQL查询来对类执行特别分析。例如,通过执行以下查询,可以从每个Classloader加载一个类列表:
select map(sort(map(heap.objects('java.lang.ClassLoader'), '{loader: it, count: it.classes.elementCount }'), 'lhs.count < rhs.count'), 'toHtml(it) + "
"')
这可以作为判断Classloader是否正在加载增量的宝贵提示
在OpenShift/Kubernetes上使用OpenJDK映像时,Metaspace的默认最大值为XX:MaxMetaspaceSize=100m。您可能已经注意到,通过JAVA_OPTIONS环境变量设置此值不起作用,因为默认值附加在底部:
VM Arguments: -Xms128m -Xmx1024m -XX:MetaspaceSize=128M -XX:MaxMetaspaceSize=256m -XX:AdaptiveSizePolicyWeight=90 -XX:MaxMetaspaceSize=100m -XX:+ExitOnOutOfMemoryError
设置MaxMetaspaceSize的正确方法是通过GC_MAX_METASPACE_SIZE环境变量。例如,如果您正在使用展开。使用JKube部署应用程序的yaml文件,以下设置将覆盖MaxMetaspaceSize和MaxMetasaceSize的默认值:
spec:
template:
spec:
containers:
- env:
- name: JAVA_OPTIONS
value: '-Xms128m -Xmx1024m'
- name: GC_MAX_METASPACE_SIZE
value: 256
- name: GC_METASPACE_SIZE
value: 96
reqwest v0.9 将 serde v1.0 作为依赖项,因此实现 converting serde_json errors into reqwest error . 在我的代码中,我使用 se
我有这个代码: let file = FileStorage { // ... }; file.write("Test", bytes.as_ref()) .map_err(|e| Mu
我只是尝试用angular-cli创建一个新项目,然后运行服务器,但是它停止并显示一条有趣的消息:Error: No errors。 我以这种方式更新了(希望有帮助):npm uninstall -g
我从我的 javascript 发送交易 Metamask 打开传输对话框 我确定 i get an error message in metamask (inpage.js:1 MetaMask -
这个问题在这里已经有了答案: How do you define custom `Error` types in Rust? (3 个答案) How to get a reference to a
我想知道两者之间有什么大的区别 if let error = error{} vs if error != nil?或者只是人们的不同之处,比如他们如何用代码表达自己? 例如,如果我使用这段代码: u
当我尝试发送超过 50KB 的图像时,我在 Blazor 服务器应用程序上收到以下错误消息 Error: Connection disconnected with error 'Error: Serv
我有一个error-page指令,它将所有异常重定向到错误显示页面 我的web.xml: [...] java.lang.Exception /vi
我有这样的对象: address: { "phone" : 888, "value" : 12 } 在 WHERE 中我需要通过 address.value 查找对象,但是在 SQL 中有函数
每次我尝试编译我的代码时,我都会遇到大量错误。这不是我的代码的问题,因为它在另一台计算机上工作得很好。我尝试重新安装和修复,但这没有帮助。这是整个错误消息: 1>------ Build starte
在我的代码的类部分,如果我写一个错误,则在不应该的情况下,将有几行报告为错误。我将'| error'放在可以从错误中恢复的良好/安全位置,但是我认为它没有使用它。也许它试图在某个地方恢复中间表情? 有
我遇到了 csv 输入文件整体读取故障的问题,我可以通过在 read_csv 函数中添加 "error_bad_lines=False" 来删除这些问题来解决这个问题。 但是我需要报告这些造成问题的文
在 Spring 中,验证后我们在 controller 中得到一个 BindingResult 对象。 很简单,如果我收到验证错误,我想重新显示我的表单,并在每个受影响的字段上方显示错误消息。 因此
我不知道出了什么问题,因为我用 Java 编程了大约一年,从来没有遇到过这个错误。在一分钟前在 Eclipse 中编译和运行工作,现在我得到这个错误: #A fatal error has been
SELECT to_char(messages. TIME, 'YYYY/MM/DD') AS FullDate, to_char(messages. TIME, 'MM/DD
我收到这些错误: AnonymousPath\Anonymized.vb : error BC30037: Character is not valid. AnonymousPath\Anonymiz
我刚刚安装了 gridengine 并在执行 qstat 时出现错误: error: commlib error: got select error (Connection refused) erro
嗨,我正在学习 PHP,我从 CRUD 系统开始,我在 Windows 上安装了 WAMP 服务器,当我运行它时,我收到以下错误消息。 SCREAM: Error suppression ignore
我刚刚开始一个新项目,我正在学习核心数据教程,可以找到:https://www.youtube.com/watch?v=zZJpsszfTHM 我似乎无法弄清楚为什么会抛出此错误。我有一个名为“Exp
当我使用 Jenkins 运行新构建时,出现以下错误: "FilePathY\XXX.cpp : fatal error C1853: 'FilePathZ\XXX.pch' precompiled
我是一名优秀的程序员,十分优秀!