广告
返回顶部
首页 > 资讯 > 精选 >深入浅析Java中 JVM的原理
  • 399
分享到

深入浅析Java中 JVM的原理

javajvmava 2023-05-31 16:05:14 399人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关深入浅析Java中 JVM的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真

这篇文章将为大家详细讲解有关深入浅析Java中 JVM的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。是运行Java应用最底层部分。

JDK(Java Development kit)

整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具(编译,debug等)和Java基础的类库(rt.jar)。是开发java应用的基础。

JRE(Java Runtime Environment,Java运行环境)

运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。运行java应用的基础。

J2SE(Java 2 Platform,Standard Edition)。

包含那些构成Java语言核心的类。比如:数据库连接、接口定义、输入/输出、网络编程

J2EE(Java 2 Platform,Enterprise Edition)。

Enterprise Edition(企业版) J2EE 包含J2SE 中的类,并且还包含用于开发企业级应用的类。比如:EJB、servlet、jsP、XML、事务控制。

主要JVM

首先,JVM是一套规范。很多公司均实现了各自的虚拟机。常见的有

HotSpot JVM(sun)
Jrockit JVM(BEA公司的JVM,应用于WEBlogic)
IBM JVM
Apache Harmony

其中,我们常用的是HotSpot JVM.

JVM结构

深入浅析Java中 JVM的原理

第一步(编译):

创建完源文件之后,程序会先被编译为.class文件。Java编译一个类时,如果这个类所依赖的类还没有被编译,编译器就会先编译这个被依赖的类,然后 引用,这个有点象make。如果java编译器在指定目录下找不到该类所其依赖的类的.class文件或者.java源文件的话,编译器话 报“cant find symbol”的错误。

第二步(运行):

Java类运行的过程大概可分为两个过程:1、类的加载  2、类的执行。

需要说明的是:JVM主要在程序第一次主动使用类的时候,才会去加载该类。也就是说,JVM并不是在一开始就把一个程序就所有的类都加载到内存中,而是到不得不用的时候才把它加载进来,而且只加载一次。

 在 编译好java程序得到MainApp.class文件后,在命令行上敲java AppMain。系统就会启动一个jvm进程,jvm进程从classpath路径中找到一个名为AppMain.class的二进制文件,将 MainApp的类信息加载到运行时数据区的方法区内,这个过程叫做MainApp类的加载。

 (java命令)然后JVM找到AppMain的主函数入口,开始执行main函数

 (类加载器)执行过程中,会创建对象。JVM会首先从方法区加载类信息和相关常量,class加载完毕之后,在堆上为对象分配内存,然后调用初始化实例,当然这时候实例保持指向class类型信息,这个信息保存在方法区中。

 (执行引擎)调用实例方法时,会根据引用找到对象信息,进而可定位对应的class类型信息,和方法表。

 (执行引擎)执行方法时,在虚拟机栈中进行,分配栈帧,随着入栈出栈,完成方法调用操作。

执行引擎

运行Java的每一个线程都是一个独立的虚拟机执行引擎的实例。从线程生命周期的开始到结束,他要么在执行字节码,要么在执行本地方法。一个线程可能通过解释或者使用芯片级指令直接执行字节码,或者间接通过JIT执行编译过的本地代码。我们上文讲到的main函数,也就是执行引擎的操作入口。

Class文件

实际上,Class文件中方法的字节码流就是有JVM的指令序列构成的。每一条指令包含一个单字节的操作码,后面跟随0个或多个操作数。

iload_0    // 把存储在局部变量区中索引为0的整数压入操作数栈。
iload_1    // 把存储在局部变量区中索引为1的整数压入操作数栈。
iadd         // 从操作数栈中弹出两个整数相加,在将结果压入操作数栈。
istore_2   // 从操作数栈中弹出结果

JVM运行时数据区

1)程序计数器(线程私有)

当前线程所执行的字节码的行号指示器,通过改变这个计数器的值,确定下一条要执行的命令。分支,循环,跳转都需要它的支持。

它是线程私有的,每个线程都有专属于自己的程序记数器,线程之间互不影响,独立存储,保证了线程切换后,可以恢复到原先执行位置。

