Java 内存管理概览

29 阅读2分钟

前言

大多数情况下无须对内存的分配、释放做太多考虑,对JVM也无须有多么深的理解。但写程序过程中也往往因为这样的原因那样的原因,造成很多不易察觉的内存问题。当内存问题出现的时候,也不能很快的定位并解决问题。

java程序,最终会编译成字节码运行在JVM上:

  • hotSpot
  • jRockit
  • J9
  • Dalvik
  • ART

JVM虚拟机内存 (java 7)

内存组成、内存分配过程、对象访问几个方面

java 运行时内存区

方法区、堆、程序计数器、虚拟机栈、本地方法栈

线程私有: 1.程序计数器 :字节码行号 2.java虚拟机栈:java方法执行的内存模型,每个方法被执行时都会创建一个栈帧,存储局部变量表、操作栈、动态链接、方法出口等。 3.本地方法栈

线程共享: java 堆: 方法区: 直接内存

内存分配过程

对象访问

内存溢出

  • 线程请求的栈深度大于虚拟机所允许的最大深度,如递归调用OOM
  • 虚拟机在扩展栈时无法申请到足够的内存,不停的创建线程触发OOM
  • 创建大量对象并且对象生命周期都很长的情况
  • 方法区存放Class等元数据信息,如产生大量类(CGLIB)

垃圾回收理论

java内存管理就是为了应对网站/服务访问慢的问题:

  1. 内存:垃圾回收占用CPU;存入太多的数据,造成内存泄漏
  2. 线程死锁
  3. I/O速度太慢
  4. 依赖的其他服务相应太慢
  5. 复杂的业务逻辑或者算法造成响应的缓慢

垃圾回收对性能的影响一般有以下几个:

  • 内存泄漏
  • 程序暂停
  • 程序吞吐量显著下降
  • 响应时间变慢

垃圾回收的一些概念

  • 回收的同时可运行其他的工作进程
  • 使用多CPU进行垃圾回收
  • 回收时必须暂停其他所有的工作
  • 使用引用计数算法的GC,出现对象的计数器溢出,则起不到标记某个是垃圾的作用
  • 变异
  • 引用计数垃圾回收
  • 标记-清理(对象分代)

GC流程和算法

GC的一般流程:

  1. 找出堆中活着的对象
  2. 释放死对象占用的资源
  3. 定期调整活对象的位置

找出活着的对象和释放死对象的情况可以使用以下算法:

  • 标记-清除
  • 标记-整理
  • 复制算法
  1. 标记 Mark
  2. 清除 Sweep
  3. 压缩 Compact
  4. 复制 Copy

垃圾回收器