如何启动?java 命令

java命令是一个入口,执行的时候  会找到对应的执行文件,它会调用java api 接口(java api 接口和jvm 一起构成了jre),接口内部会调用其他接口创建虚拟机(虚拟内存,硬件,CPU等),

然后虚拟机会创建 bootstrap 类加载器,

bootstrap类加载器,会创建 扩展类加载器和应用程序类加载器,

应用程序加载器 会首先会去寻找 方法 public static void main(String ars[]) 作为项目的执行入口,

同时加载主函数所在的类,如果发现需要加载其他类,先看父类加载器有没有加载,如果没有,自己主动去加载,如果加载不了,在交由父类加载器加载。

一般来说:

bootstrap 类加载器  会加载java API 类,辅助jvm运行,

扩展类加载器会加载 jdk 的类库。

应用程序加载器 会加载项目下的class文件

主函数所在的类及相关类加载完毕后,

加载的结果就是 class文件 被加载的内存的方法区。

开始进入链接阶段 :校验java代码是否符合java规范,给类和接口的属性付默认值,把符号连接转化为直接连接。

然后 初始化阶段: 给类的静态变量赋值,执行静态初始化段。  (把变量放入常量区)

结束之后,

要开始执行代码了,

jvm 有一个执行引擎,可以通过解释执行的方式边解释边执行代码

也有其他引擎 ,比如jit (just in time) 是先解释,然后执行。

总之就是  执行引擎会 把字节码 转化为 指令,交由 操作系统执行。

执行的过程中,遇到方法就会押入栈中,

如果遇到方法中调用另外的方法,就得等待被调用方法执行完毕,从栈中取出,然后在执行第一个方法。

一个执行引擎遇到多个线程时候, 执行引擎就像CPU,会分时处理不同的线程,

这样 可能一个方法执行到了某个地方,就去执行另外一个线程的方法了,

所以执行到了什么位置,需要存储下来,

pc 计数器。

这就是 方法栈区的作用。

如果用jni 调用了c++ 的方法,会存放到本地方法栈。

换句话说,就是 不同线程在同一个jvm 中也会有自己的 pc 计数器,方法栈区,用来存储当前线程的执行状态。

但是多个线程之间的操作的数据是可能有交互的,比如说操作的是一个对象,这个对象就是共享的,存放在堆中,

还有一些常量和方法定义(代码段)的内容,也都是线程共享的。

堆中的对象在方法执行完毕之后,如果没有用了,会被垃圾回收机制自动回收。

java 执行引擎如何执行Java程序,从什么地方开始?

执行引擎 首先从 运行时常量池中查找 “主函数“的引用,

这个引用里存储了 主函数的在方法区内的实际地址,

然后执行引擎 去方法区内的实际地址找到主函数的字节码,

然后一个指令一个指令的读取,并且执行代码,

如果遇到调用某个类的某个方法,还需要再去常量池里 寻找 方法的 引用,然后找到具体的存放方法代码的内存地址。

然后再找到具体方法代码,然后再执行。

换句话说就是 

方法区里 存储的是 变量和方法的代码,静态变量和方法的代码。

运行时常量区 存储的是 常量 ,还有 所有变量和方法的引用 (引用存储的是具体的变量值和具体的方法代码所在的内存地址)

方法区包括 运行时常量区。