一:永久代(jdk1.7)
说起JAVA的运行时数据区在java7和java8中还是有着很大的不同,最大的不同点就是在java7中还有着"永久代",而"永久代"保存的是在Java虚拟机(JVM)内部,class文件中包括类的版本、字段、方法、接口等描述信息,还有运行时常量池,用于存放编译器生成的各种字面量和符号引用。在之前大不部分的类都是"static"的,这些类很少被卸载和被收集,因此被称为永久的
在java8之前的HotSpot JVM擦才有着"永久代"这一概念。永久代是一片连续的堆空间,在JVM启动之前可以通过设置-XX:MaxPermSize参数,来调整永久代最大可分配的内存大小。调整初始化大小的参数为-XX:PermSize
二:方法区
《Java虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。在不同的JVM虚拟机上方法区的实现都是不同的,而在HotSpot中,永久代就是方法区的实现,其他的虚拟机实现并没有永久带这一说法,HotSpot使用GC分代来实现方法区内存回收。
三:Metaspace元空间(jdk1.8)
在JAVA8中HotSpots JVM移除了"永久代",取而代之的是一个叫做"元空间",对于java8而言,"元空间"是"方法区"在java8中一种新的实现。
"元空间"和"永久代"的区别:
存储位置不同——永久代物理是是堆的一部分,和新生代、老年代地址是连续的,而元空间属于本地内存
存储数据不同——JDK1.8对JVM架构的改造将类元数据放到本地内存中,将常量池和静态变量放到Java堆里。
其实,移除永久代的工作从JDK 1.7就开始了。JDK 1.7中,存储在永久代的部分数据就已经转移到Java Heap或者Native Heap。但永久代仍存在于JDK 1.7中,并没有完全移除,譬如符号引用(Symbols)转移到了native heap;字面量(interned strings)转移到了Java heap;类的静态变量(class statics)转移到了Java heap。
四:运行时数据区
简单介绍
一:堆——堆是所有线程共享的 堆是jvm内存管理的最大的一块区域,此内存区域的唯一目的就是存放对象的实例,所有对象实例与数组都要在堆上分配内存。它也是垃圾收集器的主要管理区域。。堆中可分成"新生代"和"老年代"两个区域,而"新生代"中又分为了一个Eden区和两个Suvivor区,默认空间占比为8:1:1。
如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将抛出OutOfMemoryError异常。
二:栈——栈是线程独享的,它的生命周期与线程相同。每个方法在执行的同时都会创建一个"栈帧",用于存储局部变量表、操作数栈、动态链接、方法出口等信息
三:本地方法栈——本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。一般来说就是调用其他语言实现的方法。
四:程序计数器——程序计数器(Program Counter Register)是一块较小的内存空间,它可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
由于Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器(对于多核处理器来说是一个内核)只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
五:元空间——metaspace其实由两大部分组成
● Klass Metaspace 来存klass的,klass是我们熟知的class文件在jvm里的运行时数据结构
● NoKlass Metaspace 专门来存klass相关的其他的内容,比如method,constantPool(常量池)等
五:JVM常用参数
-Xms 初始堆内存大小,默认物理内存64/1
-Xms = -XX:InitialHeapSize
-Xmx 最大堆内存,默认物理内存4/1
-Xmx = -XX:MaxHeapSize
-Xss 栈内存大小
设置单个线程栈大小,一般默认512~1024kb。
单个线程栈大小跟操作系统和JDK版本都有关系
-Xss = -XX:ThreadStackSize
-Xmn 年轻代大小
-XX:MetaspaceSize 元空间大小
元空间本质跟永久代类似,都是对JVM规范中方法区的实现。
不过元空间与永久代最大的区别在于:元空间并不在虚拟机中,而是使用本机内存。
因此,元空间大小仅受本地内存限制。
-XX:+PrintGCDetails 打印GC详细日志信息
-XX:SurvivorRatio 幸存者比例设置
-XX:NewRatio 新生代比例设置
-XX:MaxTenuringThreshold 进入老年代阈值设置