运行时内存

1 程序计数器 线程私有,记录线程所执行的字节码行号指示器。

2 虚拟机栈  描述Java方法执行内存模型 , 进入一个方法创建栈帧。

3 Java堆   存放对象实例

4 方法区:编译后的代码数据,包括加载 的类信息,常量,静态变量。

5 常量池 :class文件常量池方法区一部分存放编译器生成的字面量和符号引用,加载时放入虚拟机的运行时常量池中

6 对像创建 : 1 类是否已经加载   2 为对象分配内存 类加载后,对象所需内存确定 , 内存空间初始化0,3 设置对象头部信息 (对象所属类,哈希等) 4 根据程序员意愿,执行init方法,为对象设置初值。

7 对象布局: 对象头(1 对象运行时数据  2 类型指针 数组还有数组长度), 实例数据信息  , 对其填充

8 对象访问定位  1 句柄 (对象数据指针   对象类型指针) 好处,reference存稳定句柄值,对象变化只改变句柄中对象数据指针,  2 直接  对象地址,好处  访问块。

9分析是内存溢出还是内存泄漏,如果内存泄漏,找出泄漏对象到GC roots的引用链,看为什么对象没有回收, 如果是内存溢出,看虚拟机堆是不是太小。看某些对象生命周期是否过长,尝试减少运行期间内存消耗。

10 哪些内存需要回收。Java堆,方法区

11 什么时候需要回收 对象死

1 引用计数算法:每一个地方引用对象,计数器加1 , 很难解决对象之间相互循环引用问题。

2 可达性分析  “GC Root” 对象为起点,从起点向下搜,所走过路径为引用链,当对象到“GC Root” 没有引用链时,对象不可达。

12 生存还是死亡    不可达对象, 检测对象是否有必要执行finalize方法,如果没有覆盖finalize方法或方法已经被虚拟机调用过,会直接回收,如果有必要执行方法,在这个方法中对象有可能存活。

public class JDBCTest{
    public static JDBCTest j = null;

    public void isAlive() {
        System.out.println(" i am alive");
    }

    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("finalize exet");
        j = this;
    }
    public static void main(String[] args) throws Exception {
        j = new JDBCTest();
        j = null;
        System.gc();
        Thread.sleep(500);
        if (j != null) {
            j.isAlive();
        } else {
            System.out.println("j dead");
        }

        j = new JDBCTest();
        j = null;
        System.gc();
        Thread.sleep(500);
        if (j != null) {
            j.isAlive();
        } else {
            System.out.println("j dead");
        }

    }
}

13 回收方法区   1 废弃常量,无用类    1 类实例被回收  2 类classloader被回收 3 Class对象没有被引用

14 垃圾回收算法

1 标记 -清除   缺点 标记,清除效率不高  产生大量不连续碎片

2复制 分为大的eden和小的survivor  只用Eden ,垃圾回收时将存活对象放入survivor ,并清除Eden

3 标记 -- 整理  对垃圾回收后大部分对象都会存活使用   和标记-清除不同的是,让存活对象像一边移动,清除边界外内存。

4 分代收集   根据对象存活周期不同,新生代 ,每次垃圾收集都有大量对象死,使用复制算法   老年代 对象存活率高,标记清理或标记整理

15 hotSpot算法实现

1 枚举根节点(全局性引用,常量或静态属性   与执行上下文 栈帧本地变量表)stop the world  枚举跟节点时,必须停止所有线程,否则枚举不准确 ,编译类后使用oopMap数据结构记录哪个地方有引用,加快枚举跟节点速度

2 安全点  在安全点停下来GC, 是否有让程序长时间执行的特征  方法调用 ,循环跳转  异常跳转

如和在GC发生时让线程在安全点停下,1 抢占式  中断所有线程,如果发现有线程没有到安全点,线程跑到安全点  2 主动中断 在安全点轮询,如果需要GC,把自己中断。

3 如果线程处于sleep或阻塞,线程无法相应jvm中断请求,走不到安全点,需要安全区域:在这段代码片段中,引用关系不发生变化,任意地方开始GC安全。在线程要离开安全取时,检测是否完成枚举跟节点。

serial  新生代  垃圾收集时必须停止所有线程工作。并且只有一条线程垃圾回收  client模式默认

ParNew  serial 多线程版本 , 可以有多条线程垃圾回收  server模式默认

parallel scavenge 和ParNew 很相似 , 多条线程垃圾回收 , 和上一个关注停顿时间不同,主要关注吞吐量(用户代码运行时间/总运行时间),适合和用户交互少的后台代码执行。可以直接设置吞吐量和最大停顿时间。

老年代

serial old    serial老年代版本,单线程收集, 标记整理, client模式

Paraller old 是parallel scavenge老年代版本 多线程收集 在注重吞吐量和CPU资源敏感场合,优先Paraller old ,parallel scavenge组合

cms (concurrent mark sweep) 以获取最短回收停顿为目标,标记清除算法,

4个步骤 初始,重新 stop the world , 初始标记只标记GC Root直接关联对象,速度很快   并发标记 经行GC Roots Tracing过程,重写标记修正并发标记期间的修改,

缺点1  cms对CPU资源敏感  2 无法处理浮动垃圾 可能出现concurrent  mode failure 失败导致另一次full gc,由于cms并发清理阶段用户线程还在运行着,伴随程序运行还有垃圾产生,垃圾出现标记过程后,cms无法在当次处理他们,只好下次gc,这部分垃圾为浮动垃圾 3  空间碎片

G1

并行 :多条垃圾回收线程一起执行

并发 :垃圾回收,用户程序一起执行