2)Java虚拟机栈(线程私有)

每个方法的执行,同时都会在虚拟机栈上创建一个栈帧。用于存储局部变量表,操作数栈,方法出口,动态链接等。一个方法的执行周期,同时也就对应着栈帧的出栈入栈操作。有时候方法的递归,会造成大量的栈帧,达到一定的深度,会报StackOverflowError异常。有一点需要说明:在编译器编译Java代码时,就已经在字节码中为每个方法都设置好了局部变量区和操作数栈的数据和大小。并在JVM首次加载方法所属的Class文件时, 就将这些数据放进了方法区。因此在线程调用方法时,只需要根据方法区中的局部变量区和操作数栈的大小来分配一个新的栈帧的内存大小,并堆入Java栈。

局部变量区: 用来存放方法中的所有局部变量值,包括传递的参数。这些数据会被组织成以一个字长(32bit或64bit)为单位的数组结构(以索引0开始)中。其中类 型为int, float, reference(引用类型,记录对象在堆中地址)和returnAddress(一种JVM内部使用的基本类型)的值占用1个字长,而byte, char和shot会扩大成1个字长存储,long,double则使用2个字长。

 操作数栈: 用来在执行指令的时候存储和使用中间结果数据。

帧数据区: 常量池的解析,正常方法返回以及异常派发机制的信息数据都存储在其中。

3)本地方法栈(线程私有)

与Java虚拟机栈类似,只不过该区域是为native方法提供服务。

4)方法区(Perm)(线程共享)

    存储已被虚拟机加载的类信息,常量,静态变量,即时编译后的代码等数据。包含运行时常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容是在类加载后进入方法区运行时常量池中。

5)堆

深入浅析Java中 JVM的原理

堆是整个内存数据区最负责的部分,负责对象的创建。同时,垃圾回收的主要工作也在于此。堆又进一步进行细分,主要是为了满足垃圾回收。

堆的组成

Eden(伊甸园):对象创建的入口。

Survivor Space:用于保存在eden space内存池中经过垃圾回收后没有被回收的对象,也就是“幸存还活着”的对象。

幸存者0区(Survivor 0 space)和幸存者1区(Survivor1 space):当伊甸园的空间用完时,程序又需要创建对象;此时JVM的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的不再被其他对象所引用的对象 进行销毁工作。同时将伊甸园中的还有其他对象引用的对象移动到幸存者0区。幸存者0区就是用于存放伊甸园垃圾回收时所幸存下来的JAVA对象。

当将伊甸园中的还有其他对象引用的对象移动到幸存者0区时,如果幸存者0区也没有空间来存放这些对象时,JVM的垃圾回收器将对幸存者0区进行垃圾 回收处理,将幸存者0区中不在有其他对象引用的JAVA对象进行销毁,将幸存者0区中还有其他对象引用的对象移动到幸存者1区。幸存者1区的作用就是用于 存放幸存者0区垃圾回收处理所幸存下来的JAVA对象。

Tenured :对象经过survivor 1 space内存池,每经历过一次垃圾回收,年龄就增加1,超过设定阀值后,被移入终身代,当然也包括由于担保机制移入的对象。对于新生代和老年代,垃圾回收器对其态度不同。发生在新生代的回收频率频繁,大部分对象是“朝生夕死”,收集算法一般采用高效简单的复制算法,也就是上文描述的对象转移操作(Eden->survivor 0,survivor 0->survivor 1)。发生在该区域的垃圾回收为Young GC.对于老年代,由于大部分对象主要为存活率高的对象,垃圾回收器采用”标记-整理“算法。发生在该区域的垃圾回收为FULL GC.

堆相关参数

(影响堆空间划分,进而会影响GC发生频率)JVM调优工作,主要是基于这些参数,进行适当调整管理,达到调整堆内存大小及比例大小,以满足实际业务需求。另外还包括方法区。

