java虚拟机 JVM详解 内部原理 (小白必看)

揭开 java平台的神秘面纱
导读
        一个java程序员的水平高低最终取决于对 JVM (java虚拟机) 的了解程度 .
         首先这篇文章带大家对 JVM 进行一个初步的了解 ,从下面两个问题进行解剖 。


         1 . 什么是JVM ?
         2 . JVM有什么用 ?

一 . 什么是 JVM ?
了解什么是JVM之前先简单说下什么是Java ?, 啥是Java很难用一句话来概括,我们从四个方面来阐述 .
        语言 : 作为世界上最流行的编程语言,Java可以编写C/S、 B/S模式的软件。语法由Java Language Specification规定。
        平台 : 作为一个开发平台,以JVM为基础,除Java外还有Groovy,Scala, Kotlin, JRuby,Clojure, Jython等语言。 虚拟机内部机制由Java Virtual Machine Specification规定。
        文化 : 作为一种文化,Java几乎成为可“开源”的代名词.
        生态 : 作为生态,Java拥有世界最多的技术拥护者和开源社区的支持。从桌面应用软件、嵌入式开发到企业级应用、后台服务、中间件都可以看到Java的身影.

大家学习 Java 的过程中,相信都会有了解到 JDK 和 JRE 这两个东西 , 我们要讲的 JVM 就属于 JRE当中的. 为什么叫做虚拟机呢 ? (如下图所示 : ) 因为 java 程序是在 java虚拟机中运行 ,通过JVM 来对 class文件进行翻译给操作系统执行 , 官方提供了不同操作系统上的 JVM . 在这里JVM相当于充当了翻译官的角色 , 也使java 有跨平台这个特性.[C语言、汇编语言等古老的语言不能跨平台] ,也对应了它的口号 “一次编译,到处执行”.
在这里插入图片描述
在这里插入图片描述


二 . JVM 有什么作用 ?
        JVM 由 三个主要部件构成 :
                ① 类加载器 ② 运行时数据区 ③ 执行引擎

(1) 类加载器 [ClassLoader] :
        它负责在运行时查找和装入类文件的类 , JVM里有多个类加载器 , 每个类加载器负责加载特定位置的类.(如下图:) 例如
    引导类加载器(bootstrap) : 负责加载 jre/lib/rt.jar 中的类
    扩展类加载器(extclassloader) : 负责加载 jre/lib/ext/*.jar 中的类
    系统类加载器(appclassloader) : 负责 classspath 指定的目录或 jar 中的类

为什么要分成不同的类加载器呢? 主要为了安全性,打个比方如果一个有恶意class文件类并且路径伪装下,它要被加载的话首先会通过系统类加载器进行加载 ,加载器发现此类不符它的加载范围,会给它上一级扩展类加载器,因为每个加载器都有特定的加载范围,到最后这个类都不符合.就算在系统类加载器中加载了,也不会影响到JVM主要的类文件.

在这里插入图片描述

(2) 运行时数据区 [Runtime Data Area] :
        Java虚拟机在执行Java程序的过程中会把它管理的内存划分为若干个不同的数据区域.(如下图:)
主要分为五大区域块 :
    方法区 (Method Area) : 这是一块公共区域 , 它存放一些加载后的类信息(有类的版本、字段、方法、接口等描述信息)、常量、静态变量等信息.
Java虚拟机规范规定,当方法区无法满足内存分配的需求时,将抛出 OutOfMemoryError 异常。

    堆区 (Heap Area) : 堆也是被所有线程共享的一块区域,在JVM启动时创建 , 它存放对象实例,几乎所有的对象实例都在这里分配内存, 这块区域也是 GC(垃圾回收机制) 重点清理的区域 , 当堆中的内存无法分配给示例时,会抛出OutOfMemoryError异常。
    虚拟机栈(VM Stack) : 它描述的是Java方法执行的内存模型 , 当执行一个方法时会创建一个栈帧 , 栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息 , 基本变量和对象的引用变量都存放于此.栈中执行顺序是 “后入先出(LIFO)” 这里打个比方:当一个Main方法调用另A方法,这时会创建两个栈帧先执行的Main方法会最后出这个栈,而A方法执行完后会先出栈,则A方法被销毁. 总的来说 一个方法的入栈出栈就表示着一个方法从调用到执行完成的过程 , 栈是线程私有的,它的生命周期与线程相同,Java虚拟机规范对这个区域规定了两种异常情况 :
    ①如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常
    ②如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常.(当前大部分JVM都可以动态扩展,只不过JVM规范也允许固定长度的虚拟机栈)

    程序计数器(Program Counter Register) : 首先它是线程私有区域 , 它存储或说记录当前线程之前执行的任务状态,等线程抢到CPU时间片时,继续未完成的任务.[也称为PC寄存器]
    本地方法栈(Native Method Stack) : 用于JNT调用等 ,.JNI技术,java调用c语言等其它语言开发的函数,本地方法栈中也会抛出StackOverflowErrorOutOfMemory异常.该区域不受 GC 所管制.

[运行时数据区图:]
在这里插入图片描述
[方法区示意图:]
在这里插入图片描述
[虚拟机栈图:]
在这里插入图片描述

[栈帧出入示意图:]在这里插入图片描述
(3) 执行引擎 [Runtime Data Area] : (如下图所示) 执行引擎 将字节码分配给运行时数据区 , 执行引擎读取字节码并逐段执行.其中图中的
本地接口 (JNI): JNI 会与本地方法库进行交互并提供执行引擎所需的本地库。
本地方法库:它是一个执行引擎所需的本地库的集合。
在这里插入图片描述下面咱们来看一段代码:

public class Test1 {

 public static int num = 1;  //类变量会存放在方法区中
 
 public void method1(){
   /*
   在这个方法中创建了一个对象,但是会在内存中产生两个相关数据.
   我们知道等号左边的对象是等号右边的一个引用, 左边的引用是存放在
   此方法栈帧中的,而右边的Test2则是一个实例对象,所以它存放在堆区中.
   */
   Test2 test2 = new Test2();
 } 
}

相信看到这里大家对JVM有了一个初步的了解 , 在我们遇到的所有java问题都可以追溯到JVM中.今天的分享就到这里,后续还会继续更新相关内容,感谢大家 !
想了解 java GC机制的可看看 上一篇 博客内容 ==>>
GC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值