Java虚拟机 -- 类加载模块

Java平台无关性是如何实现的?

  • 一次加载,到处执行,其实并不是Java语言实现了跨平台的特性,而是在任何的平台上都有JVM虚拟机,Java通过javac在编译时将.java文件生成字节码并存入到.class文件中,有了class文件才有了跨平台的基础,这样JVM才能解析,将字节码生成特定平台上的机器码
  • Java源码首先被编译成字节码,再有不同平台的JVM进行解析,Java语言在不同的平台上运行不需要进行重新编译,Java虚拟机在执行字节码时,把字节码转化成具体平台上的机器指令,所以所并不是Java语言支持跨平台性,而是在任何的平台上都有对应的JVM可以对其进行解析。

为什么JVM不直接将源码解析成机器码去执行?

理论上而言,完全可以直接解析源码,这样也可以跨平台,但是引入字节码有额外的好处

  • 字节码更便于虚拟机读取,不用在解析字符串,所以运行速度比直接解析源代码快。
  • 生成字节码的过程中,编译器可以预先作语法和安全性的检查,出错的机会更少。
  • 字节码比源码更加紧凑,文件尺寸更小,方便网络传输
  • 字节码不一定非要java源码生成其他一些语言也可以编译生成字节码。

Java是如何加载class文件?

  • Class Loader:依据特定的格式(全限定类名),加载class文件到内存
    • Runtime Data Area:JVM内存空间结构模型
  • Execution Engine(执行引擎):对命令进行解析(解析class文件中的字节码)
  • Native Interface(本地接口):融合不同开发语言的原生库为Java所用
  1. 编译器将  .java源文件编译成 .class字节码文件
  2. CLassLoader将字节码转化为JVM中的Class<>对象
  3. JVM通过Class<>对象,去实例化对象,操作类中的属性与方法

谈谈类加载器(ClassLoader)

  • ClassLoader在Java中有着非常重要的作用,它主要是工作在Class装载的加载阶段,其主要作用是从系统外部获得Class二进制数据流。是Java的核心组件,所有的Class都是由ClassLoader进行加载,ClassLoader负责通过将Class文件里边的二进制数据流装载进系统,然后交给Java虚拟机进行连接,初始化等操作。

双亲委派模型:

      

  • BoorStrapClassLoader:C++编写,加载核心类库 java.*
  • ExtClassLoader:Java编写,加载扩展库 javax.*
  • AppClassLoader:Java编写,加载程序所在目录 classPath路径

ClassLoader中的loadClass方法解析:

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
    	//防止多个线程加载同一个类,避免同步
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            //如果曾经加载过该类就直接返回
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                	//判断parent是否为空
                    if (parent != null) {
                    	//不为空再次调用loadClass方法去寻找是否存在加载过的类
                        c = parent.loadClass(name, false);
                    } else {
                    	//获取最顶层ClassLoader
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

为什么要使用双亲委派模型?

  • 避免加载多份重复的字节码

LoadClass和forName的区别?

类加载分为

  • 隐式加载:new   调用类加载器
  • 显示加载:loadClass,forName

两者之间的区别

  • 调用Class.forName方法时,会有一个boolean参数表示是否需要初始化,而Class.forName是默认需要初始化的,一旦初始化,就会触发目标对象的static代码块,去初始化static代码块
  • ClassLoader.loadClass方法中的第二个参数表示目标对象是否进行连接,默认情况下是false,不进行连接的,所以就不会初始化静态的部分。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值