JVM详解

谈谈你对java平台的理解?

java是具有跨平台特性的面向对象的设计语言,“一次编译,多处运行”是跨平台特性的体现。所谓一次编译指的是通过javac将java源文件编译成.class的字节码文件,而多处运行的基础和前提是JVM,因为JAVA是通过JVM将字节码文件解析成目标机器码的(JVM中的JIT即时编译器,可以将字节码直接转化为高性能的本地机器码。JDK1.9提供AOT(提前编辑、静态编译):即运行前直接将java源文件编译成机器码),而JVM的虚拟环境支持在多种平台上进行安装,这样就实现是跨平台运行的特性。
补充:JIT属于运行时编译(在将.class文件加载成机器码时,JVM类加载器首先加载字节码文件,然后通过解释器逐行解释执行,也就是解释与编译并存特性当中的解释),而有些需要经常被调用的代码块则运用JIT编译器完成第一次编译后,便将字节码对应的机器码保存下来供下次直接使用。

Java类加载器

  • 双亲委派机制:如果一个类加载器收到了加载某个类的请求,则该类加载器并不会去加载该类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是如此,因此所有的类加载请求最终都会传送到顶端的启动类加载器;只有当父类加载器在其搜索范围内无法找到所需的类,并将该结果反馈给子类加载器,子类加载器会尝试去自己加载。如下图:


    006y8mN6ly1g6ghzc5ff5j30mf0fndnr.jpg

    基于双亲委派机制避免了JDK中的基础类被覆盖掉的可能性,比如我们自己实现一个java.lang.String类来试图覆盖JDK中的String类是不会成功的。

  • JDBC是如何打破双亲委派规则的:在JDBC 4.0之后实际上我们不需要再调用Class.forName来加载驱动程序了,我们只需要把驱动的jar包放到工程的类加载路径里,那么驱动就会被自动加载。这个自动加载采用的技术叫做SPI(Service Provider Interface),数据库驱动厂商也都做了更新。可以看一下jar包里面的META-INF/services目录,里面有一个java.sql.Driver的文件,文件里面包含了驱动的全路径名。
    根据类加载机制,当被装载的类引用了另外一个类的时候,虚拟机就会使用装载第一个类的类装载器装载被引用的类。也就是说BootStrap类加载器在加载Driver的时候还要去加载jar包中的Driver接口的实现类,而我们知道BootStrap类加载器又只负责加载jre/lib/rt.jar里的class文件,所以就需要由子类加载器去加载Driver的实现类,这就破坏了双亲委派模型(具体是通过Thread.currentThread().getContextClassLoader() 得到的线程上下文加载器去加载这些实现类,而在 sun.misc.Launcher 初始化的时候,会获取AppClassLoader,然后将其设置为上下文类加载器,所以线程上下文类加载器默认情况下就是AppClassLoader)。

运行时数据区

  • 方法区:最重要的一个内存区域,多线程共享,保存了类的信息(类名、成员、接口、父类),线程共享区
  • 堆内存(Heap):解决的是数据存储的问题,保存对象的真实信息,该内存牵扯到释放问题(GC),线程共享区
  • 栈内存(Stack):解决程序的运行问题,即程序如何执行,或者说如何处理数据。包含(本地变量表,操作数栈,常量池引用,返回地址)


    运行时数据区.png

你可能感兴趣的:(JVM详解)