zoukankan      html  css  js  c++  java
  • java内存

    java虚拟机内存结构

    • 程序计数器
      程序计数器属于线程私有,存储下一条待执行的指令的地址,实现跳转、循环、分支等功能,程序计数器不存在内存溢出OOM的问题。

    • 虚拟机栈
      虚拟机栈属于线程私有,线程每执行一个方法时都创建一个栈帧,栈帧包含了该方法的局部变量表(包括八大基本数据类型的变量、对象引用)、操作数栈、动态链接、方法出口等信息,每一个方法的执行对应栈帧的入栈和出栈过程。线程如果请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。虚拟机栈动态扩展过程中,如果超过规范的大小,抛出OutofMemoryError异常。

    • 本地方法栈
      本地方法栈属于线程私有,虚拟机栈为执行的java方法服务,本地方法栈为Native方法服务。同虚拟机栈,也可能会抛出SOE和OOM异常。(Native方法???查找)

    • 方法区
      方法区是各个线程共享的内存区域。方法区主要存放类的信息,常量,静态变量。内存不够时,抛出OOM异常。


    • java堆主要存放对象实例和数组。Java堆是垃圾收集器管理的主要区域,在垃圾回收中,将堆划分为新生代、老年代,还可以划分出每个线程私有的分配缓冲区。Java堆物理上不连续,逻辑上连续。内存不够分配内存时,抛出OOM异常。

    • 运行时常量池
      class文件包含类的版本、字段、方法、接口等信息外,还包括常量池信息,指类中的字面量和符号引用。在类加载时常量池存放在java内存中的运行时常量池中。

    对象创建过程(hotspot虚拟机)

    类加载->内存分配->初始化为0->配置对象->执行init方法

    1. 类加载
      首先检查类是否被加载过,如果没有,必须先执行相应的类加载过程。
    2. 内存分配
      对象所需内存的大小在类加载完成之后便已经确定。内存分配有两种实现方式:
      • 指针碰撞。假设java堆内存是绝对规整的,可以使用的内存在一边,已经使用的在另一边,中间存放着指针作为分界点的指示器,内存分配就是将指针向空闲的内存移动对象大小相等的距离,
      • 空闲列表。java堆中内存可用和空闲的内存是交替的,空闲列表记录堆中哪些内存块是可用的,当需要分配内存时,从空闲列表中找到一块合适的空间分配给对象。
    3. 初始化为0
      内存分配之后,虚拟机将分配到的内存都初始化为零值,这一操作保证了对象实例字段在java代码中可以不赋初始值就可以直接食用,程序能访问到这些字段的数据类型所对应的零值。
    4. 配置对象
      对对象进行必要的设置,包括这个对象属于哪个类,如何找到这个类的元数据信息,对象的哈希码,对象的GC分代年龄等信息,这些信息存放在对象的对象头中。
    5. 方法
      执行init方法,把对象按照开发者的意愿进行初始化。

    对象的内存布局

    对象在内存中存储的信息包括对象头,实例数据,对象填充。

    • 对象头
      存储对象运行所需要的数据,如哈希码,GC分代年龄、锁状态标志等。另一部分是类型指针,对象通过类型指针找到所属于的类。
    • 实例数据
      对象存储的有效信息,程序代码中所定义的字段内容。
    • 堆起填充
      起占位符作用。对象的起始地址必须是8的整数倍。

    对象的访问定位

    • 句柄访问
      堆中存放着某个对象的句柄池,引用则存放句柄池的地址。句柄池中包含指向对象的地址以及指向对象所属类的地址。
    • 指针访问
      引用直接存放对象的地址,
  • 相关阅读:
    剑指 Offer——13. 调整数组顺序使奇数位于偶数前面
    剑指 Offer——3. 从尾到头打印链表
    剑指 Offer——2. 替换空格
    剑指 Offer——1. 二维数组中的查找
    LeetCode 905. Sort Array By Parity 按奇偶校验排列数组
    LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素
    SSH 代码笔记
    anaconda3安装caffe
    opencv多版本安装
    人脸文章与数据库
  • 原文地址:https://www.cnblogs.com/a1225234/p/11068385.html
Copyright © 2011-2022 走看看