Java 核心技术 0 —— Class加载 和 运行时数据区域

在这里插入图片描述

         JVM 是 字节码的运行环境,负责装载class到JVM内部,解释编译为对应平台的机器码指令,用来进行执行;对于JVM设计来说,有权威的定义规范,做为一个合格的Java程序员,了解 JVM 的 类加载 细节 和 运行时数据区域组成 等理论上的知识,对了解Java技术体系的设计和发展来说都是一件很有意义的事情。

        这么一个场景:磁盘上有一个.java文件,你通过编译器的javac 命令把它编译成了一个平台无关的.class 文件,相信大家都干过。其本质就是一个本地机器码变成字节码的过程。当变成.class File之后的故事,在Java技术体系中,就另一个即将展开JVM如何运转的新世界了。

        首先,就要聊到JVM的类加载机制了。

  1. 加载loading过程:将类的文件,网络等其他方式生成的字节流 注入JVM内存中,同时将Klass 类模板信息 放到方法区中,并创建一个指向 该Klass 的 java.lang.Class对象放到堆中。
  2. 链接Linking:
    1.  Verification 校验阶段 : 校验当前由class文件变成的字节流是否正确的符合规范,一般有格式验证(这一步是配合加载阶段完成的)、语义验证、符号引用验证等 。
    2. Preparation 准备阶段: 为属于类域的静态变量分配存储空间并赋一个初始零值 。基本类型设置对应初始值,引用类型设置null,基本类型常量跟字符串字面量(final static修饰)设置为具体的值。
    3. Resolution 解析阶段:把类中的符号引用转换为直接引用,如果不理解符号引用跟直接引用可以参考知乎文章
  3. Initialization 初始化,调用类构造< clinit >()方法,对类变量及静态代码块进行赋值。

program counter register 程序计数器寄存器

        内存较小,它是当前线程所执行的class文件上的字节码byte code 行号的指示器。在JVM设计的概念模型,字节码解释器在工作的时候,需要改变这个计数器的值来选取下一条需要执行的字节码指令,Java的 if分支,forwhile循环,break跳转,trycatch异常,线程切换 等程序控制流的基础功能实现都需要这个计数器来实现。每一个线程都会有一个program counter register ,否则它就无法恢复到它能正确执行的位置。场景举例:你开辟了99个线程来帮你办事,就要99个程序计数器。各个线程间的计数器互不影响,独立存储,这类内存区域就是线程私有的内存。

JVM Stack 虚拟机栈       

        是程序执行字节码即运行方法时必须的一片空间,也是线程私有,即 99个线程进入这个方法时,每个方法都会来一片这样的内存空间。在进入一个方法前,需要多少槽数的局部变量表(基础数据类型+引用指针+线程切换恢复的地址位置returnAddress)是确定的(64位的数据 long,double 需要2个变量槽,其他1个槽就够了)。出现栈深度不够会抛出StackOverflowError和栈扩展失败会抛出 OOM OutOfMemeryError。

      program counter register 中的值 就是当前指令所在的内存地址,这类内存地址,returnAddress就是线程切换后的能恢复的地址位置。 

在这里插入图片描述

Native Method Stacks 本地方法栈

        JVM使用本地方法时需要的空间,也是线程私有的。和JVMStack一样,出现栈深度不够会抛出StackOverflowError和栈扩展失败会抛出 OOM OutOfMemeryError。

Java Heap 堆

        在JVM设计规范中,所有的对象和数组都应当在堆上分配空间,所以这块内存是JVM最大的内存空间。属于所有线程共有的内存区域,因为大家都会使用这个操场,那么这个区域的内存管理就GC机制尤为重要,也是GC大显身手的地方。

        当前Java堆大部分都被设计为大小可扩展的,可通过 -Xmx 和 -Xms 来设定 最大或最小范围。如果堆内存空间不足满足实例分配就会出现OOM。

Method Area 方法区

        各线程共享,它用于存储被JVM加载的class信息,常量,静态变量,JIT compile 之后的 code cache 代码缓存数据。《Java JVM规范》把Method Area 看作为 Heap的一个逻辑部分,所以Method Area 内存分配不足时也会抛出OOM异常。

Method Area 中有一部分叫做 Runtime Constant Pool 运行时常量池 ,  Class文件 中除了有类版本信息,字段,方法,接口 的描述外,还有一个存放编译期间生成的各种字面量和符号引用,这部分内容 在class load 后,存放在Method Area 的    运行时常量池中。

Direct Memory 直接内存

  • Direct Memory 并不是虚拟机运行时数据区的一部分;
  • 由于在 JDK 1.4 中引入了 NIO 机制,为此实现了一种通过 native 函数直接分配对外内存的,而这一切是通过以下两个概念实现的:
    • 通道(Channel);
    • 缓冲区(Buffer);
  • 通过存储在 Java 堆里面的 DirectByteBuffer 对象对这块内存的引用进行操作;
  • 因避免了 Java 堆和 Native 堆(native heap)中来回复制数据,所以在一些场景中显著提高了性能;
  • 直接内存出现 OutOfMemoryError 异常的原因是物理机器的内存是受限的,但是我们通常会忘记需要为直接内存在物理机中预留相关内存空间;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值