网站开发前途,查询网站所有关键词排名,网页设计实例,外贸建站哪家强外贸网站怎么做前言#xff1a; java虚拟机再执行Java程序的时候把它所拥有的内存区域划分了若干个数据区域。这些区域有着不同的功能#xff0c;各司其职。这些区域不但功能不同#xff0c;创建、销毁时间也不同。有些区域为线程私有#xff0c;如#xff1a;每个线程都有自己的程序计数… 前言 java虚拟机再执行Java程序的时候把它所拥有的内存区域划分了若干个数据区域。这些区域有着不同的功能各司其职。这些区域不但功能不同创建、销毁时间也不同。有些区域为线程私有如每个线程都有自己的程序计数器则程序计数器随着用户线程创建而创建随其销毁而销毁。而有些区域是所有线程共有的如堆是被所有线程所共有的。根据《java虚拟机规范》的规定java虚拟机所管理的内存将会包括以下几个运行时数据区域 注意JVM可以说是一套规范。
下面我来分别详细介绍这五个区域。 1.程序计数器线程隔离 程序计数器是一块较小的内存空间。它的作用是记录这个线程下一个指令的位置。Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的。在多线程当中线程在执行完自己所被分配到的时间片后会被切换线程我们无法保证线程执行完毕后再被切换时间片的大小是不确定的。为了保证线程切换回来后能恢复到正确的执行位置。所以我们需要程序计数器为我们记录下一条指令的地址等线程重新抢回CPU时去这个程序计数器当中取到下一条指令的地址继续往下执行这就是程序计数器的主要作用。所以每个线程都需要自己的程序计数器互不影响。所以程序计数器是线程私有的。 总结来说它是程序控制流的指示器分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个程序计数器来完成。 2.java虚拟机栈线程隔离 虚拟机栈和程序计数器一样都是线程私有的生命周期与其对应的线程相同。这个虚拟机栈内部保存一个个的栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法返回等信息。每一个方法从开始执行到执完毕都代表着一个栈帧再虚拟机栈中入栈到出栈。它于虚拟机执行时方法调用和方法执行时的数据结构它是虚拟栈的基本元素。 在栈帧中的局部变量表中存放着基本数据类型数据和对像引用。这个基本类型是确确实实的存储再栈帧中而对象引用在这里存的不是真正意义上的对象可能是一个指向对象起始地址的引用指针也可能是指向对象的那个句柄或者其他与此对象相关的位置。 这些数据在局部变量表中存储空间大小以局部变量槽(Slot)来表示。除了double、long类型的数据占两个变量槽之外其余数据类型占的是一个变量槽。所以说这个方法需要多大的局部变量空间在刚调用这个方法就已经确定了。在方法运行期间不会改变局部变量表的大小。
在这个数据区域规定了两种异常情况
StackOverflowError异常当线程申请线程深度大于Java虚拟机所允许的深度就会报这个异常。OutOfMemoryError异常当虚拟机栈可以动态扩展的时候无法申请到足够大的深度时就会报这个异常。 3.本地方法栈线程隔离 这个区域和虚拟机栈差不多。两者不同的是虚拟机栈为虚拟机执行的是java(也就是字节码)方法而本地方法栈为虚拟机执行的是用于执行本地非Java方法。甚至有一些虚拟机将虚拟机栈和本地方法栈合二为一。与虚拟机栈一样本地方法栈也会在栈深度溢出或者栈扩展失 败时分别抛出StackOverflowError和OutOfMemoryError异常。 4.java堆线程共享 堆是JVM中最大的一块内存区域。堆是所有线程共享的区域在堆中对象的创建和销毁都是由垃圾回收器自动管理的。它在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例Java 世界里“几乎”所有的对象实例都在这里分配内存。但还是有些情况下不是在堆上的。 方法内联优化在某些情况下编译器会进行方法内联优化将方法的调用直接替换为方法体内的代码。这种优化可以使得对象实例的创建在栈上进行而不是在堆上。这种情况下对象实例的生命周期可能会比较短暂。 线程私有对象有些对象只被某个线程所拥有并且不会被其他线程访问。这样的对象可以在栈上分配从而实现更高效的内存访问。 Java堆既可以被实现成固定大小的也可以是可扩展的不过当前主流的Java虚拟机都是按照可扩 展来实现的如果在Java堆中没有内存完成实例分配并且堆也无法再 扩展时Java虚拟机将会抛出OutOfMemoryError异常。 5.方法区线程共享
其实方法区是在JDK1.8以前的版本里存在的一块内存区域主要就是存放从class文件里加载进来的类的而且常量池也是在这块区域内的。
但是在JDK1.8之后这块区域摇身一变换了名字叫做“Metaspace”翻译过来就是“元数据空间”的意思当然它只是改了个名实现的功能是没变的。
方法区Method Area与Java堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。 5.1 类型信息
对每个加载的类型类class、接口interface、枚举enum、注解annotation),JVM必须在方法区中存储以下类型信息: ①这个类型的完整有效名称全名包名.类名) ②这个类型直接父类的完整有效名(对于interface或是java.lang.0bject都没有父类) ③这个类型的修饰符(public, abstract,final的某个子集) ④这个类型直接接口的一个有序列表
5.2域信息(Field)成员变量
JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。 域的相关信息包括:域名称、域类型、域修饰符(public, private,protected,static,final, volatile, transient的某个子集)
5.3方法(Method)信息
JVM必须保存所有方法的以下信息同域信息一样包括声明顺序:
方法名称方法的返回类型(或void)·方法参数的数量和类型(按顺序)方法的修饰符(public, private,protected,static, final,synchronized,native,abstract的一个子集)方法的字节码(bytecodes)、操作数栈、局部变量表及大小(abstract和native方法除外)