Java的结构与运行机制

2024-05-25 17:04
文章标签 java 结构 运行机制

本文主要是介绍Java的结构与运行机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. JDK JRE JVM三者的区别

  • JDK(Java Development Kit):Java开发工具包

    JDK包含JRE,还包括其他例如:编译器(javac)、javadoc、jar等,JDK是能够创建和编译程序的。

  • JRE(Java runtime environment):Java运行环境

    JRE是运行已编译Java程序所需要的所有内容的集合,包括JVM,java类库,java命令和其他基础构建,JRE不能够创建和编译程序。

  • JVM(Java Virtual Machine):Java虚拟机

    JVM是运行java字节码1的虚拟机,JVM有针对不同系统的特定实现(这是因为不同操作系统二进制所代表的不完全相同),目的是使用相同的字节码,在不同的操作系统上都能给出相同的结果,如下图所示

    在这里插入图片描述

JDK、JRE、JVM三者之间的关系
在这里插入图片描述

Java文件在三者之间的流转
在这里插入图片描述

2. Java的运行机制(宏观)

  1. 编译:JDK调用javac工具将.java文件编译成.class文件
    如果在编译时该类所依赖的类还没有被编译则会自动编译所依赖的类并引用
    如果找不到所依赖的类则会报Can't found sysbol的异常

  2. 运行(启动JVM进程):
    类加载的生命周期:加载-->验证-->准备-->解析(验证、准备、解析称为类的连接)-->初始化-->使用-->卸载

    1. 加载:读取class文件到内存的过程

      • 加载.class文件
      • 将class文件的信息存储到方法区
      • 生成一个引用对象(java.lang.Class)
    2. 检验合格性:分为四个阶段
      格式验证:在加载阶段检查字节流是否符合class文件规范
      .class文件是否以魔数(Magic Number)0XCAFEBABE开头
      小版本号Minor version和大版本号Major version
      常量池中常量是否有不支持类型
      Constant_Utf8_info型的常量中是否有不符合UTF-8编码的数据
      class文件中各个部分及文件本身是否有被删除的或附加的其他信息
      ……
      元数据验证:进行字节码语义分析
      检查这个类是否有父类(除了java.lang.Object之外,所有的类都应该有父类)
      这个类的父类是否继承了不允许被继承的类(final修饰的类)
      如果这个类不是抽象类,是否实现了其父类或接口之中要求实现的所有方法
      类中的字段、方法是否与父类产生了矛盾(例如覆盖了父类的final字段,或者不符合规则的方法重载)
      ……
      字节码验证:通过数据流分析和控制流分析,确定程序语法是否合法,是否符合逻辑,是最复杂的验证阶段
      保证任意时刻操作数栈的数据类型与指令代码序列都能配合工作,例如不会出现类似于在操作栈上放置一个int类型的数据,使用时却是按long类型来载入本地的变量表中这样的情况
      保证任何跳转指令都不会跳转到方法体以外的字节码指令上
      保证方法体中的类型转换总是有效的,例如可以把一个子类对象赋值给父类数据类型,这是安全的,但是把一个父类对象赋值给子类数据类型,甚至把对象赋值给与它毫不相关的数据类型,这是危险的,不合法的
      ……
      符号引用验证:
      符号引用中通过字符串描述的全限定名是否能找到对应的类
      在指定的类中是否存在符合方法的字段描述符及简单名称所描述的方法和字段
      符号引用中的类、字段、方法的可访问性—检查权限,验证可被当前类访问
      ……
      由JVM校验.class文件是否符合规范,为了防止代码危害虚拟机本身以及底层系统

    3. 准备:类变量分配内存,在分配内存的过程中,类变量就有了默认值
      为类变量分配内存并设置类变量初始值(默认值,不是赋值),这些类变量所使用的内存全都在方法区进行分配(不包括实例变量:实例变量会在对象实例化随着对象分配到Java堆中)

    4. 解析:将class常量池内的符号引用替换为直接引用的过程
      符号引用:就是字符串,通过字符串中的信息就能直接找到对应的类的数据(只需要无分歧对应数据位置即可)
      直接引用:将符号引用转化为直接引用是因为直接引用是JVM虚拟机可以直接使用的,是虚拟机可读的地址信息,是直接指向目标的指针,不同的JVM虚拟机解析出来的直接地址是不同的,一旦出现直接地址就意味着该目标已经存在于内存中
      如果符合规范就通过类加载器加载到JVM中运行得出结果

    5. 初始化:按照程序代码进行初始化,对数据进行赋值
      类的执行
      JVM主要是在程序第一次运行时,不得不使用类的时候才会立即加载并生成一个java.lang.Class对象,并存在方法区,且只加载一次,这就是为什么实例变量和静态方法只执行一次的原因,执行代码的过程是JVM解释.class文件给操作系统的过程
      注意:.class文件并不能直接与操作系统进行交互,而是通过JVM这个中间层间接与操作系统进行交互
      仅有JVM是不能解释.class文件的,必须是jvm通过调用一个lib类库,而jre就包含这个lib类库

