浅谈Java文件被执行的历程

Java的编译过程

Java程序从源文件创建到程序运行要经过两大步骤

1、源文件由编译器编译成字节码(ByteCode)

2、字节码由java虚拟机解释运行。因为java程序既要编译同时也要经过JVM的解释运行,所以说Java被称为半解释语言("semi-interpreted" language)。

一个例子

下面我们通过一个简单的 OneTest.java,来看一下一个java文件从编译到运行的历程。

Public class OneTest{
    public static void main(String[] args){
          Person one = new Person();
           one.say();
    }
}
Public class Person{
    private String name;

    public void say(){
       System.out.println("I `m a Person");
   }
}

这里是两个java文件,分别是OneTest.java,Person.java

第一步

首先是编译阶段,由JVM编译器,将OneTest.java文件进行编译,得到字节码文件(OneTest.class),这里我们发现,OneTest.java中依赖了Person对象,也就是需要Person.java文件,编译器便会检索Persion.java是否被编译(是否存在Person.class),若不存在,则先编译Person.java,java编译一个类时,如果这个类所依赖的类还没有被编译,编译器会自动的先编译这个所依赖的类,然后引用。

1、如果java编译器在指定的目录下找不到该类所依赖的类的 .class文件或者 .java源文件,就会报“Cant found sysbol”的异常错误。

2、编译后的字节码文件格式主要分为两部分:常量池和方法字节码。
常量池记录的是代码出现过的常量、类名、成员变量(Person.java中的类Person名、name成员变量)等以及符号引用(类引用、方法引用(OneTest.java中的person.say),成员变量引用等);方法字节码中放的是各个方法的字节码。

第二步

然后进行解释运行阶段,这里运行阶段分为两步:类的加载和类的执行

JVM主要在程序第一次主动使用类的时候,才会去加载该类。也就是说,JVM并不是在一开始就把一个程序就所有的类都加载到内存中,而是到不得不用的时候才把它加载进来,而且只加载一次。

1、OneTest类的加载:在类路径下找到编译好的 java 程序中;得到 OneTest.class 字节码文件后,系统就会启动一个 JVM 进程,JVM进程从classpath路径下找到一个名为OneTest.class的二进制文件,将OneTest.class文件中的类信息加载到运行时数据区的方法区中,这一过程叫做类的加载。(只有类信息在方法区中,才能创建对象,使用类中的成员变量)关于类的加载器

2、运行OneTest.java中的main方法:main函数的第一条命令是Persion person = new Person();就是让JVM创建一个Person对象,但是这时候方法区中没有Person类的信息,所以JVM马上加载Person类,把Person类的类型信息放到方法区中。

3、加载完Person类之后,Java虚拟机做的第一件事情就是在堆区中为一个新的Person实例分配内存, 然后调用构造函数初始化Person实例,这个Person实例持有着指向方法区的Person类的类型信息(其中包含有方法表,java动态绑定的底层实现)的引用

4、当使用person.say()的时候,JVM根据person引用找到Person对象,然后根据Person对象持有的引用定位到方法区中Person类的类型信息的方法表,获得say()函数的字节码的地址。

5、执行say方法。

