深入理解Java内存模型
来源:互联网 发布:站群软件 编辑:程序博客网 时间:2024/05/16 12:05
Java虚拟机的运行时内存按照类型可分为5部分:Java方法区、Java栈、Native方法区、Java堆和程序计数器。 其中栈和程序计数器不能跨线程访问。
程序计数器:是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,而且永远不会发生Out of Memory问题,其它四种内存区域都可能出现OOM现象。
Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同, 跟C语言类似不使用new关键字的变量存放在栈里。在栈里可能出现StackOverflowException或者OOM异常。
本地方法栈: 就是Native层用C语言编写的栈(没调用new),其它跟Java栈类似。
Java堆:所有的java队形实例、数组都在堆上new出来,是垃圾收集器(Garbage Collection)管理的主要区域。Java堆可以处在物理不连续的内存空间中, 但逻辑上要是连续的。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。在日常编程中遇到的OOM异常大都发生在Java堆。
方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
上面是JVM的内存模型, 那么一个Java对象在内存里分为几部分呢?
答案:对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。
那么JVM是如何回收内存的呢?
一、引用计数法: 当指向的Java对象的引用计数为0时, 在下次GC回收时会被释放。
考虑问题: 如果出现相互引用, 即A指向B,B指向A, 那么GC能回收吗?
public static class ReferenceCountingGC{ public Object instance=null; private final int ONE_MB=1024*1024; private byte[]bigSize=new byte[1*ONE_MB]; //只为了占空间 public static void testGC(){ ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; //假设在这行发生GC,objA和objB是否能被回收? long begin = Runtime.getRuntime().totalMemory(); System.out.println("befor:" + begin); System.gc(); long after = Runtime.getRuntime().totalMemory(); System.out.println("after:" + after); System.out.println("diff:" + (after-begin)); //判断到底释放了多少 }}执行结果:
befor:16252928
after:16318464
diff:65536
GC前后差了64K字节, 而objA和objB都大于1M字节, 现实没有被释放! 所以编程中切忌不要相互引用!!!
二、可达性分析算法
基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如图所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。
在Java语言中,可作为GC Roots的对象包括下面几种:虚拟机栈(栈帧中的本地变量表)中引用的对象;方法区中类静态属性引用的对象;方法区中常量引用的对象;本地方法栈中JNI(即一般说的Native方法)引用的对象。
关于内存基础知识就说这么多, 下一篇准备写如何计算Java对象的大小。
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 【深入理解Java内存模型】
- 深入理解Java内存模型
- 深入理解java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 深入理解java内存模型
- 深入理解Java内存模型
- 深入理解Java内存模型
- 接上篇(解决float导致塌陷问题)之clear:both失效
- PTA 02-线性结构1 两个有序链表序列的合并 (15分)
- 二叉树(递归遍历和非递归遍历)(递归求树的高度以及叶子节点数和拷贝树)
- 关于windows driver kit 10使用的一些问题
- 虚函数,构造函数,析构函数调用
- 深入理解Java内存模型
- Broadcast 源码解析
- Retrofit系列二
- nginx+tomcat做负载时,当一台服务器宕机如何解决?
- 正数求和
- Java学习笔记--解析JDK与IDE(Linux下Java环境变量的配置)
- ADB命令简单使用技巧(Android)
- C语言学习第二章
- javascript 小知识整理