JDK、JRE、JVM

本文详细介绍了Java的main方法,包括其在类结构中的位置,如何编写和运行,以及Java字节码的生成、加载、验证和执行过程。重点强调了Java的平台无关性和JVM在其中的作用。
摘要由CSDN通过智能技术生成

main方法示例

public class Grammar1_HelloWorld {
    public static void main(String[] args) {
        System.out.println("hello world!");
    }
}

Java的main方法相较于c/c++等编程语言来说是较长的,构成main方法的三个核心:
● 源文件 - Grammar1_HelloWorld.java
● 类 - Grammar1_HelloWorld
● 方法 - main 方法
由于Java的方法依托于类而存在,所以main方法要写在类内部,同时Grammar1_HelloWorld类作为主类,要和源文件名一致(不含后缀.java),即类在源文件内部,main方法在类内部,语句在方法内部,如下图所示。
在这里插入图片描述

main方法时如何运行的?

  1. 编写源代码
    首先,使用文本编辑器或集成开发环境(IDE)编写Java源代码。如上Grammar1_HelloWorld.java
  2. 编译源代码
    使用Java编译器(javac),将源代码文件编译成字节码(.class文件)。在命令行中,执行以下命令:
javac Grammar1_HelloWorld.java

编译器检查源代码的语法和语义是否正确。如果没有错误,编译器会生成对应的Grammar1_HelloWorld.class字节码文件。
3. 类加载与初始化
运行Java程序时,通过java命令指定包含main方法的类名。在命令行中,执行以下命令:

java Grammar1_HelloWorld

执行java Grammar1_HelloWorld命令后,JVM(Java虚拟机)开始工作:

  • 类加载:JVM的类加载器负责查找、加载Grammar1_HelloWorld.class文件,将其字节码数据读入内存。加载过程中包括验证字节码的正确性、准备静态变量、解析符号引用等步骤。
  • 类初始化:当Grammar1_HelloWorld类被首次主动使用时(此处即执行main方法),JVM会进行类初始化,即执行类的静态初始化块(如果有)和初始化静态字段。
  1. 执行主方法
    JVM找到并调用Grammar1_HelloWorld类的main方法。此方法接收一个来自命令行的字符串数组args作为参数,但在这个例子中并未使用。main方法内部调用了System.out.println方法,该方法属于java.lang.System类,它负责将传入的字符串参数输出到标准输出设备(如控制台)。
  2. 输出结果
    System.out.println方法执行时,会在控制台上打印出字符串“hello world!”,至此,整个程序的执行流程结束。
    综上,Java “hello world!” 程序的运行经历了编写源代码、编译源代码、类加载与初始化、执行主方法、输出结果等几个关键步骤。这一过程展示了Java程序特有的编译成字节码、依赖JVM运行的特性,以及Java语言的面向对象和平台无关性特点。

拓展:字节码Java

字节码是Java程序在编译阶段生成的一种中间形式的代码,它是介于源代码(如.java文件)与最终运行时的机器代码之间的二进制表示。Java字节码的设计目标是实现平台无关性、安全性、高效性和可移植性。

定义与特点

定义:

Java字节码是一种针对Java虚拟机(JVM)设计的低级指令集,它以二进制形式存储在.class文件中。这些指令是高度精简的,旨在提供一种通用的、与具体硬件架构无关的指令集,由JVM负责将其解释或即时编译(Just-In-Time compilation, JIT)为对应平台的机器码执行。

特点:

  • 平台无关性:字节码不直接依赖于特定的操作系统或处理器架构,而是依赖于实现了Java虚拟机标准的软件环境。这意味着同一个字节码文件可以在任何支持JVM的平台上运行,实现了“一次编写,到处运行”的理念。
  • 安全性:字节码受到JVM的严格验证,确保其符合安全约束,例如类型安全、访问权限控制等,防止恶意代码对系统的破坏。
  • 高效性:虽然字节码比源代码更接近机器码,但相比纯解释执行,JVM通常使用JIT编译器将热点字节码动态编译成本地机器码,从而获得接近甚至超越某些原生编译语言的性能。
  • 可移植性:由于字节码的统一标准,开发者可以使用各种Java编译器(如javac)生成字节码,而无需关心目标平台的具体细节。同时,字节码也可以作为工具(如反编译器、静态分析工具、AOT编译器等)的输入,便于进行进一步处理或优化。

字节码文件结构

