一个类只能加载一次。首先我们得确定类信息存在于哪里?类信息所存在的位置内存大小是否能够容下成千上万个类信息的存储。如果一个比较大的项目中有成千上万个类。在项目运行一段时间,大部分类信息加载到了内存中。会不会导致OOM?对象会被垃圾回收器回收。类信息会吗?
当一个类满足卸载条件时(这个类没有任何对象,并且class对象和加载该类的classloader已经被回收),也是可以被卸载从而释放这部分内存的。JAVA8移除了永久带增加了元数据区(加载的类就放在这里),这部分是直接内存,因此理论上只受操作系统物理内存大小的限制。如果通过jvisualvm观察,会发现已经加载的类的数量也是会减少的,说明被回收。
java.lang.OutOfMemoryError: PermGen spacejava.lang.OutOfMemoryError: Metaspace
原因
永久代是 HotSot 虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。
JDK8后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:
- 字符串常量由永久代转移到堆中
- 和永久代相关的JVM参数已移除
可能原因有如下几种:
- 在Java7之前,频繁的错误使用String.intern()方法
- 运行期间生成了大量的代理类,导致方法区被撑爆,无法卸载
- 应用长时间运行,没有重启没有重启 JVM 进程一般发生在调试时