-Xms:设置 Java 应用程序启动时的初始堆大小;
-Xmx:设置 Java 应用程序能获得的最大堆大小;
-Xss:设置线程栈的大小;
-XX:MinHeapFreeRatio:设置堆空间最小空闲比例。当堆空间的空闲内存小于这个数值时,JVM 便会扩展堆空间;
-XX:MaxHeapFreeRatio:设置堆空间的最大空闲比例。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆;
-XX:NewSize:设置新生代的大小;
-XX:NewRatio:设置老年代与新生代的比例,它等于老年代大小除以新生代大小;
-XX:SurvivorRatio:新生代中 eden 区与 survivor 区的比例;
-XX:MaxPermSize:设置最大的持久区大小;
-XX:TargetSurvivorRatio: 设置 survivor 区的可使用率。当 survivor 区的空间使用率达到这个数值时,会将对象送入老年代。

对象的生命周期

  创建阶段

检查指令的参数,是否能在常量池中定位到一个类的符号引用,如果是引用,判断代表的类是否加载,解析和初始化过

如果没有加载,则必须进行加载,解析和初始化

类加载检查,这时候已经知道所需内存的大小。

分配内存。从java堆中划分一块大小确定的内存。支持2种方式,至于选择哪种方式分配内存,与java堆是否规整有关(也就是是否空间空间和使用空间相互交错情况)。1.指针碰撞(分界点的指示器移动);2.空闲列表方式。然而,java堆是否规整,则取决于垃圾收集器的工作方式。此外,在分配内存时还要考虑多线程情况,保证原子性。分配内存的原子性有2种方式进行保证(CAS 和 本地线程分配缓冲-XX +/- UseTLAB)。

5)、分配内存完成后,初始化内存空间(初始化为0)

维护对象的对象头信息。如元数据信息,哈希码,GC分代年龄,信息,类元指针。

调用init方法,按照程序员意愿进行初始化。

     <7.1> 从超类到子类对static成员进行初始化;
     <7.2> 超类成员变量按顺序初始化,递归调用超类的构造方法;
      <7.3> 子类成员变量按顺序初始化,子类构造方法调用。

应用阶段

分为强引用、软引用、虚引用、若引用

   不可视阶段;

当一个对象处于不可视阶段,说明我们在其他区域的代码中已经不可以在引用它,其强引用已经消失,例如,本地变量超出了其可视的范围。

   不可到达阶段;

处于JVM对象生命周期不可到达阶段的对象,在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用,这些对象通常是指所有线程栈中的临时变量, 所有已装载的类的静态变量或者对本地代码接口(JNI)的引用。这些对象都是要被垃圾回收器回收的预备对象,但此时该对象并不能被垃圾回收器直接回收。其 实所有垃圾回收算法所面临的问题是相同的——找出由分配器分配的,但是用户程序不可到达的内存块。

   可收集阶段、终结阶段、释放阶段 ;

当一个对象处于可收集阶段、终结阶段与释放阶段时

<1> 回收器发现该对象已经不可达。 

     <2> finalize方法已经被执行。 

     <3> 对象空间已被重用。

关于深入浅析Java中 JVM的原理就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: 深入浅析Java中 JVM的原理

