java虚拟机学习笔记一:虚拟机的自动内存管理机制

来源:互联网 发布:淘宝优站网址 编辑:程序博客网 时间:2024/05/16 07:05

这里记录下我对java虚拟机学习时的理解,可能有很多不足或者我的理解过于浅薄,但是java虚拟机肯定是需要不断的去重复理解并实践才可以掌握的.

   第一部分:虚拟机提供的运行时的数据区域划分

   一个java虚拟机进程其实也就是我们的Java程序进程(java的程序必然要在jvm上面运行)我们编写的java程序运行在内存中时准确的说是运行在java虚拟机的内存中时这个java程序的内存划分分为5个数据区域:方法区内存区域,虚拟机栈内存区域,本地方法栈内存区域,堆内存区域,程序计数器内存区域.

    (1)程序计数器内存区域:这个数据区域是属于线程相互隔离的主要用来存放当前进程中的所有线程的执行指示器的,意思就是因为java虚拟机的多线程是通过线程轮换执行来实现的也就是所谓的并发,为了多个线程在发生切换之后能够正确的回到每个线程之前执行的方法上,程序计数器会记录每个线程的指示器来保存每个线程执行的位置.所以这个区域是线程相互隔离的.而且占用内存较少,所以java虚拟机规范声明这个区域是不会发生内存溢出问题的.

    (2)虚拟机栈内存区域:也就是我们常说的栈内存区域,这个区域也是线程相互隔离的,这个内存区域的生命周期和线程相同.这个数据区域主要是用来存放java方法的模型的.举个例子比如现在有2个线程在执行相同的java方法,java虚拟机会在这个内存区域分配2个线程独有的内存区域,每一个线程的内存区域都是一个栈,而当前线程执行的方法称为栈帧,从方法执行的开始到结束就是一个栈帧进栈和出栈的行为,所以先执行的方法总是后出,后执行的方法总是先出,这是栈数据结构的特征.而栈帧代表的就是一个正在执行的方法,当前方法中的局部变量,方法的返回值都会存放到当前的栈帧中.当前方法执行结束后随着栈帧的出栈,栈帧占用的内存就被回收,随着线程执行的结束当前线程占用的内存也会被回收.对于这个区域java虚拟机规范指出这个区域会抛出StackOverflowError和outofmemoryerror异常错误..

     (3)本地方法栈内存区域:与虚拟机栈内存区域一样,只是这个区域用来存放的是执行本地方法时的内存.jdk默认的hotspot虚拟机将虚拟机栈和本地方法栈内存区域合到了一起..

     (4)堆内存区域:首先堆内存区域(heap)是java虚拟机5个数据区域中内存最大的一块.并且堆内存对于线程是共享区域,也就是说所有线程在没有做同步处理的时候都可以一起使用堆内存中的数据.java虚拟机将堆内存区域设置这么大的一个原因就是因为几乎所有的java程序中的对象创建之后都会放到这个区域中,而这个区域也是java虚拟机垃圾收集器的主要回收对象,因此这个区域也被称为GC堆.这个区域是最有可能发生OutOfMemoryerror异常错误的..

     (5)方法区/静态内存区域:这个区域和堆内存区域一样对于线程也是共享区域,这个区域用来存放Class信息,Class变量,Class对象.并且这个区域中有一个叫做运行时常量池的区域.这个运行时常量池存放的是当前Class文件中在编程过后的字面量和我们编写Java源文件时的字面量也就是int char float这些基本数据类型的字面量以及类的全限定名称,方法的名称和标识等.这个区域也被称为非堆.java虚拟机规范声明这个区域会出现outofmemoryerror异常错误的..

    第二部分:JDK默认虚拟机HOTSPOT对象创建,内存布局及访问定位的理解

    (1)对象的创建:HotSpot虚拟机是jdK或者说是SUN(现在是oracle)默认的java虚拟机实现.java语音是一门面向对象的程序设计语音,所以java语音在编写代码的过程中会出现大量的对象这些对象都会存放到堆内存中.那对象是如何创建的呢?java虚拟机在遇到new指令的时候首先会去检查这个new指令后面的参数也就是类名是否在常量池中出现,并且查看这个类名所代表的类对象是否已经加载到静态内存区域并且解析和初始化过,如何没有会先进行相应的类加载过程,在创建当前类的对象并放到堆内存中.在存放当前对象的时候java虚拟机需要为当前的对象分配好内存在进行存放,分配有二种方式一种是指针相撞,如果内存是连续的通过计算出当前对象占用的内存大小将指针向后面移动相同的大小来分配这种分配方式要求内存必须是连续存放的.第二种是空闲列表在分配的时候找到一块与当前对象相同大小的空闲区域分配,分配完成后在列表上进行记录.在进行堆内存分配时选择哪种策略,主要是通过当前内存的现有使用情况来决定的,而且内存的现有使用情况又是由垃圾收集器来决定的,所以选择何种垃圾收集器,决定了选择何种堆内存分配的策略.

    (2)对象在堆内存的组成布局:对象在堆内存中分配好内存空间后,对象有会被分成3个组成部分,对象头,实例数据,对齐填充.对象头存放的是当前对象的哈希码,GC分代年龄,线程持有锁等.对象头保存的另一个重要部分就是对象的类型指针指向当前对象的类对象.而如果是数组对象的话还会存放数组的长度.实例部分存放的是对象真正存储的实例成员变量,包括父类继承和子类定义的..

    (3)对象的访问定位:其实对象在堆内存中,那如何被在栈内存区域中的方法使用呢?java虚拟机和java通过引用的方式来获取或者说访问java对象所以对象也被成为引用数据类型.通过一个引用性的变量这个变量保存的是一个位于堆内存中的对象地址.通过这种方式对象可以同时被多个引用性变量所引用来使用.而这种方式也被称为指针引用

  

0 0
原创粉丝点击