什么情况下 Java 会卸载一个类 (unload class)

最近遇到一个线上问题, 一个 Java web 应用在运行一段时间(几个小时或几天)后, 会抛出 NoClassDefFoundError. 该应用使用的是 Akka 框架, 并且开启了参数: akka.jvm-exit-on-fatal-error. 所以, 当 Akka 捕获这个 NoClassDefFoundError 后, 直接就发生了重启 JVM 的操作.

2020-04-22 01:11:39,369 ERROR [squbs-akka.actor.default-dispatcher-5] ActorSystemImpl ActorSystem(squbs) Uncaught error from thread [squbs-cal-publishing-dispatcher-18326] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled
java.lang.NoClassDefFoundError: Could not initialize class org.xerial.snappy.Snappy

这里使用 Snappy 这个类的代码是一个非常普遍, 经常使用的代码, 所以一开始怀疑 Snappy 这个类一开始是被正常加载且正常使用的. 之后, 某个时间点这个 Snappy 类由于某种原因被卸载了(unload), 当然最终这个怀疑是不正确的. 不过这里就引发了一个思考, 到底什么情况下一个 Java 类会被卸载 (unload)?

根据 The Java® Language Specification Java+SE 8 Edition 的说法, 只有当下面的情况下, 一个 Class 才有可能被卸载:

只有当加载该类的 ClassLoader 被卸载的情况下, 该类才有可能被卸载.

这里的前提条件是: 该类没有任何实例, 没有任何被任何类, 接口, 对象引用, 加载该类的 ClassLoader 也满足可以被卸载的前提下, 该类才有可能被卸载.

标签: none

添加新评论