internalerror 是 jvm 内部崩溃,非代码错误;unknownerror\_ 非标准异常,多源于定制 jvm 或 jni 问题;二者均不可捕获,应通过 core dump、日志和复现条件定位根本原因。

InternalError 是 JVM 自己崩了,不是你的代码写错了
InternalError 表示 JVM 在运行过程中遇到了它自己无法处理的内部状态异常,比如内存管理模块出错、类加载器逻辑矛盾、JIT 编译器生成了非法指令等。这不是你调用 new RuntimeException() 能触发的,而是 JVM 底层 C/C++ 代码主动抛出的错误(通常继承自 VirtualMachineError)。
常见现象包括:应用突然静默退出、日志里只有一行 java.lang.InternalError: XXX、堆栈末尾常带 at java.base/java.lang.ClassLoader.defineClass1(Native Method) 这类 native 调用痕迹。
- 别试图 catch
InternalError—— 即使捕获了,JVM 状态很可能已不可靠,继续运行可能引发更隐蔽的数据损坏 - 优先检查 JVM 版本是否匹配:某些
InternalError: Malformed class name在 JDK 17.0.1 存在,升级到 17.0.2 就消失 - 留意 GC 参数组合:比如同时启用
-XX:+UseZGC和-XX:+UnlockExperimentalVMOptions在旧版 ZGC 上可能触发InternalError: ZGC not supported on this platform - 如果复现稳定,用
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -Xlog:gc*,vm*=debug开启底层日志,重点看 error 前 200ms 的 GC 和类加载行为
UnknownError\_ 不是标准 Java 异常,大概率是 JNI 或 JVM 补丁引入的私有错误
Java 标准异常体系里根本没有 UnknownError_ 这个类。它通常出现在两种场景:一是某些厂商定制 JVM(如 Alibaba Dragonwell、Amazon Corretto 的特定 patch 版本)内部用于标记尚未归类的致命错误;二是 JNI 层代码在抛出异常时误用了未注册的错误名。
典型表现是堆栈中出现 java.lang.UnknownError_: null 或带乱码类名,且 getCause() 返回 null。
立即学习“Java免费学习笔记(深入)”;
- 先确认 JVM 来源:运行
java -version和java -XshowSettings:properties -version,比对官网发布的 build 号,避免使用非公开测试版 - 检查本地库:如果有自定义
.so/.dll,用ldd(Linux)或depends.exe(Windows)验证其依赖的 JVM 符号版本是否匹配 - 禁用可疑扩展:比如某些监控 agent(如 older versions of SkyWalking 8.x)会在字节码增强时意外注入
UnknownError_,尝试移除-javaagent启动参数验证 - 不要重命名或反射加载这个类 —— 它没有 public 构造器,
Class.forName("java.lang.UnknownError_")会直接抛ClassNotFoundException
InternalError 和 UnknownError\_ 都不该进 try-catch,但得留好现场
这两类错误都属于「JVM 已失去可信执行环境」的信号,强行捕获并吞掉只会掩盖真正问题。关键是让崩溃发生得可追溯。
- 必须开启 core dump:
-XX:+CoreDumpOnCrash -XX:CoreDumpPath=/var/log/java-crash/,配合ulimit -c unlimited - 加上
-XX:+PrintGCDetails -XX:+PrintConcurrentLocks -XX:+HeapDumpOnOutOfMemoryError—— 即使不是 OOM,这些开关也能在 InternalError 前输出最后几秒的内存快照 - 避免用
-XX:OnError执行复杂脚本:某些 JVM 在 InternalError 时连 shell 都无法安全 fork,推荐只写入时间戳到固定文件,例如-XX:OnError="echo %p %t >> /tmp/jvm-crash.log" - 如果跑在容器里,确保
/proc/sys/kernel/core_pattern指向宿主机可写路径,否则 core 文件会被丢弃
真正要盯住的是「可复现条件」,不是错误名字本身
叫 InternalError 还是 UnknownError_ 并不重要,重要的是什么操作会让它稳定出现。这类错误本质是 JVM 对某个输入状态的断言失败,而那个输入往往藏在你没注意的地方。
- 记录触发前的精确操作链:比如「先调用
Unsafe.copyMemory()拷贝 64KB 到 DirectByteBuffer,再执行System.gc()两次,第 3 次就 crash」 - 检查 native 内存:用
pmap -x <pid></pid>看 RSS 是否逼近容器 limit,InternalError: Native memory allocation (mmap) failed其实就是 OOM 的 native 版 - 留意时间因素:某些
InternalError: Timer expired实际是系统时钟被 NTP 突然校准导致 JVM 内部定时器逻辑错乱,不是代码问题 - 如果只有高并发下出现,关掉 JIT 编译试试:
-Xint—— 很多InternalError: Exception in compiler thread就因此消失,说明是 C2 编译器 bug,不是你的逻辑问题
这类错误没有银弹,能定位到「哪一行触发、在哪种 JVM 版本下必现、换哪个参数就绕过」,就已经赢了一半。剩下的就是等 vendor 修,或者换更稳的替代方案。