Java的main方法为什么这么写

  1. public:设置访问权限,因为main方法被作为一个主方法,需要且必须被直接访问

  2. static:在JVM中没有实例化main所在的类,而是直接通过类名.main()的方式进行调用的,所以如果不写staticJVM就无法访问到main方法

  3. void:main方法不能有返回值,因为,jvm就算接收到返回值,它返回给谁?所以main中不能存在返回值,包括所有直接对接到JVM层的方法都不能有返回值

  4. String[] args:是用于在main方法执行前接收命令行参数的,作用主要是开发过程无数据情况下以命令行数据进行测试,作用效果不大,但是是规定

JVM在将类字节码读到内存中后,会找到加载的类中的主类,然后在主类中找到main方法之后,将main线程压栈到线程栈中执行main方法

new对象的底层存储

以Hello hello=new Hello()为例

  1. 对象声明:Hello hello
    中开辟一个地址空间,用于存放声明的对象

  2. 创建对象:new Hello()
    1)申请内存空间,将Hello类的相关信息(实例变量,实例方法等)加载到堆内存中
    2)执行构造方法就是<init>方法

  3. 使声明的对象与堆内存中的信息产生关联:
    即将堆内存中的地址赋值给栈中声明的对象,由声明的对象携带这个地址指向堆内存对象信息

堆内存中开辟对象的结构是什么?

  1. 头部信息
    1)偏移值(对齐填充)
    2)持有指向方法区的指针
    3)描述信息(持有当前对象锁的线程id和持有对象锁线程的个数,在GC中存活的生命周期,偏向锁2的标志)
  2. 实例信息
    实例信息为对象的属性和行为,后续会进行详细的解释,目前可以理解为:你定义的类的信息会加载到堆内存中的实例信息部分

  1. JVM能理解的代码就叫做字节码,文件以.class结尾,不面向任何特定的处理器,只面向JVM虚拟机通过字节码的方式,Java语言成功解决了传统解释型语言执行效率低的问题,同时保留了解释型语言可移植的特性虽然执行效率低于C/C++等语言,但是在切换操作系统的情况下,字节码文件无需重新编译,即可运行。 ↩︎

  2. 什么是偏向锁:当线程已经对此对象加锁后,执行完毕,如果下一次访问该线程也是上一次的线程,那么不对此线程重新上锁 ↩︎

这篇关于Java的结构与运行机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1002102

相关文章

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Java注解之超越Javadoc的元数据利器详解

《Java注解之超越Javadoc的元数据利器详解》本文将深入探讨Java注解的定义、类型、内置注解、自定义注解、保留策略、实际应用场景及最佳实践,无论是初学者还是资深开发者,都能通过本文了解如何利用... 目录什么是注解?注解的类型内置注编程解自定义注解注解的保留策略实际用例最佳实践总结在 Java 编程

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows