初中网站建设,网站建设的实施方案,可以带锚文本的网站,兰州网站建设方案方法区和永久代的关系
方法区与 Java 堆一样#xff0c;是各个线程共享的内存区域#xff0c;它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分#xff0c;但是它却有一个别名叫做 N…方法区和永久代的关系
方法区与 Java 堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然 Java 虚拟机规范把方法区描述为堆的一个逻辑部分但是它却有一个别名叫做 Non-Heap非堆目的应该是与 Java 堆区分开来。
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用并没有规定如何去实现它。那么在不同的 JVM 上方法区的实现肯定是不同的了。 方法区和永久代的关系很像 Java 中接口和类的关系类实现了接口而永久代就是 HotSpot 虚拟机对虚拟机规范中方法区的一种实现方式。 也就是说永久代是 HotSpot 的概念方法区是 Java 虚拟机规范中的定义是一种规范而永久代是一种实现一个是标准一个是实现其他的虚拟机实现并没有永久代这一说法。
方法区实在虚拟机规范里面被定义的不同的虚拟机对这个定义的实现不同方法区是jvm规范中定义的永久代是虚拟机厂商HotSpot 对方法区的具体的实现在别的jvm实现的厂商中就有可能不是叫永久代。在HotSpot 虚拟机中在 jdk1.7 版本之前的方法区实现叫永久代PermGen spacejdk1.8 之后叫做元空间Metaspace。
主要存放class和元数据的信息class被加载的时候就会被放入永久代gc不会在主程序运行期间对永久代进行清理这样会导致一个问题就是永久代区域会随着加载的class的增多而胀满最终抛出OOM异常
新生代和老年代
jvm中的堆分为新生代和老年代。
新生代用来存放新生的对象新生代中的对象朝生夕死所以会频繁的触发 minor 脉了GC 进行垃圾回收。新生代分为 eden 区、survivor from 区和 survivor to 区。eden区是java新对象的出生地如果新创建的对象占用内存很大的话就会直接分配到老年代。当eden区的内存不足时就会触发 minor gc 对新生代进行一次垃圾回收。survivor from 区存放的是上一次minor gc 的幸存者它将作为这一次gc的被扫描者。survivor to 区会保留这一次gc的幸存者。新生代 minor gc 的流程是它采用的复制算法首先eden区和survivor from区中存活的对象复制到survivor to区域并将它们的年龄加一。然后清空eden区和survivor from区中的对象接着将survivor from和survivor to互换也就是原先的survivor to成为下一次gc时的survivor from。这样要注意的是如果有对象的年龄达到了老年代的标准就放进老年代如果survivor to区域的空间不够的话就会通过分配担保机制将多出来的对象提前转到老年代但老年代要进行担保的前提是自己本身还有容纳这些对象的剩余空间由于无法提前知道会有多少对象存活下来所以这里是取之前每次晋升到老年代的对象的平均大小作为经验值与老年代的剩余空间做比较老年代主要存放生命周期较长的内存对象所以不会频繁的进行垃圾回收。老年代采用的是标记清除算法也就是首先扫描一次老年代标记出存活对象然后回收没有标记的对象。
java8之前jvm堆中还有一块称作永久代的区域主要存放class和元数据的信息class被加载的时候就会被放入永久代gc不会在主程序运行期间对永久代进行清理这样会导致一个问题就是永久代区域会随着加载的class的增多而胀满最终抛出OOM异常。
java8移除了永久代取而代之的是一个叫做元数据区的概念也叫做元空间。元空间和永久代是类似的但它们最大的区别是元空间并不在虚拟机中而是使用的本地内存因此默认情况下元空间的大小仅受本地内存的限制。也就是类的元数据放入本地内存中字符串池和类的静态变量放入java堆中这样可以加载多少类的元数据就由系统实际可用空间来控制了。
为什么移除永久代
大致意思就是说为了 JRockit 和 Hotspot 融合工作JRockit客户不需要配置永久代因为JRockit没有永久代
除了为了融合适配移除永久代以外还有其他原因 永久代设置空间大小是很难确定的因为可能某个实际的业务场景中有不断的类加载等工作但是元空间时使用本地内存默认情况下时手本地大小限制的。 调优困难一般来说这个区域的回收效果比较难令人满意尤其是类型的卸载条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。方法区的垃圾收集主要回收两部分内容常量池中废弃的常量和不在使用的类型。
JVM 内存模型 堆和方法区逻辑上是分开的但是在物理内存上两者又是连续的 再精确一些的话实际上是 java7之前方法区和老年代是相连的所以永久代的垃圾收集是和老年代捆绑在一起的因此无论谁满了都会触发永久代和老年代的垃圾收集。
在Java8中元空间(Metaspace)登上舞台方法区存在于元空间(Metaspace)。同时元空间不再与堆连续而且是存在于本地内存Native memory也称作直接内存当Java Heap空间不足时会触发GC但Native memory空间不够却不会触发GC 元空间不会触发fullGC 元空间保存在本地内存中的好处是什么呢
原因一因为直接内存JVM将会在IO操作上具有更高的性能因为它直接作用于本地系统的IO操作。而非直接内存也就是堆内存中的数据如果要作IO操作会先复制到直接内存再利用本地IO处理。 从数据流的角度非直接内存是下面这样的作用链本地IO -- 直接内存 -- 非直接内存 -- 直接内存 -- 本地IO
而直接内存是本地IO -- 直接内存 -- 本地IO
原因二整个永久代有一个 JVM 本身设置固定大小上线无法进行调整而元空间使用的是直接内存受本机可用内存的限制并且永远不会得到java.lang.OutOfMemoryError。
设置元空间大小
可以使用 -XXMaxMetaspaceSize 标志设置最大元空间大小默认值为 unlimited这意味着它只受系统内存的限制。 -XXMetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
JVM 常用配置参数(Java 8)
日志 -XX:PrintFlagsFinal打印JVM所有参数的值 -XX:PrintGC打印GC信息 -XX:PrintGCDetails打印GC详细信息 -XX:PrintGCTimeStamps打印GC的时间戳 -Xloggc:filename设置GC log文件的位置 -XX:PrintHeapAtGC查看 GC 前后的堆、方法区可用容量变化 -XX:PrintTenuringDistribution查看熬过收集后剩余对象的年龄分布信息 -XX:PrintGCApplicationConcurrentTime -XX:PrintGCApplicationStoppedTime 查看 GC 过程中用户线程并发时间以及停顿的时间 参考文档 https://www.javanav.com/val/acbb4071b64240b49145a1baf7856551.html
dump 设置 -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/tmp/heapdump.hprof当 OOM 发生时自动 dump 堆内存信息到指定目录 内存设置 -Xms设置堆的初始化内存大小 -Xmx设置堆的最大内存 -Xmn设置新生代内存大小 -Xss设置线程栈大小 -XX:NewRatio新生代与老年代比值 -XX:SurvivorRatio新生代中Eden区与两个Survivor区的比值默认为8即Eden:Survivor:Survivor8:1:1 -XX:MaxTenuringThreshold从年轻代到老年代最大晋升年龄。CMS 下默认为 6G1 下默认为 15 -XX:MetaspaceSize设置元空间的大小第一次超过将触发 GC -XX:MaxMetaspaceSize元空间最大值 -XX:MaxDirectMemorySize用于设置直接内存的最大值限制通过 DirectByteBuffer 申请的内存 -XX:ReservedCodeCacheSize用于设置 JIT 编译后的代码存放区大小如果观察到这个值有限制可以适当调大一般够用即可 设置垃圾收集相关 -XX:UseSerialGC设置串行收集器 -XX:UseParallelGC设置并行收集器 -XX:UseConcMarkSweepGC使用CMS收集器 -XX:ParallelGCThreads设置Parallel GC的线程数 -XX:MaxGCPauseMillisGC最大暂停时间 ms -XX:UseG1GC使用G1垃圾收集器 CMS 垃圾回收器相关 -XX:UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction与前者配合使用指定MajorGC的发生时机 -XX:ExplicitGCInvokesConcurrent代码调用 System.gc() 开始并行 FullGC建议加上这个参数 -XX:CMSScavengeBeforeRemark表示开启或关闭在 CMS 重新标记阶段之前的清除YGC尝试它可以降低 remark 时间建议加上 -XX:ParallelRefProcEnabled可以用来并行处理 Reference以加快处理速度缩短耗时 G1 垃圾回收器相关 -XX:MaxGCPauseMillis用于设置目标停顿时间G1 会尽力达成 -XX:G1HeapRegionSize用于设置小堆区大小建议保持默认 -XX:InitiatingHeapOccupancyPercent表示当整个堆内存使用达到一定比例默认是 45%并发标记阶段就会被启动 -XX:ConcGCThreads表示并发垃圾收集器使用的线程数量默认值随 JVM 运行的平台不同而变动不建议修改