垃圾回收算法 2019-08-09 为什么要垃圾回收 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。 对象存活算法之引用计数法 堆中每个对象实例都有一个引用计数。当一个对象被创建时,且将该对象实例分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象实例的计数器+1),但当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数器减1。任何引用计数器为0的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减1。(局部变量表的生命周期跟随方法的运行和结束) 优点 引用计数收集器可以很快的执行,交织在程序运行中。对程序需要不被长时间打断的实时环境比较有利。 缺点 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0. 在代码中分析JVM是否采用引用计....
对象 2019-08-09 对象创建流程 虚拟机遇到一条new指令时,首先检查这个对应的类能否在常量池中定位到一个类的符号引用 判断这个类是否已被加载、解析和初始化(类会被加载到方法区中) 为这个新生对象在Java堆中分配内存空间,其中Java堆分配内存空间的方式主要有以下两种:指针碰撞、空闲列表。 将分配到的内存空间都初始化为零值(引用null,int 0,boolean false) 设置对象头相关数据(GC分代年龄、对象的哈希码 hashCode、元数据信息) 执行对象方法(init方法) 指针碰撞(缺点:内存碎片) 分配内存空间包括开辟一块内存和移动指针两个步骤 非原子步骤可能出现并发问题,Java虚拟机采用CAS配上失败重试的方式保证更新操作的原子性 空闲列表(缺点:无法精确的分配内存空间,导致浪费内存空间) 分配内存空间包括开辟一块内存和修改空闲列表两个步骤 非原子步骤可能出现并发问题,Java虚拟机采用CAS配上失败重试的方式保证更新操作的原子性 Java对象内存布局 对象头 用于存储对象的元数据信息:包括对象运行时数据和类型指针 Mark Word 部分数据的长度在32位和64位....
JVM运行时数据区 2019-08-08 JVM运行时数据区分布图讲解 线程共享数据区:方法区、堆 线程隔离数据区:虚拟机栈、本地方法栈、程序计数器 程序计算器 程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。 内存区域中唯一一 个没有规定任何 OutOfMemoryError 情况的区域。 JAVA虚拟机栈 用于作用于方法执行的一块Java内存区域。 每个方法在执行的同时都会创建一个栈帧(Stack Framel):用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 特点 栈的执行顺序是后进先出。 局部变量表存放了编译期可知的各种基本数据类型(boolean、byte、char、s....