少年帮|JVM内幕:Java虚拟机详解( 六 )

加载了标准 Java 扩展 API 中的类 , 比如 security 的扩展函数 。

  • System 加载器是应用的默认类加载器 , 比如从 classpath 中加载应用类 。
  • 用户自定义类加载器也可以用来加载应用类 。 使用自定义的类加载器有很多特殊的原因:运行时重新加载类或者把加载的类分隔为不同的组 , 典型的用法比如 web 服务器 Tomcat 。

  • 少年帮|JVM内幕:Java虚拟机详解加速类加载共享类数据(CDS)是Hotspot JVM 5.0 的时候引入的新特性 。 在 JVM 安装过程中 , 安装进程会加载一系列核心 JVM 类(比如 rt.jar)到一个共享的内存映射区域 。 CDS 减少了加载这些类需要的时间 , 提高了 JVM 启动的速度 , 允许这些类被不同的 JVM 实例共享 , 同时也减少了内存消耗 。
    方法区在哪里The Java Virtual Machine Specification Java SE 7 Edition 中写得很清楚:“尽管方法区逻辑上属于堆的一部分 , 简单的实现可以选择不对它进行回收和压缩 。 ” 。 Oracle JVM 的 jconsle 显示方法区和 code cache 区被当做为非堆内存 , 而 OpenJDK 则显示 CodeCache 被当做 VM 中对象堆(ObjectHeap)的一个独立的域 。
    Classloader 引用所有的类加载之后都包含一个加载自身的加载器的引用 , 反过来每个类加载器都包含它们加载的所有类的引用 。
    运行时常量池JVM 维护了一个按类型区分的常量池 , 一个类似于符号表的运行时数据结构 。 尽管它包含更多数据 。 Java 字节码需要数据 。 这个数据经常因为太大不能直接存储在字节码中 , 取而代之的是存储在常量池中 , 字节码包含这个常量池的引用 。 运行时常量池被用来上面介绍过的动态链接 。
    常量池中可以存储多种类型的数据:
    • 数字型
    • 字符串型
    • 类引用型
    • 域引用型
    • 方法引用
    示例代码如下:
    Object foo = new Object();写成字节码将是下面这样:
    0:new #2// Class java/lang/Object1:dup2:invokespecial #3// Method java/ lang/Object ""( ) Vnew 操作码的后面紧跟着操作数 #2。 这个操作数是常量池的一个索引 , 表示它指向常量池的第二个实体 。 第二个实体是一个类的引用 , 这个实体反过来引用了另一个在常量池中包含 UTF8 编码的字符串类名的实体(// Class java/lang/Object) 。 然后 , 这个符号引用被用来寻找 java.lang.Object 类 。 new 操作码创建一个类实例并初始化变量 。 新类实例的引用则被添加到操作数栈 。 dup 操作码创建一个操作数栈顶元素引用的额外拷贝 。 最后用 invokespecial 来调用第 2 行的实例初始化方法 。 操作码也包含一个指向常量池的引用 。 初始化方法把操作数栈出栈的顶部引用当做此方法的一个参数 。 最后这个新对象只有一个引用 , 这个对象已经完成了创建及初始化 。
    如果你编译下面的类:
    package org.jvminternals;public class SimpleClass {public void sayHello() {System.out.println("Hello");} }生成的类文件常量池将是这个样子:
    Constant pool:#1 = Methodref#6.#17//java/lang/Object."":()V#2 = Fieldref#18.#19//java/lang/System.out:Ljava/io/PrintStream;#3 = String#20//"Hello"#4 = Methodref#21.#22//java/io/PrintStream.println:(Ljava/lang/String;)V#5 = Class#23//org/jvminternals/SimpleClass#6 = Class#24//java/lang/Object#7 = Utf8#8 = Utf8()V#9 = Utf8Code#10 = Utf8LineNumberTable#11 = Utf8LocalVariableTable#12 = Utf8this#13 = Utf8Lorg/jvminternals/SimpleClass;#14 = Utf8sayHello#15 = Utf8SourceFile#16 = Utf8SimpleClass.java#17 = NameAndType#7:#8//"