本文链接: https://www.lsjlt.com/news/226917.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 深入浅析Java中 JVM的原理
    这篇文章将为大家详细讲解有关深入浅析Java中 JVM的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真...
    99+
    2023-05-31
    java jvm ava
  • 深入浅析java中反射的原理
    深入浅析java中反射的原理?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1.Class类任何一个类都是Class的实例对象,这个实例对象有三种表示方式//第一种表示方式---...
    99+
    2023-05-31
    java 反射 ava
  • 深入浅析JAVA中封装的原理
    本篇文章为大家展示了深入浅析JAVA中封装的原理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。第一节 什么是JAVA中的封装面向对象的三大特性:封装、继承、多态。概念:将类的某些信息隐藏在类的内部,...
    99+
    2023-05-31
    java 封装 ava
  • 深入浅析Java中线程池的原理
    这篇文章将为大家详细讲解有关深入浅析Java中线程池的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。ThreadPoolExecutor简介ThreadPoolExecutor是线程池类...
    99+
    2023-05-31
    java ava 线程池
  • 深入浅析Java中输出HelloWorld的原理
    今天就跟大家聊聊有关深入浅析Java中输出HelloWorld的原理,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。我们初学java的第一个程序是"hello world&q...
    99+
    2023-05-31
    java helloworld ava
  • 深入浅析java中堆排序的原理
    本篇文章为大家展示了深入浅析java中堆排序的原理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。从堆排序的简介到堆排序的算法实现等如下:1. 简介  堆排序是建立在堆这种数据结构基础上的选择排序,是...
    99+
    2023-05-31
    java 堆排序 ava
  • 深入浅析java 中volatile与lock的原理
    深入浅析java 中volatile与lock的原理?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。java 中volatile和lock原理分析volatile和lock是...
    99+
    2023-05-31
    java volatile lock
  • 深入浅析java 中HashMap的实现原理
    这篇文章将为大家详细讲解有关深入浅析java 中HashMap的实现原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1. HashMap的数据结构数据结构中有数组和链表来实现对数据的存储,...
    99+
    2023-05-31
    java hashmap ava
  • 深入浅出解析Java ThreadLocal原理
    目录1.了解ThreadLocal简介使用2.源码解析 – 探究实现思路threadLocals变量与ThreadLocalMapset(T value) 方法get() 方法rem...
    99+
    2022-11-12
  • 深入浅析java 1.8 中动态代理的原理
    这篇文章将为大家详细讲解有关深入浅析java 1.8 中动态代理的原理,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JDK8动态代理源码分析动态代理的基本使用就不详细介绍了:例子:class...
    99+
    2023-05-31
    java 动态代理 ava
  • 深入浅析Java中的AtomicLongArray原子类
    本篇文章为大家展示了深入浅析Java中的AtomicLongArray原子类,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。AtomicLongArray介绍和函数列表 AtomicLong...
    99+
    2023-05-31
    java atomiclongarray 原子类
  • 深入浅析JVM中的参数分配
    深入浅析JVM中的参数分配?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、堆参数设置-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志-XX:...
    99+
    2023-05-31
    jvm
  • 深入浅析HashMap的工作原理
    这篇文章给大家介绍深入浅析HashMap的工作原理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。实际上,HashSet 和 HashMap 之间有很多相似之处,对于 HashSet 而言,系统采用 Hash 算法决定集...
    99+
    2023-05-31
    hashmap
  • 深入浅析Java 中的CharArrayReader
    深入浅析Java 中的CharArrayReader?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。CharArrayReader 介绍CharArrayRead...
    99+
    2023-05-31
    java chararrayreader ava
  • 深入浅析Java 中的LockSupport
    这期内容当中小编将会给大家带来有关深入浅析Java 中的LockSupport,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。LockSupport介绍LockSupport是用来创建锁和其他同步类的基本线...
    99+
    2023-05-31
    java pp locksupport
  • 深入浅析Java中的 FilterInputStream
    这期内容当中小编将会给大家带来有关深入浅析Java中的 FilterInputStream,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。FilterInputStream 介绍FilterInputStr...
    99+
    2023-05-31
    java filterinputstream npu
  • 深入浅析Java中拆箱与自动装箱的原理
    这篇文章给大家介绍深入浅析Java中拆箱与自动装箱的原理,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。什么是自动装箱和拆箱自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象...
    99+
    2023-05-31
    java 自动装箱 拆箱
  • 深入浅析ELK原理与简介
    为什么用到ELK: 一般我们需要进行日志分析场景:直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档、...
    99+
    2022-11-12
  • Java深入浅出分析Synchronized原理与Callable接口
    目录一、基本特点二、加锁工作过程偏向锁轻量级锁重量级锁三、其他的优化操作锁消除锁粗化四、Callable 接口一、基本特点 1. 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁....
    99+
    2022-11-13
  • 深入浅析Java中的 concurrency锁
    本篇文章给大家分享的是有关深入浅析Java中的 concurrency锁,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。根据锁的添加到Java中的时间,Java中的锁,可以分为&...
    99+
    2023-05-31
    java concurrency ava
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作