# JAVA程序运行原理分析

## **一、平台语言类型：**

* **编译型语言**

编译型语言是通过专门的编译器，将高级语言【一次性翻译成】可被平台（如OS操作系统）执行的机器码，编译一次，脱离开发环境可独立运行，故效率高；但对编译器严重依赖，而不同操作系统所使用的编译器是各不相同的，所以造成了编译型语言可移植性差的特点。如同打包发布好的vs程序，不管放在windows哪个磁盘下，均可脱离vs执行；但把这个编译好的exe放到unix下，便是不可能正常set up 的。这也就解释了它效率高，但跨平台可移植性差的特点。

* **解释型语言**

同样的，解释型语言也有专门的解释器，将原程序解释成特定的平台可执行文件，不同的是，解释型语言不会进行整体的编译，而是把编译和解释混合在一起执行。但解释性语言跨平台性好，只需通过不同的解释器，将其解释成某平台可识别的指令即可。这是编译的过程无法做到的。

* **区别**

| 类型  | 原理                             | 优点                                | 缺点                 |
| --- | ------------------------------ | --------------------------------- | ------------------ |
| 编译型 | 通过专门的编译器，将高级语言一次性翻译程可被平台执行的机器码 | 编译一次，脱离开发环境可独立运行，故效率高             | 对编译器严重依赖，可以执行性差    |
| 解释型 | 有专门的解释器，将程序解释称特定的平台指令          | 跨平台性好，只需通过不同的解释器，将其解释称某平台可识别的指令即可 | 编译和解释混合在一起执行，导致效率低 |

* **引出面试题**

1\)、**Java是属于哪种类型的？**

> **答：既是解释型语言，又是编译型语言**

2\)、**Java程序运行原理**

> 1、使用java进行编程，首先源程序会通过编译，将java编译成class字节码，【默认路径为该JRE运行环境路径下】
>
> 2、 再通过解释形成可执行文件
>
> ![](/files/-Ltdv9mqEZ4XfzdQbHFx)
>
> 开发人员编写Java代码(.java文件)，然后将之编译成字节码(.class文件)，再然后字节码被装入内存，一旦字节码进入虚拟机，它就会被解释器解释执行，或者是被即时代码发生器有选择的转换成机器码执行。

## 二、JAVA代码编译和执行的整个过程

## **Java代码编译和执行的整个过程包含了以下三个重要的机制:**

* **Java源码编译机制**

① 分析和输入到符号表

② 注解处理

③ 语义分析和生成class文件

![](/files/-Ltdv9ms3SV0YPvu3e4a)

最后生成的class文件由以下部分组成：

1. 结构信息。包括class文件格式版本号及各部分的数量与大小的信息
2. 元数据。对应于Java源码中声明与常量的信息。包含类/继承的超类/实现的接口的声明信息、域与方法声明信息和常量池
3. 方法信息。对应Java源码中语句和表达式对应的信息。包含字节码、异常处理器表、求值栈与局部变量区大小、求值栈的类型记录、调试符号信息
4. **类加载机制**

JVM的类加载是通过ClassLoader及其子类来完成的，类的层次关系和加载顺序可以由下图来描述：

![](/files/-Ltdv9mudQW0IIwGlXfX)

类加载器的作用是加载类文件到内存，比如编写一个HelloWord.java程序，然后通过javac编译程class文件，那么怎么才能加载到内存中被执行呢？ClassLoader承担的就是这个责任，那不可能随便建立一个.class文件就能被加载的，Class Loader加载的class文件是有格式要求的（具体要求详见《JVM Specification》，目前我还是看不懂），ClassLoader只管加载，只要符合文件结构就加载，至于说能不能运行，则不是它负责，那是由Execution Engine负责的。

类加载的步骤如下：

1）、**加载**

① Bootstrap ClassLoader

负责加载$JAVA\_HOME中jre/lib/rt.jar里所有的class到堆类存的永久存储区，由C++实现，不是ClassLoader子类

②Extension ClassLoader

负责加载java平台中扩展功能的一些jar包，包括$JAVA\_HOME中jre/lib/\*.jar或-Djava.ext.dirs指定目录下的jar包

③App ClassLoader

负责记载classpath中指定的jar包及目录中class

④Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader，如tomcat、jboss都会根据j2ee规范自行实现ClassLoader

加载过程中会先检查类是否被已加载，检查顺序是自底向上，从Custom ClassLoader到BootStrap ClassLoader逐层检查，只要某个classloader已加载就视为已加载此类，保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下，也就是由上层来逐层尝试加载此类。

2）、**链接**

(1) 验证（Verify）：字节码验证器将验证生成的字节码是否正确，如果验证失败，将提示验证错误；

(2) 准备（Prepare）：对于所有静态变量，内存将会以默认值进行分配；

(3) 解释（Resolve）：有符号存储器引用都将替换为来自方法区（Method Area）的原始引用。

3）、**初始化**

这是类加载的最后阶段，所有的静态变量都将被赋予原始值，并且静态区块将被执行。

* **类执行机制**

JVM是基于堆栈的虚拟机。JVM为每个新创建的线程都分配一个堆栈.也就是说,对于一个Java程序来说，它的运行就是通过对堆栈的操作来完成的。堆栈以帧为单位保存线程的状态。JVM对堆栈只进行两种操作:以帧为单位的压栈和出栈操作。

JVM执行class字节码，线程创建后，都会产生程序计数器（PC）和栈（Stack），程序计数器存放下一条要执行的指令在方法内的偏移量，栈中存放一个个栈帧，每个栈帧对应着每个方法的每次调用，而栈帧又是有局部变量区和操作数栈两部分组成，局部变量区用于存放方法中的局部变量和参数，操作数栈中用于存放方法执行过程中产生的中间结果。栈的结构如下图所示：

![](/files/-Ltdv9mwYzh0gmWrtyvD)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tuonioooo-notebook.gitbook.io/performance-optimization/jvmyou-hua-pian/javacheng-xu-yun-xing-yuan-li-fen-xi.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