Java字节码以.class文件的形式存储。每个.class文件遵循严格的结构,包括以下几个关键部分:

  • 魔数(Magic Number):
    位于文件开头的四个字节,固定为0xCAFEBABE,用于标识这是一个合法的Java Class文件。
  • 版本号:
    紧跟魔数的四个字节分别代表主版本号和次版本号,用于标识Class文件所遵循的JVM规范版本。高版本的JVM通常向下兼容较低版本的Class文件,而低版本JVM则无法识别过高版本的Class文件,此时会抛出UnsupportedClassVersionError异常。
  • 常量池(Constant Pool):
    Class文件的核心部分,包含了类、方法、字段的符号引用以及字面量等常量数据。常量池中的每一项都有一个索引,供其他部分的指令引用。
  • 类信息:
    包括访问修饰符、类名、父类名、接口列表、字段表、方法表等,描述了类的基本属性、继承关系、成员变量和方法定义。
  • 属性表(Attributes):
    存储额外的类或成员信息,如源文件名、注解、代码块、方法参数信息等。其中,Code属性包含了方法的字节码指令序列。
  • 字节码指令集
    Java字节码指令集是一种精简的、面向堆栈的指令集。每个指令通常由一个字节(8位)或两个字节构成,后跟零到多个操作数。指令集主要包括以下几类操作:
  • 数据操作指令:
    用于对操作数栈上的基本类型数据进行操作,如加载常量、复制栈顶元素、数值运算、类型转换等。
  • 堆栈操作指令:
    调整操作数栈深度,如推送和弹出栈帧、交换栈顶元素、复制栈内数据等。
  • 加载/存储指令:
    访问局部变量、类字段和数组元素,用于将数据从局部变量区、对象字段或数组加载到栈上,或将栈上数据存储回这些位置。
  • 控制流指令:
    实现条件分支、循环、跳转、异常处理等功能,如if-else、switch、for、while、try-catch-finally等结构对应的控制转移。
  • 方法调用与返回指令:
    用于调用其他方法(包括实例方法、静态方法、接口方法),以及从方法中返回结果或结束执行。
  • 对象创建与操作指令:
    创建新对象、检查类与接口实例关系、初始化对象、调用对象构造器、操作类与接口的实例字段等。
  • 异常处理指令:
    与异常处理相关的指令,如抛出异常、处理异常、设置异常处理器等。

字节码执行过程

当JVM加载一个.class文件时,会执行以下步骤:

  • 验证:检查Class文件的结构、语义和元数据的有效性,确保其符合JVM规范且不会危害系统安全。
  • 准备:为类或接口的静态字段分配内存,并赋予默认初始值(对于引用类型为null,基本类型为零值)。
  • 解析:将常量池中的符号引用转化为直接引用(如内存地址),便于后续快速访问。
  • 初始化:如果类尚未初始化,触发类构造器方法的执行,完成静态初始化块和静态字段的赋值。
    对于方法的执行,JVM会根据方法的Code属性中的字节码指令序列进行解释执行或JIT编译执行。解释执行时,JVM逐条读取指令并执行;JIT编译执行时,JVM将热点方法编译为本地机器码,后续直接执行已编译的代码以提升性能。
    字节码应用与工具
    字节码在实际开发中有多种应用,如:
  • 性能分析:通过分析字节码,可以获取方法的调用关系、热点代码分布等信息,有助于优化程序性能。
  • 动态代理:利用字节码生成技术(如ASM、ByteBuddy、cglib等库),可以在运行时动态创建代理类,实现AOP(面向切面编程)等功能。
  • 热部署:某些框架(如Spring Loaded、JRebel)支持在不重启应用的情况下,通过替换字节码实现代码的热更新。
  • 代码混淆与加密:对字节码进行混淆或加密处理,可以保护知识产权,增加逆向工程的难度。
    常用的字节码分析与操作工具有:
  • javap:Java自带的反汇编器,用于查看Class文件的字节码指令。
  • ASM、ByteBuddy、cglib:字节码操作库,支持在运行时生成、修改或分析字节码。
  • BCEL、Javassist:类似ASM的字节码处理库,提供了较为高级的API来操作字节码。
  • JaCoCo、YourKit:代码覆盖率工具和性能分析工具,基于字节码进行监控和报告生成。
    综上所述,Java字节码是Java程序在编译阶段生成的一种中间表示,它实现了平台无关性、安全性、高效性和可移植性,是Java语言跨平台特性的基石。通过对字节码的理解和操作,可以深入优化程序性能、实现高级编程特性和增强代码的安全性。

