美文网首页
Java内存

Java内存

作者: Sakura羿 | 来源:发表于2018-06-27 20:59 被阅读0次

    一、Java内存区域:

    程序计数器(线程私有):当前线程所执行的字节码的行号指示器,字节码解释器通过这个计数器的值来选去下一条需要执行的字节码指令(分支,循环,跳转,异常处理,线程恢复)——每个线程都需要一个独立的程序计数器,如果线程执行的是java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,如果是Native方法,这个计数器为空。

    java虚拟机栈(线程私有):生命周期与线程相同,java方法执行的内存模型:每个方法执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用到执行完成,都对应着一个栈帧在虚拟机中入栈到出栈的过程。

    本地方法栈:虚拟机栈为虚拟机执行java方法(字节码)服务,本地方法栈为Native方法服务。

    java堆(线程共享):存储的是对象实例,垃圾收集器管理的主要区域,分为新生代和老年代(分代收集算法)

    方法区(线程共享):存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码,垃圾收集比较少出现,内存回收目标主要是针对常量池的回收和类型的卸载。

    运行时常量:方法区的一部分,

    直接内存:一种基于通道和缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存,通过一个存储在java堆中的DirectByteBuffer对象作为这块内存的引用进行操作(提高了性能,避免了在java堆和Native堆中来回复制信息)

    二、对象的创建

    new关键字(克隆和反序列化),虚拟机遇到new指令时,先检查这个指令的参数是否能在常量池定位到这个类的符号引用,并检查这个符号代表的类是否已被加载、解析和初始化过,若没,必须先执行类加载过程。类加载检查通过后,虚拟机为新生对象分配内存(类加载完成后对象所需的内存大小便可确定),为对象分配内存相当于把一块确定大小的内存从java堆中划分出来,分配方式有指针碰撞和空闲列表。

    三、对象在内存中分为三个区域:

    1. 对象头:64位虚拟机中是64bit(但不固定,如未被锁定时会缺少几个bit)两部分:

      • 存储对象自身的运行时数据:哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳
      • 类型指针:即对象指向它的类元数据的指针(通过这个指针来确定这个对象是哪个类的实例),虚拟机可以通过普通的java对象的元数据信息来确定Java对象的大小,但数组不可以,数组的对象头还需要一块用于记录数组长度的数据,
    2. 实例数据:对象真正存储的有效信息,包括从父类继承下来的,还有在子类中定义的,根据分配策略,默认的,相同宽度的字段总是分配到一起,父类在子类之前对其填充:填充为8字节的整数倍

    3. java程序通过栈上的reference访问具体对象的方式:句柄和直接指针

    相关文章

      网友评论

          本文标题:Java内存

          本文链接:https://www.haomeiwen.com/subject/idiiyftx.html