• Home
  • About
    • yukiiris photo

      yukiiris

      少说话,多读书

    • Learn More
    • Twitter
    • Facebook
    • Instagram
    • Github
    • Steam
  • Posts
    • All Posts
    • All Tags
  • Projects
  • Moon

理解JAVA虚拟机(一)

21 Sep 2017

Reading time ~1 minute

1. 运行时的数据区域

  • 程序计数器
    • 为了线程切换后恢复正常执行顺序
    • 各个线程间互不影响
  • Java虚拟机栈/栈内存
    • 栈帧(即操作系统概念中的堆栈?):线程私有,存储局部变量表、操作数栈、动态链接、方法出口等信息
    • 局部变量表:存放编译期可知的基本数据类型、对象引用、returnAdress
    • 会抛出两种异常:请求栈深度大于所允许的深度、没有足够内存
  • 本地方法栈:与虚拟栈类似
  • Java堆/垃圾堆
    • 是Java虚拟机所管理的内存中最大的
    • 被所有线程共享,在启动是创建
    • 存放对象实例
    • 是垃圾收集器管理的主要区域
  • 方法区/非堆
    • 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译的代码等
  • 运行时的常量池
    • 方法区的一部分
    • 存放编译期生成的各种字面量和符号引用
    • 动态性
  • 直接内存:与JVM无关,与NIO有关

2. 虚拟机对象

  • 对象的创建
    • 检查常量池中是否有这个类的符号引用以及是否被加载,解析、初始化
    • 分配内存,虚拟机会维护一个内存列表以知道有哪些内存可用
    • 虚拟机设置对象信息,存放在对象头中
    • 执行
String a = "100";
String b = "100";

String c = new String("100");
String d = new String("100");

System.out.println(a == b);//true
System.out.println(c == b);//false

      这是因为虚拟机在创建b的时候会想去常量池看一下有没有同意为“100”的对象,如果发现了,会将b指向这个对象的引用;而创建c、d的时候,是强制要求分配不同的新内存的,所以不是同一个对象。

  • 对象的内存布局
    • 对象头:包含两部分,一部分存储对象自身运行时的数据(如哈希码、GC年龄分代)、类型指针(确定对象属于哪个类)
    • 实例数据:有效信息
    • 对齐填充:占位符

3. 对象的访问定位

  • 句柄
    • Java堆中分出一块句柄池
    • Java栈本地变量表中的reference指向句柄地址、句柄包含指向实例数据和类型数据的指针
    • 优点:稳定
  • 直接指针
    • reference指向堆中的指针,指针和实例数据存在一起,指针指向类型数据
    • 快


JVMJava Share Tweet +1