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

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis