您的位置:首页 > 编程语言 > Java开发

一个Java程序的执行过程

2015-03-26 17:08 274 查看
我们手工执行java程序是这样的:

1 在记事本中或者是UE的文本编辑器中,写好源程序;

2 使用javac命令把源程序编译成.class文件;

编译后的.class(类字节码)文件中会包含以下内容:

ConstantPool:符号表;

FieldInfo:类中的成员变量信息;

MethodInfo:类中的方法描述;

Attribute:可选的附加节点。

FieldInfo节点包含成员变量的名称,诸如public,private,static等的标志。ConstantValue属性用来存储静态的不变的成员变量的值。Deprecated和Synthetic被用来标记一个成员变量是不被推荐的或由编译器生成的。

3 有了.class文件,我们执行 java 解释命令就可以运行java程序了。

现在我们主要讨论一下,当执行 java这个命令后,会发生什么事情呢?

首先,JVM装载.class,也就是类装载器装载类字节码。一个类装载器本身也是一个java类,所以,类装载器自身也需要被另外一个类装载器装载,这就出现了类似先有蛋,还是先有鸡的问题。但J***A中的类装载器的这个问题却很容易解决。J***A的虚拟机(JVM)中内嵌了一个称为Bootstrap类装载器,它是用特定于操作系统的本地代码实现的,属于J***A虚拟机的内核,Bootstrap类不用专门的类装载器去进行装载。Bootstrap类负责加载J***A核心包中的类(即rt.jar文件中的类),这些类的Class.getClassLoader()方法返回值为null,即表示是Bootstrap类装载器。J***A核心包中有另外两个类装载器:ExtClassLoader和AppClassLoader,它们都是用J***A语言编写的J***A类,其中ExtClassLoader类装载负责加载存放在<J***A_HOME>/jre/lib/ext目录下的jar包中的类,AppClassLoader负责加载应用程序的启动执行类,即当使用java命令去启动执行一个类时,J***A虚拟机使用AppClassLoader加载这个类。在编译和运行J***A程序时,都会通过ExtClassLoader类装载器去<J***A_HOME>/jre/lib/ext目录下的JAR包中搜索要加载的类,所以,如果将包含例如ServletAPI的jar包或者是javamail.jar包复制到该目录下,在编译Servlet或JavaMail程序时,就不必在CLASSPATH环境变量中增加包含ServletAPI的jar包或者是javamail.jar包文件。

以上,就是一个J***A程序执行的大致过程。

------------------------------------------


Java字节码程序的执行过程:



Java字节码程序的执行过程

Java程序在启动的时候首先交给JVM(一个JVM的运行创建一个独立的进程)一个拥有public static void main(string[] args)函数的类,JVM通过引导类加载器(Bootstrap ClassLoader)加载该类,加载完成之后进行校验、内存填充和结构化(即连接--校验/准备/分解),然后启用一个线程执行main函数(大多数可执行程序都有像main一样的入口函数约定,有些地方可以成为入口地址),在执行main函数的过程中碰到新的类,将会再次用ClassLoader加载该类,重复连接,并且继续执行main中调用的其它函数,依次反复,直到特定的终止条件发生,程序退出。

JVM执行连接是典型的动态链接,也就是在执行过程中按需加载类,所有加载类的工作都交由ClassLoader来完成。在后面谈到的Java字节码类文件格式?就是ClassLoader加载之后交给虚拟机的字节码格式,换句话来说JVM不管ClassLoader之前的类来源和格式,它只管ClassLoader加载之后的格式,理解这点很重要。

ClassLoader分为系统级和用户自定义级两类,通过用户自定义类加载器,可以完成自定义的类加载方式(如何自定义请参考该章的实战?部分)。

关于更多Java字节码的执行过程细节,在后面内容JVM抽象架构?中将会更进一步提到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: