美文网首页
一、Java程序是如何运行的

一、Java程序是如何运行的

作者: 四纪 | 来源:发表于2018-03-02 08:30 被阅读0次

    Java中有一个虚拟机的概念,就是在机器和编译程序之间多了一层抽象的虚拟的机器,这个虚拟机在各个平台上都提供给编译程序一个共同的接口(这样就可以跨平台了吧?),编译程序只需要面向虚拟机,生成虚拟机能理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码。这种让虚拟机理解的代码叫字节码

    JVM就是Java虚拟机的英文缩写,全名是Java VirtualMachine,它是怎么工作的呢?我们先写一串代码,然后介绍这个代码的运行过程。

    public class Main {

        private static int size=1;

        public static void main(String args[]) {

            User u = new User();

            u.setName("Realsky");

            u.setPwd("110");

            String name = u.getName();

            String pwd = u.getPwd();

            u = null;

        }

    }

    class User {

        private String name;

        private String pwd;

        public String getName() {

            return name;

        }

        public void setName(String name) {

            this.name = name;

        }

        public String getPwd() {

            return pwd;

        }

        public void setPwd(String pwd) {

            this.pwd = pwd;

        }

    }

    装载

    JVM装载指定的class文件,最终形成这个class类的实例对象。

    JVM使用类装载器定位到相应的class文件,然后读取这个class文件(一个线性二进制工作流),把它传给JVM。然后JVM提取其中的类型信息,比如类的类名,方法名,变量名,修饰符,方法的返回类型等等。还要初始化常量池,里面保存了各种类型的所有常量。之后将这些东西放到一个叫方法区的地方,形成class类的实例,这个实例存放在内存的堆区,它成为java程序和内部数据结构之间的接口,程序要访问该类型的信息,就调用该类型对应的class实例对象的方法。

    比如:装载Main类,读取Main类的class文件,生成对应的java.lang.Class类的实例,读取其中的类型信息,比如修饰符private,public,static,变量size,name,pwd,User共同构成了这个类的常量池,将这些信息保存在方法区。

    连接

    验证类,保证这个类是没有错误的。

    确定类中类型符合Java语义,比如final类不能有子类,final方法不能被覆盖,等等。之后为类变量分配内存,设置默认值。最终在类型的常量类中寻找类、接口、字段和方法的复合引用替换成直接引用的过程。

    比如:连接Main类,JVM为size分配内存,并设默认值0,找到常量池中User类的引用,如果User类还没有装载就装载并连接这个类,然后将常量池中对User类的引用替换为直接引用,这个时候User类还没有初始化,因为还没有用到它。

    初始化

    初始化一些静态变量,让这个类可以跑起来。

    可能会调用()方法(这个方法只能由JVM来调用)来初始化该类的静态变量,调用这个方法之前,要确认超类的()方法已经调用完毕。

    比如:初始化Main类,JVM将Main类的静态变量赋值为1.

    使用

    User u = new User(); 

    创建一个User类实例,实际上是通过这个类的class实例实例化的,方法:

    User u=(User)Class.forName("User").newInstance();

    u.setName("RealSky"); u.setPwd("110");

    调用类的方法, 为该类的变量复制。JVM的调用过程是,通过方法区找到这个方法,利用class实例的如下方法调用:

    Class.forName("User").getMethod("setName").invoke(u,"RealSky");

    String name = u.getName(); String pwd = u.getPwd();

    和上一步类似,区别就是这个赋值给了其他变量,这个变量和实例对象一样,保存在堆区。而我们也发现了,class实例的作用就是起到一个中间作用,将程序中的调用放映到堆区上数据的变化。

    u = null;

    触发JVM的垃圾回收机制,使用完这个命令,User实例就没有被引用了,JVM就会回收这个实例。

    相关文章

      网友评论

          本文标题:一、Java程序是如何运行的

          本文链接:https://www.haomeiwen.com/subject/ciuoxftx.html