JVM内存管理

内存区域

Java的内存区域主要包括虚拟机栈,本地方法栈,程序计数器,堆,方法区。

虚拟机栈 是对应于每个线程运行时候的东西,JVM会给每个线程分配一个栈,线程运行就是执行栈里面的东西。这个栈又包含了帧,帧对应着线程函数。栈里面只能够出帧和入帧,对应着每个函数的运行和运行完成。

本地方法栈 是每个线程native代码对应的部分。与虚拟机栈很相似,但是本地方法栈执行的是Java Native方法。

程序计数器 可以看作是当前线程执行字节码的行号指示器。字节码解释器可以通过改变程序计数器的值来选取下一条需要执行的指令。分支,循环,跳转都需要这个计数器来实现。

JAVA堆 是所有线程共享的,每次new的时候,JVM就会在Java堆里面划一块区域。平时的内存溢出也基本都是这块区域超出了。

JAVA方法区 是存储着已经加载的类,常量,静态变量等数据。方法区,也常被称作永久代,方法区很少进行垃圾回收,回收也非常严苛。如果这个区域出现异常,则一般会提示PermGen space。

引用

Java中有四种引用,强引用,软引用,弱引用,虚引用。JVM对每种类型的回收是不一致的。

强引用是Java中最常见的,一般我们使用的Object object = new Object就是强引用。一个对象只要存在强引用,对象就不会被回收,如果内存不够,就抛出OutOfMemory异常。

软引用是如果一个对象只有软引用,那么在内存足够的时候对象不会回收该对象,如果内存不够的时候对象就会被回收。软引用适合作高速缓存。

软引用可以和引用队列一起使用,当引用对象被回收的时候,会被虚拟机加入到引用队列里面去。

SoftReference<Object> softObject = new SoftReference(new Object(),new ReferenceQueue<Object>())

弱引用是一个对象如果只有弱引用,那么对象在下次垃圾回收的时候,不管内存足不足够都会被回收。它比软引用的周期更短,不过垃圾回收是一个优先级非常低的线程,对象实际上被回收也不会那么快。它也可以跟一个引用队列一起使用。

虚引用是一个更加弱小的引用,只有虚引用的对象不知道对象什么时候会被回收。它主要用来跟踪对象被垃圾回收的活动。它一定要跟一个引用队列一起使用。

垃圾回收

Java会有一个单独垃圾回收进程,对虚拟机在程序新建的但已经没有用的对象进行回收。对于如何判断对象是否还在使用,这里面有两种常见的方式是引用计数法跟可达性分析法。引用计数法通过给每个对象的引用进行计数,这种方式很简单,并且效率高。但是在解决循环引用的时候效果并不好。而主流的编程语言都是采用可达性分析法来进行对象是否还有用的判断的,可达性分析法通过一系列的“GC ROOT”对象,通过其引用的对象以及这些对象的引用不断地循环扩展,构成一颗引用树,那些没有在这颗树上的对象就是没有用的,可以被回收的对象了。

垃圾收集算法有很多,像标记清除算法,复制算法,标记整理算法,分代收集算法等等。

内存分配策略

JVM在内存分配的时候遵循着一些规则:

  1. 对象优先分配在Eden区
  2. 大对象直接分配在老年代,老年代的回收是非常少的,老年代的回收是一次Full GC。
  3. 长期存活的对象进入老年代
  4. 动态对对象年龄的判断,如果Eden区有相同年龄的对象内存之和超过新生代空间一半,则将年龄超过这些年龄相同对象的对象都移到老年区
  5. 空间分配担保,在进行minor GC前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的总空间,如果大于则直接GC,如果不大于,则要根据之前新生代到老年代的对象的平均大小来判断,如果老年代连续可用空间比平均大小大,则继续minor GC,如果不大,则进行一次Full GC。
    内存代,新生代,老年代,永久代
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值