zoukankan      html  css  js  c++  java
  • java 虚拟机系列-java内存分配、类加载,垃圾回收机制算法

    请参看:

    https://zhuanlan.zhihu.com/p/25511795?comefrom=http://blogread.cn/news/   总结的很好

    https://zhuanlan.zhihu.com/p/25575446

    一、前言

    最近看了《深入理解java虚拟机》中内存分配和类加载两个章节的内容,其实之前也看过这两节,但是觉得每次看都会有收获,这次看觉得对java虚拟机的运行时数据区了解的更深入了一些,对类加载的过程所做的事情和涉及到的数据区也更清楚了。

    jvm体系总体分四大块:

    • 类的加载机制
    • jvm内存结构
    • GC算法 垃圾回收
    • GC分析 命令调优

    二、总结

    1、java运行时数据区:jvm内存结构

    分为五大块:程序计数器;虚拟机栈;本地方法栈;java堆;方法区。

    (1)程序计数器:线程私有,是java字节码行号指示器;

    作用:用来选取下一条要执行的字节码的指令,像循环,跳转、分支、异常处理、线程恢复(多线程间的切换竞争处理器)等,都需要读取程序计数器中数据。

    (2)虚拟机栈:线程私有,也称局部变量表,为虚拟机执行java方法(字节码)服务;

    作用:虚拟机在虚拟机栈中为每个方法创建一个栈桢,存放局部变量表,操作数栈,动态链接,方法出口等信息,每个方法的调用都会对应一个栈帧出栈和入栈的过程。 

    (局部变量表:存放编译器可知的java基本类型、对象引用类型(可以指向一个对象也可指向一个句柄)、和returnAddress类型(指向一条java字节码指令)一个局部变 量空间是32位,long和double要占用2个)

    (3)本地方法栈:用来存放本地方法(native)的数据,为虚拟机执行本地方法服务。HotSpot将虚拟机栈和本地方法栈合二为一。

    (4)java 堆:线程共享,在虚拟机启动时创建,可通过设置 -Xmn  和 -Xms 设置最大,最小堆内存

    作用:存放所有对象和数组。若空间不足,会抛出 outofmemery 和stackoverflow异常。

    从内存回收的角度来看:现在GC收集器都采用分代手机算法,所以java堆还需分为年轻代和老年代。Eden空间,From Survivor空间,To Survivor空间;

    (5)方法区:线程共享,被称为”永久代“,但hotSpot的GC分代回收机制扩展至方法区;主要收集常量池和对类型卸载(效果不好)。

    作用:用于存放虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等。内存不足时会抛出outofmemery异常。

    (6)运行时常量池:是方法区的一部分,class文件中除了存放类的版本,字段,方法等信息外,还有一个常量池,存放编译期生成的字面量和符号引用。

    作用:存放编译期生成的字面量和符号引用。(在类加载的加载阶段,虚拟机将二进制字节流加载进运行时数据区的方法区)

    注意:直接内存,并不是java运行时数据区的一部分,但是也是频繁使用的,基于通道和缓冲区的IO方式。NIO; 内存不够会报 outofmemery异常。

      使用实例:下面通过 一个对象的创建过程 来看看虚拟机是怎样利用这些运行时数据区的:

    当虚拟机遇到一个new指令时,首先到常量池中检查该符号引用(若找不到说明这个类没有加载到内存),并检查这个符号引用代表的类是否已经被加载,解析和初始化(若没有,则先进行类加载),然后在java堆中分配该对象所需的内存空间(对象的大小在类加载阶段确定的),然后对对象进行初始化工作。

    对象内存分配方法:

    指针碰撞法:   适合规整的内存;中间有个指针,使用的内存放指针的一边,未使用过的放另一边。

    空闲列表法:适合不规整的内存,相互交错;维护一个列表,记录哪块内存可用。

    内存是否规整取决于垃圾回收算法



    2、类加载的过程(类的加载机制)

    类加载的过程分为 加载 ;验证;准备;解析;初始化;

    (1)加载阶段:虚拟机通过累的全限定名找到对应的二进制流文件;  --- 》  将二进制流文件加载到运行时数据区的方法区;----》在堆中生成一个java.lang.class对象,作为堆中对象访问方法区的入口。

    (2)连接阶段:包括验证、准备、解析(位置不固定)

    验证:验证文件格式(是否符合定义规范,版本信息是否正确等);元数据验证(对类的数据类型进行语义分析); 字节码校验(对类的方法进行语义分析,是否安全);

    准备:为类变量分配内存,并设置初始值。初始化常量池中的静态变量为默认值(常量在 javac 编译时,已经生成了constValue值了,所以在准备阶段是将constantValue值赋给常量;

    解析:将常量池内的符号引用转换成直接引用,直接关联内存;

    (3)初始化(对类中的类变量和静态语句块赋值)



    在网上关于java内存分配模型的讲解真的是数不胜数,其中的源头应该都是《深入理解java虚拟机》这本书吧。我吧这些总结起来,就是想做个记录,以后在面试前好好看看,能快速想起来。  

    参考:《深入理解java虚拟机》

    结合:http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html   




  • 相关阅读:
    指针
    const
    指针数组和指向数组的指针
    extjs初探之由浅入深目录
    ie6字体设置13px引发的问题
    在IAR下通过Jlink将程序直接下载到Flash指定地址
    提高C语言程序运行稳定性的方法
    C/C++编程习惯
    释放QQ占用的C盘空间
    非阻塞算法思想在关系数据库应用程序开发中的使用
  • 原文地址:https://www.cnblogs.com/yeemi/p/7470125.html
Copyright © 2011-2022 走看看