jvm虚拟机之堆和方法区

堆和方法区是jvm内存模型中重要的结构。jdk8中,逻辑上的划分:堆存放对象实例,而方法区存放类信息(如变量、方法信息等)这段空间也叫元空间(metaspace),静态变量和常量池(主要用于存放字符串常量和用于寻找具体变量及方法信息的索引)。物理上,元空间占用的是本地直接内存,而剩下的占用的是jvm中的内存。
我们平常创建的对象基本会放在堆中,创建对象的方法有如下几种:

  • new 一个对象,这是我们最常用的
  • class.newInstance() 通过反射创建
  • clone
  • 反序列化
    存放在堆中的对象不是一成不变的,jvm会进行垃圾回收,对用不到的对象进行回收,防止堆占用空间过高。对象存活时间一般是朝生夕死。即存活的时间很短。然后存活越久的对象有更大概率一直活着。根据这个现象,将堆划分为两块区域,进行不同的频率的回收。如图是堆空间划分:
    堆空间划分分为新生代和老年代。刚建立的对象会先放在新生代中,当新生代满了之后,发生GC,称为minorGC。当对象熬过15次(jvm设定,可修改)GC。会将其转移到老年代。老年代满了之后,也会发生GC,称为majorGC。可以看出新生代GC频率更高。新生代空间:老年代空间=1:2。
    新生代中,为了进行垃圾回收,还分为eden区和survivor。图中from和to都是survivor区。eden区存放新建立的对象,而其中一个survivor存放已经活下几次回收的对象。另一个survivor用来存放下一次GC后仍存活的对象。比如from先存放活了几轮的对象,MinorGC后,会将存活的对象都放在to区,然后清空from区。from和to只是一个说法,会根据情况改变。比如上面讲到的,to区有数据后就是from区了。
    当然根据不同情况,对象转移情况不同,不一定熬过15次才进入老年代。可以看下图。
    垃圾回收中对象转移过程我们已经在堆中创建了对象,那怎么知道这个对象被谁使用?这就靠引用,类似于地址。变量通过引用指向对象。那怎么通过对象来调用类中的方法呢,(静态方法和普通的方法)。同样也是通过引用对象中存放着对类信息的引用。下面来了解一下对象头和对象创建过程。
    对象由,对象头,对象中的变量(如果是int short等占四字节,如果是double float占8字节。如果是对象,占四字节)和对齐字节(用于补充对齐),对象头由如下部分组成
    对象头通过类型指针指向对象类型,即他的类信息所在地址。
    下面讲一下对象创建过程:
  • 加载类信息,如果类还没加载先加载类
  • 为对象分配内存,由上述可知,对象中大小是可以编译期就知道的,分配内存方法有,指针碰撞和空闲列表法,有兴趣的可以去了解一下
  • 默认初始化,给对象变量赋值为Null。给基本类型赋值为 0,false。‘
  • 初始化,即调用初始化代码块 构造函数进行初始化。
    以上是java堆中的一些基本概念。下面讲一下方法区。
    方法区是否发生GC全靠虚拟机本身设置。虚拟机规范中没有要求。让方法区发生GC的要求也很苛刻,可以说基本不发生GC。这也可能是方法区上的东西不直接放堆里的原因。因为类信息,只要有他对象实例存在就会用到,而且可能会被类加载器动态加载。只有不满足上述条件之后才可能发生GC。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值