拓展:JDK、JRE、JVM

JDK、JRE、JVM是Java开发、运行环境与虚拟机的三个核心组成部分,它们之间存在紧密联系并共同支撑着Java应用程序的开发、编译与运行。以下是对这三个概念的详细解读:

Java Development Kit (JDK)

Java Development Kit,即Java开发工具包,是为Java应用程序开发提供的完整软件开发环境。它包含了编译、调试、打包、运行Java程序所需的所有工具和库文件。

组件与功能:

  • 编译器(javac):将源代码(.java文件)编译成字节码(.class文件)。
  • 文档生成工具(javadoc):自动生成API文档。
  • 打包工具(jar):将相关类文件打包成Java归档(.jar)文件,便于分发和管理。
  • Java运行环境(JRE):包含运行Java程序所需的组件,如JVM和标准库。
  • 调试工具(jdb):Java调试器,用于调试Java程序。

Java Runtime Environment (JRE)

Java Runtime Environment,即Java运行环境,是运行Java应用程序所必需的软件环境。它包含了运行Java程序的最小集合,使用户能够在没有安装JDK的情况下运行已编译好的Java程序。
组件与功能:

  • Java虚拟机(JVM):负责解释或编译字节码并执行,提供跨平台运行能力。
  • Java类库(Java SE API):标准版Java库,包含了Java基础类库(如集合框架、IO/NIO、网络通信、并发工具、反射机制等)以及用户界面库(如Swing、AWT)。
  • Java插件:允许Java应用程序在浏览器中运行。
  • Java Web Start:支持从Web服务器上远程下载并启动Java应用程序。

Java Virtual Machine (JVM)

Java Virtual Machine,即Java虚拟机,是JRE的核心部分,它是一个抽象化的计算机,能够装载并执行Java字节码。JVM屏蔽了底层操作系统和硬件的差异,使得同一份字节码能在任何安装了JVM的平台上运行。
组成部分与工作原理

  • 类加载器(ClassLoader):负责查找和加载类文件(.class),并将其转化为可在JVM内部使用的数据结构。类加载器遵循双亲委派模型,确保类的唯一性与安全性。
  • 运行时数据区:
    堆(Heap):存放对象实例和数组,所有线程共享。垃圾回收器(Garbage Collector)负责回收不再使用的对象所占用的空间。
  • 方法区(Method Area):存储类信息、常量池、静态变量、即时编译后的代码等数据。在JDK 8及以前,这部分常被称为永久代(PermGen),在JDK 8之后被元空间(Metaspace)替代。
  • Java栈(Java Stack):每个线程独有,用于存储方法调用时的局部变量、操作数栈、方法返回地址等信息。每个方法调用对应一个栈帧(Stack Frame)。
  • 本地方法栈(Native Method Stack):与Java栈类似,但服务于Native方法(使用C/C++等非Java语言实现的方法)的调用。
  • 程序计数器(Program Counter Register):记录当前线程正在执行的字节码指令地址,是线程私有的。
    执行引擎:
  • 解释器:逐条解释执行字节码指令。
    即时编译器(JIT):将热点代码编译为机器码,提高执行效率。现代JVM通常采用分层编译策略,兼顾启动速度和运行效率。
  • 垃圾回收器(Garbage Collector, GC):自动回收不再使用的对象,释放内存资源,防止内存泄漏。
    本地接口:允许Java代码调用操作系统本地方法库(如C库),实现与操作系统和硬件的交互。

总结

  • JDK涵盖了开发Java程序所需的全套工具,包括编译器、调试器等,以及用于运行Java程序的JRE,是开发者的必备套装。
  • JRE仅包含运行Java程序所需的最小子集,即JVM和相关的类库,适用于不需要进行开发活动,只需运行Java程序的用户。
  • JVM是JRE的一部分,是实际执行Java字节码的抽象计算机,负责程序的解释或编译、内存管理、垃圾回收等核心任务,保证Java程序能够在不同平台上一致地运行。

因此,从包含关系上看,JDK > JRE > JVM。在实际使用中,开发人员需要安装JDK进行编程与调试,而普通用户只需安装JRE来运行已经开发完成的Java应用程序。JVM作为两者共有的核心组件,确保了Java程序的跨平台特性。
在这里插入图片描述

  • 33
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值