前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >选择JDK1.8的理由之JVM内存变化

选择JDK1.8的理由之JVM内存变化

作者头像
用户1212940
发布2022-04-13 15:25:05
4810
发布2022-04-13 15:25:05
举报
文章被收录于专栏:Lambda

jvm运行时内存区域主要分为:程序计数器,jvm栈,本地方法栈,堆,方法区。

一、JVM中内存

JVM中内存通常划分为两个部分,分别为堆内存栈内存, 栈内存主要用执行线程方法,存放本地临时变量与线程中方法执行时候需要的引用对象地址

JVM所有的对象信息都存放在堆内存中,相比栈内存,堆内存可以大的多,所以JVM一直通过对堆内存划分不同的功能区块实现对堆内存中对象管理。

堆内存不够最常见的错误就是OOM(OutOfMemoryError)

栈内存溢出最常见的错误就是StackOverflowError,程序有递归调用时候最容易发生

二、堆内存划分

在JDK7以及其前期的JDK版本中,堆内存通常被分为三块区域Nursery内存(young generation)、长时内存(old generation)、永久内存(Permanent Generation for VM Matedata),显示如下图:

其中最上一层是Nursery内存,一个对象被创建以后首先被放到Nursery中的Eden内存中,如果存活期超两个Survivor之后就会被转移到长时内存中(Old Generation)中

永久内存中存放着对象的方法、变量等元数据信息。通过如果永久内存不够,我们就会得到如下错误:

java.lang.OutOfMemoryError: PermGen

而在JDK8中情况发生了明显的变化,就是一般情况下你都不会得到这个错误,原因在于JDK8中把存放元数据中的永久内存从堆内存中移到了本地内存(native memory)中,JDK8中JVM堆内存结构就变成了如下:

这样永久内存就不再占用堆内存,它可以通过自动增长来避免JDK7以及前期版本中常见的永久内存错误(java.lang.OutOfMemoryError: PermGen),也许这个就是你的JDK升级到JDK8的理由之一吧。当然JDK8也提供了一个新的设置Matespace内存大小的参数,通过这个参数可以设置Matespace内存大小,这样我们可以根据自己项目的实际情况,避免过度浪费本地内存,达到有效利用。

-XX:MaxMetaspaceSize=128m设置最大的元内存空间128兆

注意:如果不设置JVM将会根据一定的策略自动增加本地元内存空间。 如果你设置的元内存空间过小,你的应用程序可能得到以下错误: java.lang.OutOfMemoryError: Metadata space

  • jdk8移除了PermGen,取而代之的是MetaSpace元空间(Metaspace): 一种新的内存空间的诞生。JDK8 HotSpot JVM 使用本地内存来存储类元数据信息并称之为:元空间(Metaspace);这与Oracle JRockit 和IBM JVM’s很相似。这将是一个好消息:意味着不会再有java.lang.OutOfMemoryError:PermGen问题,也不再需要你进行调优及监控内存空间的使用,但是新特性不能消除类加载器导致的内存泄漏。你需要使用不同的方法以及遵守新的命名约定来追踪这些问题。
  • PermGen 空间的状况 这部分内存空间将全部移除。

JVM的参数:PermSize 和 MaxPermSize 会被忽略并给出警告(如果在启用时设置了这两个参数)。

  • Metaspace 内存分配模型 (最大区别)大部分类元数据都在本地内存中分配。 用于描述类元数据的“klasses”已经被移除。
  • Metaspace 容量 默认情况下,类元数据只受可用的本地内存限制(容量取决于是32位或是64位操作系统的可用虚拟内存大小)。
  • 新参数(MaxMetaspaceSize) 用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整。
  • Metaspace 垃圾回收 对于僵死的类及类加载器的垃圾回收将在元数据使用达到“MaxMetaspaceSize”参数的设定值时进行。 适时地监控和调整元空间对于减小垃圾回收频率和减少延时是很有必要的。持续的元空间垃圾回收说明,可能存在类、类加载器导致的内存泄漏或是大小设置不合适。 Java 堆内存的影响一些杂项数据已经移到Java堆空间中。升级到JDK8之后,会发现Java堆 空间有所增长。
  • Metaspace 监控 元空间的使用情况可以从HotSpot1.8的详细GC日志输出中得到。

Jstat 和 JVisualVM两个工具,在我们使用b75版本进行测试时,已经更新了,但是还是能看到老的PermGen空间的出现。

  • 参数设置 默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

-XX:MetaspaceSize,初始空间大小,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize时,适当提高该值。

-XX:MaxMetaspaceSize,最大空间,默认是没有限制的。

除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性: -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为分配空间所导致的垃圾收集

-XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为释放空间所导致的垃圾收集

  • 更新原因 1、字符串存在永久代中,容易出现性能问题和内存溢出。 2、类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代(就小了)溢出。 3、永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。 4、Oracle 可能会将HotSpot 与 JRockit 合二为一。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/09/21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、JVM中内存
  • 二、堆内存划分
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档