ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

【面试】JDK8的元空间存储什么内容?会发生FGC吗?JVM调优

【面试】JDK8的元空间存储什么内容?会发生FGC吗?JVM调优 JDK8的元空间存储什么内容会发生FGC吗​ 先来看张图(JVM线程模型)​ 在jdk1.8之前还有一个分区叫做方法区它是堆内存的一个逻辑分区。主要用于存储虚拟机加载的类信息、常量、静态变量以及编译器编译后的代码等数据。为了与堆做区分方法区还有个名字叫“非堆”也有人用“永久代”HotSpot对方法区的实现方法来表示方法区。​ 在jdk1.8中方法区已经不存在原方法区中存储的类信息、编译后的代码数据等已经移动到了元空间MetaSpace中元空间并没有处于堆内存上而是直接占用的本地内存。元空间的大小仅受本地内存限制但可以通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize来指定元空间的大小。去永久代的原因有字符串存在永久代中容易出现性能问题和内存溢出。类及方法的信息等比较难确定其大小因此对于永久代的大小指定比较困难太小容易出现永久代溢出太大则容易导致老年代溢出。永久代会为 GC 带来不必要的复杂度并且回收效率偏低。默认的MetaspaceSize大小是多少呢怎么查看正在运行的java进程的MetaspaceSize呢通过以下命令可以查看java-XX:PrintFlagsInitial# 输出结果:uintx MaxMetaspaceFreeRatio70{product}uintx MaxMetaspaceSize18446744073709551615{product}uintx MetaspaceSize21810376{pd product}jmap-heappid# 由于设置了参数-XX:MetaspaceSize256m -XX:MaxMetaspaceSize256m# 输出以下结果Heap Configuration: MetaspaceSize268435456(256.0MB)MaxMetaspaceSize268435456(256.0MB)如果使用默认的MetaspaceSize大小会出现什么问题如何调优首先MetaspaceSize的默认大小为21M如果我们的项目文件过多在我们应用进程启动的时候就可以看到发生FGC。这里可以通过调整-XX:MetaspaceSize这个参数减少启动的FGC。另一种情况是我们Java应用很多都是通过动态代理实现一些功能动态代理就要产生运行时编译的代理类这样就会占用到Metaspace如果这个参数不调整同样会发生FGC。还有就是MaxMetaspaceSize参数如果不设置会使用机器自身内存如果程序存在内存泄漏会导致机器内存不足需要设置一个合理的值来满足应用正常运行。平常调优的方式是先预估再观察和调整根据项目大小业务量变化再通过如下脚本# 1秒输出一次来观察jvm内存变化和gc情况jstat-gcutilpid1000总结元空间Metaspace里存的是常量、加载的类信息、方法、动态编译的代码这里要注意默认大小如果超过会发生FGC而我们调优的目的就是尽量不产生FGC需要通过-XX:MetaspaceSize这个参数设置来避免产生FGC。注意静态变量和字符串常量池仍然在堆中。-------------欢迎各位留言交流如有不正确的地方请予以指正。
返回列表