一、JVM内存区域划分 (2)

方法区和Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。在JDK1.7中使用永久代实现方法区,JDK1.8中改为使用元空间实现方法区。
       JDK1.7中方法区的实现:在JDK1.7中,使用永久代来实现方法区,永久代实际上是使用了堆中的一部分内存,永久代的大小可以通过-XX:PermSize 和 -XX:MaxPermSize设置,比如-XX:PermSize=64m -XX:MaxPermSize=128m;当永久代内存不够时会抛出OutOfMemoryError:PermGen异常。
       JDK1.8中方法区的实现:在JDK1.8中,去掉了堆中的永久代,使用元空间(使用本地内存)来实现方法区,可以使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize来设置元空间的大小,比如-XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m,如果没有设置,元空间大小会根据应用程序在运行时的需求进行调整,如果设置过小,会抛出OutOfMemoryError:Metadata space异常。
       废弃永久代的原因:一是:移除永久代可以促进HotSpot JVM与JRockit VM的融合,因为JRockit没有永久代;二是:由于永久代内存经常不够用或发生内存泄露,爆出OutOfMemoryError:PermGen异常。

7、运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中。运行时常量池做为方法区的一部分,内存收到方法区的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。
       字符串常量池和String.intern()方法:深入分析String#intern

8、直接内存(Direct Memory)

直接内存并不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域;在JDK1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。直接内存的容量通过-XX:MaxDirectMemorySize指定,比如-XX:MaxDirectMemorySize=256m;如果不指定,则默认与Java堆最大值(-Xmx)一样。

9、各内存区域常用参数 内存区域 JDK1.7 JDK1.8
  -Xss比如-Xss128k   -Xss比如-Xss128k  
  -Xms和-Xmx比如-Xms128m -Xmx256m   -Xms和-Xmx比如-Xms128m -Xmx256m  
TLAB   -XX:+/-UseTLAB比如-XX:+UseTLAB   -XX:+/-UseTLAB比如-XX:+UseTLAB  
新生代   -XX:NewSize、-XX:MaxNewSize、-Xmn、-XX:NewRatio   -XX:NewSize、-XX:MaxNewSize、-Xmn、-XX:NewRatio  
Eden、Survivor   -XX:SurvivorRatio比如-XX:SurvivorRatio=8   -XX:SurvivorRatio比如-XX:SurvivorRatio=8  
方法区   -XX:PermSize 和 -XX:MaxPermSize   -XX:MetaspaceSize和-XX:MaxMetaspaceSize  
字符串常量池   -XX:StringTableSize   -XX:StringTableSize  
直接内存   -XX:MaxDirectMemorySize   -XX:MaxDirectMemorySize  
10、从另一个角度看JVM内存

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzydjj.html