内存分配与回收策略

时间: 2024-10-06 03:22:49

运行时内存的相关文章

Java 进阶(一) JVM运行时内存模型

1.JVM运行时数据区域的划分 a.程序计数器(Program Counter Register) 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.每个线程拥有独立的一个计数器,如果当前执行的是Native方法,则计数器值为空. b.JVM栈(Java Virtual Machine Stack) 描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stacks Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息. 每一个方法从调用直至执行完成

深入理解java虚拟机一 JAVA运行时内存区域与class文件

一 JAVA运行时内存区域 JVM在加载class文件时,会将class文件定义的数据结构转为运行时内存中的数据,那么jvm是如何安排运行时的内存区域呢? jvm将运行时内存划分为以下几个部分: 堆:所有线程共享 方法区:类信息.静态变量.常量等 运行时常量池:class文件的常量池(字面常量和符号引用)+运行时产生的常量 程序计数器:  当前线程执行的字节码的行号指示器 虚拟机栈:栈帧 = 本地局部变量表.操作数栈.动态链接.出口信息 本地方法栈:native方法 直接内存:不属于jvm管理,

jvm运行时内存解析

一.jvm的概念 在了解jvm的概念之前,我们先来了解java平台的逻辑结构,图片来自<深入java虚拟机> 从图中我们可以看到jdk包含了jre,java语言和java开发工具和Api,jre包含了java运行的基础类库和java虚拟机,java虚拟机支撑着java程序的运行. jvm(java virtual machine)翻译为java虚拟机,从字面上来理解,jvm就是一个虚拟的机器,其实类似于一个操作系统,通过软件去虚拟出一个虚拟机,帮助我们管理计算机的内存和调用计算机的硬件等等.而

运行时内存模型

运行时内存模型运行时中,类型.对象.线程和托管对有相互的关系.CLR的一个windows进程,这个进程中可能存在多个现在.一个线程创建时,会分配1M的栈.这个栈主要用于方法传递实参和方法内部定义的局部变量.如果方法中有涉及到对象,则在堆中创建类型对象和类型实例.类型对象主要由类型对象指针.同步块索引.静态字段.方法列表组成.类型实例主要由类型对象指针.同步块索引.实例字段组成.其中类型实例的类型对象指针指向类型对象的类型对象指针.它们的相互关系如下图所示. 通过这张图,可以清楚了解运行时的内存由

对象与运行时内存

和大多数猴子一样,我原来也抵触对原理的学习, 后来发现掌握了原理才有了那种了然于胸,运筹帷幄的感觉,也就是顿悟. 这里主要介绍Java对象与运行时内存的知识. java运行时内存 Program Counter Registe(程序计数器): 记录当前线程执行字节码的位置,相当于行号指示器,为线程私有的. Java Virtual Machine Stacks(java虚拟机栈): 存放方法出口信息.局部变量表(对象引用.基本类型数据等),为线程私有的. Native Method Stack(

内存的划分 &amp; 程序代码运行时内存工作流程

内存的划分: 1,寄存器. 2,本地方法区. 3,方法区. 4,栈内存. 存储的都是局部变量. 而且变量所属的作用域一旦结束,该变量就自动释放. 5,堆内存. 存储是数组和对象(其实数组就是对象) ,凡是new建立的都在堆中. 特点: 1)每一个实体都有首地址值. 2)堆内存中的每一个变量都有默认初始化值,根据类型的不同而不同.整数是0,小数0.0或者0.0f,boolean类型是false,char类型是 '\u0000',引用数据类型是NULL 3)垃圾回收机制. 全局变量和局部变量的区别:

java运行时内存模式学习

学习java运行时内存模式: 各区介绍: 方法区(线程共享):用于存放被虚拟机加载的类的元数据:静态变量,常量,以及编译和的代码(字节码),也称为永久代(所有该类的实例被回收,或者此类classLoader被回收). Java堆(线程共享):存放对象实例和数组,这里是内存回收的主要地方.可以分为新生代(young)和年老代(tenured).从字面也可以知道,新生代存放刚刚建立的对象 而年老代存放长久没有被垃圾回收机制回收的对象.一般新生代有分为eden,from survivor和to sur

[转]JVM运行时内存结构

目录[-] 1.为什么会有年轻代 2.年轻代中的GC 3.一个对象的这一辈子 4.有关年轻代的JVM参数 1.为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能.你先想想,如果没有分代,那我们所有的对象都在一块,GC的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描.而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当GC的时候先把这块存“朝生夕死”对象的区域进行回收,这样就会

获取java程序运行时内存信息

由于最近想自己动手测试一下String和StringBuffer的效率问题,需要获取程序运行时的内存占中信息,于是上网查了一下,根据查到的资料写了个程序,发现结果有问题,才发现查到的资料是错误的.所以在这里跟大家分享一下获取内存占用的正确方法 错误的方法 //程序开始时:(先调用一下垃圾回收,但是不一定立即执行) Runtime.getRuntime().gc(); long initm=Runtime.getRuntime().freeMemory(); //程序结束时: Runtime.ge

程序运行时内存管理

1,管理运行阶段内存空间分配 malloc()/new; int *pn = new int(存储的类型,内存根据此设定相应存储字节的内存) pn是内存地址(所以 当声明一个变量的指针变量时没初始化,声明后再来初始化则pn 接收的应该是变量在内存中的地址 &VariableName); *pn是存储在内存的值 用于给所指向内存中的变量赋值; 为一个数据对象(结构,基本类型)获得并指定分配内存格式 typeName pointer_name = new typeName; 指定需要什么样的内存和用