以上就是浅谈Java文件被执行的历程的详细内容,更多关于Java文件被执行的历程的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java中for循环的执行过程分析

    本文实例分析了Java中for循环的执行过程.分享给大家供大家参考.具体分析如下: public class Test01{ public static void main(String[] args) { int i = 0 ; for(foo('A');foo('B')&&i<3;foo('C')){ i++ ; foo('D') ; } } public static boolean foo(char c){ System.out.print(c + " "

  • Java程序执行过程及内存机制详解

    本讲将介绍Java代码是如何一步步运行起来的,其中涉及的编译器,类加载器,字节码校验器,解释器和JIT编译器在整个过程中是发挥着怎样的作用.此外还会介绍Java程序所占用的内存是被如何管理的:堆.栈和方法区都各自负责存储哪些内容.最后用一小块代码示例来帮助理解Java程序运行时内存的变化. Java程序执行过程 步骤 1: 写源代码,源代码将以.java的文件格式保存在电脑硬盘中. 步骤 2: 编译器(compiler)检查是否存在编译期错误(例如缺少分号,关键字拼写错误等).若通过检测,编译器

  • Java初始化块及执行过程解析

    问题:Java对象初始化方式主要有哪几种?分别是什么? 针对上面的问题,想必大家脑海中首先浮现出的答案是构造器,没错,构造器是Java中常用的对象初始化方式. 还有一种与构造器作用非常相似的是初始化块,它可以对Java对象进行初始化操作.下面主要阐述Java的初始化块及执行过程. Java初始化块其实是Java类的成员之一,其语法格式如下: [修饰符]{ //初始化块的可执行代码 ... } 初始化块的修饰符只能是static,使用static修饰符的初始化块称为静态初始化块,后面会介绍到. 下

  • java 异常被catch后 将会继续执行的操作

    我就废话不多说了,大家还是直接看代码吧~ import java.util.UUID; public class Test { public static void main(String[] args) { try { int i = 2/0; } catch (Exception e) { e.printStackTrace(); } try { System.out.println("try2"); } catch (Exception e) { // TODO: handle

  • 详解java中Reference的实现与相应的执行过程

    一.Reference类型(除强引用) 可以理解为Reference的直接子类都是由jvm定制化处理的,因此在代码中直接继承于Reference类型没有任何作用.只能继承于它的子类,相应的子类类型包括以下几种.(忽略没有在java中使用的,如jnireference) SoftReference WeakReference FinalReference PhantomReference 上面的引用类型在相应的javadoc中也有提及.FinalReference专门为finalize方法设计,另

  • java多线程中执行多个程序的实例分析

    我们知道多线程因为同时处理子线程的能力,对于程序运行来说,能够达到很高的效率.不过很多人对于多线程的执行方法还没有尝试过,本篇我们将为大家介绍创建线程的方法,在这个基础上,对程序执行多条命令的方法进行展示.下面我们就来看看具体的操作步骤吧. 1.创建线程对象我们需要用到Thread类,该类是java.lang包下的一个类,所以调用时不需要导入包.下面我们先创建一个新的子类来继承Thread类,然后通过重写run()方法(将需要同时进行的任务写进run()方法内),来达到让程序同时做多件事情的目的

  • Java如果在try里面执行return还会不会执行finally

    前言 我们都知道,finally在捕获异常的操作中,总是最后并且一定会执行的.那么,如果我在使用try finally的时候,如果try 给了一个return,那么还会不会执行finally呢?这里就来试一试 finally Finally代码不管有没有异常发生它都会执行. 没有异常发生的时候,在try内的代码执行结束后,执行finally. 如果发生了异常并且给catch捕获,则在执行完catch之后执行finally. 如果有异常且未被捕获,则在异常被抛给上层之前执行. 事实上,不用try

  • Java使用多线程异步执行批量更新操作方法

    写在前面: 相信不少开发者在遇到项目对数据进行批量操作的时候,都会有不少的烦恼,尤其是针对数据量极大的情况下,效率问题就直接提上了菜板.因此,开多线程来执行批量任务是十分重要的一种批量操作思路,其实这种思路实现起来也十分简单,就拿批量更新的操作举例: 整体流程图 步骤 获取需要进行批量更新的大集合A,对大集合进行拆分操作,分成N个小集合A-1 ~ A-N . 开启线程池,针对集合的大小进行调参,对小集合进行批量更新操作. 对流程进行控制,控制线程执行顺序. 按照指定大小拆分集合的工具类 impo

  • 详解java中finalize的实现与相应的执行过程

    FinalReference引用 此类是一个package类型,表示它并不是公开的一部分,继承自Reference, 即表示也是一种特定的引用类型,因此每个包装在其中的对象在被回收之前,自己都会放到指定的referqyebceQueue当中. 这个引用对象专门为带finalize方法的类服务,可以理解为每一个有相应的方法的对象,其都会封装为一种finalRefernece对象. 因为finalize方法是object定义的,其默认实现为空.那么如果重写了此方法,那么方法体肯定不为空.即可以通过这

  • 浅谈Java文件被执行的历程

    Java的编译过程 Java程序从源文件创建到程序运行要经过两大步骤 1.源文件由编译器编译成字节码(ByteCode) 2.字节码由java虚拟机解释运行.因为java程序既要编译同时也要经过JVM的解释运行,所以说Java被称为半解释语言("semi-interpreted" language). 一个例子 下面我们通过一个简单的 OneTest.java,来看一下一个java文件从编译到运行的历程. Public class OneTest{ public static void

  • 浅谈Java文件执行顺序、main程序入口的理解

    在我们通过JVM编译Java后缀名的文件时,JVM首先寻找入口(main方法) public static void main(String[] args) 1.由于在入口时,未调用任何对象,该方法只能设置为static静态 2.JVM为Java的最底层,所以即使有返回结果,结果也无处可去,因此该方法必然是void无返回值 3.由于main方法是入口,被JVM自动调用,只有将该方法设置为public公有级别才能对JVM可见 综上,入口main方法只能写为 public static void m

  • 浅谈java 执行jar包中的main方法

    浅谈java 执行jar包中的main方法 通过 OneJar 或 Maven 打包后 jar 文件,用命令: java -jar ****.jar 执行后总是运行指定的主方法,如果 jar 中有多个 main 方法,那么如何运行指定的 main 方法呢? 用下面的命令试试看: java -classpath ****.jar ****.****.className [args] "****.****"表示"包名": "className"表示&

  • 浅谈java定时器的发展历程

    在开发中,我们经常需要一些周期性的操作,例如每隔几分钟就进行某一项操作.这时候我们就要去设置个定时器,Java中最方便.最高效的实现方式是用java.util.Timer工具类,再通过调度java.util.TimerTask任务. Timer是一种工具,线程用其安排以后在后台线程中执行的任务.可安排任务执行一次,或者定期重复执行.实际上是个线程,定时调度所拥有的TimerTasks. TimerTask是一个抽象类,它的子类由Timer安排为一次执行或重复执行的任务.实际上就是一个拥有run方

  • 浅谈Java安全编码之文件和共享目录的安全性

    目录 一.linux下的文件基本权限 二.linux文件的特殊权限 2.1.Set UID 和 Set GID 2.2.Sticky Bit 2.3.SUID/SGID/SBIT权限设置 三.文件隐藏属性 四.特殊文件 五.java中在共享目录中使用文件要注意的问题 六.安全目录 一.linux下的文件基本权限 chmod是linux下面的权限管理命令,我们可以通过chmod来对文件的权限进行修改. 普通文件的权限有三种,rwx分别是读,写和执行.再加上三个用户分组:owner,group,ot

  • 浅谈js文件引用方式及其同步执行与异步执行

    任何以appendChild(scriptNode) 的方式引入的js文件都是异步执行的 (scriptNode 需要插入document中,只创建节点和设置 src 是不会加载 js 文件的,这跟 img 的与加载不同 ) html文件中的<script>标签中的代码或src引用的js文件中的代码是同步加载和执行的 html文件中的<script>标签中的代码使用document.write()方式引入的js文件是异步执行的 html文件中的<script>标签src

  • 浅谈Java finally语句到底是在return之前还是之后执行(必看篇)

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语句是不会被执行的: (1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到. (2)在try块中有System.exit(0);这样的语句,System.exit(0);

  • 浅谈java 中文件的读取File、以及相对路径的问题

    一.对于java项目中文件的读取 1.使用System 或是 系统的Properties对象 ①直接是使用 String relativelyPath=System.getProperty("user.dir"); ②使用Properties对象 我们先来遍历一下系统的属性: Properties properties = System.getProperties(); Enumeration pnames = properties.propertyNames(); while (pn

  • 浅谈Java中spring 线程异步执行

    多线程并发处理起来通常比较麻烦,如果你使用spring容器来管理业务bean,事情就好办了多了.spring封装了Java的多线程的实现,你只需要关注于并发事物的流程以及一些并发负载量等特性,具体来说如何使用spring来处理并发事务: 1.了解 TaskExecutor接口 Spring的TaskExecutor接口等同于java.util.concurrent.Executor接口. 实际上,它存在的主要原因是为了在使用线程池的时候,将对Java5的依赖抽象出来. 这个接口只有一个方法exe

  • 浅谈Java中File文件的创建以及读写

    1.创建一个文件 @Test public void test6() throws IOException { File file1 = new File("C:\\IDEA\\h1.txt"); if(!file1.exists()){//文件不存在 file1.createNewFile(); System.out.println("创建成功"); }else{//文件存在 file1.delete(); System.out.println("删除成

随机推荐