JVM——Java虚拟机架构

5 篇文章 1 订阅

一、基础概念

`Java虚拟机`(Java virtualmachine)实现了Java语言最重要的特征:即`平台无关性`。

平台无关性`原理`:
编译后的 Java程序(.class文件)由 JVM执行。
JVM屏蔽了与具体平台相关的信息,使程序可以在多种平台上不加修改地运行。
Java虚拟机在'执行字节码'时,把字节码'解释'成具体平台上的机器指令执行。
因此实现`Java平台无关性`

二、JVM结构图理解

在这里插入图片描述

`JVM` = '类加载器 classloader' + '执行引擎 executionengine' + '运行时数据区域 runtime data area'
首先Java源代码文件被Java编译器编译为字节码文件,
然后JVM中的类加载器加载完毕之后,交由JVM执行引擎执行。
在整个程序执行过程中,JVM中的`运行时数据区(内存)`会用来存储程序执行期间需要用到的数据和相关信息。

因此,在Java中我们常常说到的`内存管理`就是针对这段空间进行管理('如何分配和回收内存空间')。

三、类加载器(Class Loader)

Classloader把硬盘上的class文件加载到JVM中的`运行时数据区域`,但是它不负责这个类文件能否执行,而这个是`执行引擎`负责的。

加载类的机制原理:

双亲委派模型以及自定义类加载器:

四、执行引擎

作用:执行`字节码`'或者执行本地方法'

五、Runtime DataArea(运行时数据区)

JVM在运行期间,在运行时数据区对JVM内存空间的划分和分配,划分为了以下`几个区域来存储`

在这里插入图片描述

'其中红色部分为线程私有的,即每个线程各自都有一份。蓝色部分为线程共享的'

(图注:JDK1.7已经把常量池转移到堆里面了!)

`PC寄存器(The PC Register)`

Java 虚拟机可以支持多条线程同时执行(可参考《Java 语言规范》第 17 章),每一条 Java 虚拟机线程都有自己的 PC(Program Counter)寄存器。
在任意时刻,一条 Java 虚拟机线程 只会执行一个方法的代码,这个正在被线程执行的方法称为该线程的当前方法(Current Method)。
如果这个方法不是 native 的,那 PC 寄存器就保存 Java 虚拟机正在执行的 字节码指令的地址,如果该方法是 native 的,
那 PC 寄存器的值是 undefined。PC 寄存器的容 量至少应当能保存一个 returnAddress 类型的数据或者一个与平台相关的本地指针的值。 
此内存区域是唯一一个在JVM中没有规定任何OutOfMemoryError情况的区域。

`JVM栈(Java Virtual MachineStacks)`

(1)JVM栈是线程私有的,并且生命周期与线程相同。并且当线程运行完毕后,相应内存也就被'自动回收'。
(2)栈里面存放的元素叫栈帧,每个方法从调用到执行结束,其实是对应一个栈帧的入栈和出栈。
     栈帧用于存储执行方法时的一些数据,如局部变量表、操作数栈(执行引擎计算时需要),方法出口等等。
(3)这个区域可能有两种异常:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
    (如:将一个函数反复递归自己,最终会出现这种异常)。如果JVM栈可以动态扩展(大部分JVM是可以的),
          当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。

`本地方法栈(Native Method Stacks)`

(1)本地方法栈与JVM栈的作用很相似,他们的区别在于'虚拟机栈是为执行Java代码方法服务',而本地方法栈是为'Native方法服务'。
(2)和JVM栈一样,这个区域也会抛出StackOverflowError和OutOfMemoryError异常。

`方法区(Method Area)`

(1)方法区域是全局共享的,比如每个线程都可以访问同一个类的静态变量。在方法区中,存储了已被'JVM加载的类的信息、静态变量、编译器编译后的代码'等。
     如,当程序中通过getName、isInterface等方法来获取信息时,这些数据来源于方法区。
(2)由于使用'反射机制'的原因,虚拟机很难推测哪个类信息不再使用,因此'这块区域的回收很难'!
     另外,对这块区域主要是针对常量池回收,值得注意的是JDK1.7已经把常量池转移到堆里面了。
(3)同样,当方法区无法满足内存分配需求时,会抛出'OutOfMemoryError'`运行时常量池(Runtime Constant Pool)`

(1)存放类中固定的常量信息、方法引用信息等,其空间从方法区域(JDK1.7后为堆空间)中分配。
(2)Class文件中除了'有类的版本、字段、方法、接口等描述信息外',还有就是常量表,用于'存放编译期已可知的常量',
     这部分内容将在类加载后进入'方法区(永久代)'存放。但是Java语言并不要求常量一定只有编译期预置入Class的常量表的内容才能进入方法区常量池,
     '运行期间也可将新内容放入常量池(最典型的String.intern()方法)'。
(3)当常量池无法在申请到内存时会抛出OutOfMemoryError异常,上面也分析过了。

`Java堆`

(1)Java堆是JVM所管理的最大的一块内存。它是被所有线程共享的一块内存区域,在虚拟机启动时创建。
(2)几乎所有的实例对象都是在这块区域中存放。(JIT编译器貌似不是这样的)。
(3)Java堆是'垃圾收集管理的主要战场'。所有Java堆可以细分为:新生代和老年代。
     再细致分就是把新生代分为:Eden空间、FromSurvivor空间、To Survivor空间。
     JVM具体的垃圾回收机制总结请查看另外一篇:

JVM——内存管理和垃圾回收学习整理

(4)根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。
    如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。

jdk版本升级后这部分的相关改进

JDK 1.7 和 1.8 将字符串常量由永久代转移到堆中,并且 JDK 1.8 中已经不存在永久代的结论。现在我们看看元空间到底是一个什么东西?

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。
不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。
因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:

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

  除了上面两个指定大小的选项以外,还有两个与 GC 相关的属性:  

     -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,
     减少为分配空间所导致的垃圾收集   
     -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,
     减少为释放空间所导致的垃圾收集
引用自文章:https://blog.csdn.net/hk10066/article/details/83783917

六、堆和栈的区别

`(1)各司其职`
  最主要的区别就是栈内存用来存储局部变量和方法调用信息。
  而堆内存用来存储Java中的对象。无论是成员变量、局部变量还是类变量,它们指向的对象都存储在堆内存中。

`(2)空间大小`
  栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满并产生StackOverFlowError。
  关于如何设置堆栈内存的大小,可以查看JVM——内存管理和垃圾回收中的相关介绍。

`(3)独有还是共享`
  栈内存归属于线程的私有内存,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见。
  而堆内存中的对象对所有线程可见,可以被所有线程访问。

`(4)异常错误`
  如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
  如果JVM栈可以动态扩展(大部分JVM是可以的),当扩展时无法申请到足够内存则抛出OutOfMemoryError异常。
  而堆内存没有可用的空间存储生成的对象,JVM会抛出java.lang.OutOfMemoryError。
静态的成员变量与非静态的成员变量的区别:
1. 作用上的区别:
1. 静态的成员变量的作用共享一个 数据给所有的对象使用。
2. 非 静态的成员变量的作用是描述一类事物的公共属性。
2. 数量与存储位置上的区别:
1. 静态成员变量是存储方法 区内存中,而且只会存在一份数据。
2. 非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。
3. 生命周期的区别:
1. 静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。
2.非静态的成员数据是随着对象的创建而存在,随着 对象被垃圾回收器回收而消失。

参考链接:

http://blog.csdn.net/seu_calvin/article/details/51404589

https://www.cnblogs.com/huansky/p/11970503.html

https://blog.csdn.net/oguro/article/details/53008848

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值