Java 是如何工作的?
微信搜索关注《Java学研大本营》,加入读者群,分享更多精彩
在本文中,您将学习如何用简单的语言编译和运行 java 程序。我们可以在任何文本编辑器(记事本、Sublime Text、Atom 等)中编写任何简单的 java 程序,但条件是您的 java 程序应包含正确的语言语法和.java格式。
例如,我使用.java Formate 创建了一个名为 FirstJavaProgram 的简单 java 程序。
简单的Java程序 现在在创建这个程序之后,每当我们使用 java Compile javac编译这个程序时,它都会生成一个带有类名和.class格式的字节码文件。例如下图显示了上述 java 程序的编译。
通过javac编译 Java 程序 编译java程序后,我们可以看到生成了字节码,如下图所示。
Before javac (Before Compiler 编译程序)
After javac (After Compiler 编译程序)
为什么 Java 是平台无关的?
我们可以看到java程序编译后自动生成了一个.class 。现在,这个 .class 文件由JVM解释, JVM 将这个 .class 文件转换为机器代码(二进制代码)。所以这就是为什么 java 是一种平台无关语言的原因,因为它首先生成字节码,这个字节码由依赖于机器的 JVM 进一步解释。
现在让我们看看什么是 JVM(Java 虚拟机),但在了解之前我们应该清楚地了解下图中显示的整个 java 程序过程。
下图表示Java 架构,其中每个步骤都以图形方式详细说明。
Java架构
Java架构总结
Java 体系结构是组件的集合,即JVM、JRE和JDK。它集成了解释和编译过程。它定义了创建 Java 程序所涉及的所有过程。Java Architecture解释了程序编译和执行的每一步。
可以使用以下步骤解释Java 体系结构:
-
Java中有一个编译解释的过程。
-
Java 编译器将 Java 代码转换为字节码。
-
之后,JVM 将字节码转换为机器码。
-
然后机器代码由机器执行。
JVM(Java虚拟机)
Java的主要特点是一次编写到处运行。该功能表明我们可以编写一次代码并在任何地方或任何操作系统上使用它。我们的 Java 程序可以运行任何平台只是因为 Java 虚拟机。它是一个 Java 平台组件,为我们提供了执行 Java 程序的环境。JVM的主要任务是将字节码转换成机器码。
虚拟机 现在让我们一一查看每个组件。
类加载器子系统
classLoader SubSystem负责以下三个Activity。
1)加载
2)链接
2.1)验证
2.2)准备
2.3)分辨率
3)初始化
1.加载
加载是指读取Class文件,并将相应的Binary Data存入方法区。
对于每一个Class文件,JVM在Method Area中存储了如下的方法。
-
加载的类或接口或枚举的完全限定名称。
-
其直接父类的完全限定名称。
-
变量信息
-
方法信息
-
修饰符信息
-
常量池信息 将.class文件加载到Method Area后,JVM会立即在Heap Memory上创建一个Class类型的对象来表示Class级别的二进制信息。
例如
程序员可以使用类对象来获取类级别信息,如类的完全限定名称、父名称、方法和变量信息等。
注意:对于每个加载的 .class 文件,只会创建一个类对象,即使我们在我们的应用程序中多次使用类。
2.链接
链接包含 3 个活动
-
确认
-
准备
-
解析度
验证
这是确保类的二进制表示在结构上正确或不正确的过程。
也就是说,JVM 将检查 .class 文件是否由有效编译器生成或是否正确。即 .class 文件是否格式正确或不正确。
作为 ClassLoader 子系统的一部分的内部字节代码验证器负责此活动。
如果验证失败,那么我们将得到运行时异常 Saying java. lang.VerifyError。
准备
在这个阶段,JVM 会为Class Level Static 变量分配 Memory并分配默认值(Not Original Value)。
注:Original Value Assign 进入初始化 部分。
解析度
它是用原始引用替换加载类型使用的符号引用的过程。
通过搜索方法区以定位引用的实体,符号引用被解析为直接引用。
例如;
理解解决方案 在上面的程序中,一共有三个类
-
字符串类
-
学生班
-
对象类(对象类是所有java类的父类) 对于上面的程序,ClassLoader子系统加载了Student.class、String.class和Object.class。
这些班级名称的名称存储在学生班级的常量池中。
在解析阶段,这些名称被替换为方法区域中的实际引用。
3.初始化
在此阶段,所有静态变量都将被分配原始值,静态块将从上到下、从父到子执行。
所以 ClassLoader 子系统的总结如下图所示。
类加载器子系统总结
类加载器的类型
ClassLoader SubSystem 包含以下三个 ClassLoader。
1
-
引导类加载器或原始类加载器
-
扩展类加载器
-
应用类加载器
BootStrap类加载器
这个 ClassLoader 负责从jdk\jre\lib 加载类。
所有核心 Java API 类都存在于rt.jar中。它仅存在于此位置。因此,所有 API 类(如(String、StringBuffer))将仅由 BootStrap ClassLoader 加载。
它是用C和C++等本地语言实现的。
扩展类加载器
它是 Bootstrap ClassLoader 的子类。
ThisClassLoader 负责从jdk\jre\lib\ext 加载类。
应用类加载器
它是扩展类加载器的子类。
该类加载器负责从应用程序类路径(当前工作目录)加载类。
它在内部使用环境变量类路径。
让我们看一个All ClassLoader的例子
例如,
这里 getClassLoader 给出 ClassLoader 的路径
让上面程序的输出是
以上 Java 程序的输出 对于String Class From Bootstrap Class-Path by Bootstrap ClassLoader 输出为空,因为我们在上面看到 BootStrap 类路径是用C和C++实现的,因此 Bootstrap ClassLoader 不是 Java 对象。因此,我们在第一种情况下得到 null。
而Ketan 类是 Application ClassLoader 的一部分,因为我们可以在当前工作目录中获取 Ketan.class 文件。
推荐书单
《项目驱动零起点学Java》
《项目驱动零起点学Java》共分 13 章,围绕 6 个项目和 258 个代码示例,分别介绍了走进Java 的世界、变量与数据类型、运算符、流程控制、方法、数组、面向对象、异常、常用类、集合、I/O流、多线程、网络编程相关内容。《项目驱动零起点学Java》总结了马士兵老师从事Java培训十余年来经受了市场检验的教研成果,通过6 个项目以及每章的示例和习题,可以帮助读者快速掌握Java 编程的语法以及算法实现。扫描每章提供的二维码可观看相应章节内容的视频讲解。
《项目驱动零起点学Java》贯穿6个完整项目,经过作者多年教学经验提炼而得,项目从小到大、从短到长,可以让读者在练习项目的过程中,快速掌握一系列知识点。
马士兵,马士兵教育创始人,毕业于清华大学,著名IT讲师,所讲课程广受欢迎,学生遍布全球大厂,擅长用简单的语言讲授复杂的问题,擅长项目驱动知识的综合学习。马士兵教育获得在线教育“名课堂”奖、“最受欢迎机构”奖。
赵珊珊,从事多年一线开发,曾为国税、地税税务系统工作。拥有7年一线教学经验,多年线上、线下教育的积累沉淀,培养学员数万名,讲解细致,脉络清晰。
精彩回顾
微信搜索关注《Java学研大本营》
访问【IT今日热榜】,发现每日技术热点