JVM基本结构

JVM总体结构:

这里写图片描述

类加载子系统:
类加载子系统负责从文件系统或者网络中加载Class 信息,加载的类信息存放于一块称为方法区的内存空间。
程序计数器:
每个线程拥有自己的计数器,它指向当前执行指令的字节码地址,它是JVM唯一一个不会出现内存溢出的区域
虚拟机栈:
生命周期与线程相同,也是线程私有的,每个方法在执行时都会创建一个栈帧用于存放局部变量等方法信息。每一个方法的执行过程就是一个栈帧在虚拟机栈中入栈到出栈的过程;
如果线程请求的栈深度大于虚拟机所允许的深度会出现StackOverflowError异常
当前大部分栈都可动态扩展,所以有可能出现OutOfMemoryError异常
本地方发栈:
它和虚拟机栈作用相似,只不过它为Native方法服务
堆:
堆分为新生代和老年代。其中,新生代布放新生对象或者年龄不大的对象,老年代则存放老年对象。新生代有可能分为eden 区、s0 区、s1 区, s0 和l s1 也被称为from 和to 区域,它们是两块大小相等、同一时刻只会有一个区域被使用,主要用于年轻代复制回收算法。对象首先分配在eden 区(体积超过-XX:PretenureSizeThreshold的大对象直接分配在老年代),在一次新生代回收后,如果对象还存活,则会进入s区域中的一个。之后,每经过一次新生代回收,对象如果存活,它的年龄就会加1 。当对象的年龄达到一定条件后(默认15),就会被认为是老年对象,从而进入老年代。
注意:PretenureSizeThreshold参数(无默认值)只对Serial和ParNew两款收集器有效,Parallel Scavenge收集器不认识这个参数,Parallel Scavenge收集器一般并不需要设置,如果遇到必须使用此参数的场合,可以考虑ParNew加CMS的收集器组合。

方法区:
线程共享,用于存储类信息(Class对象),常量,静态变量…有可能出现OutOfMemoryError异常。
运行时常量池(方法区得一部分):一般编译时会将Class中的常量存入该区域中,在运行时也可以通过String的intern()方法将新的常量放入该区域中
直接内存:
Java 的NIO 库允许Java 程序使用直接内存。直接内存是在Java 堆外的、直接向系统申请的内存区间。通常,访问直接内存的速度会优于Java 堆,它的大小不会直接受限于Xmx 指定的最大堆大小,但是系统内存是有限的, Java 堆和直接内存的总和依然受限于操作系统能给出的最大内存。
这里写图片描述

堆,栈和变量内存分配的关系:

  • 栈的优势是:存取速度比堆要快,仅次于直接位于cpu中的寄存器;栈数据可以共享。 但缺点是:存在栈中数据大小与生命周期必须是确定的,缺乏灵活性。
  • 堆的优势在于可以动态分配内存大小,生存期也不必事先告诉编译器,java的垃圾收集器会自动收走这些不再使用的数据,缺点是由于要在运行时动态分配内存,存取速度较慢。
  • 基本数据类型的存储,这种类型如int=3的形式来定义,称为自动变量。自动变量存在的是字面值,即不是类的实例,也不是类的引用。a 是一个指向int类型的引用,指向3这个字面值。这些字面值的数据由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退了,字段值就消失了),处于追求速度的原因就存在栈中。
  • 另外栈有一个很重要的特殊性,就是存在栈中的数据可以共享。如 需要定义int a = 3; int b =3;这两个自动变量。编译器先处理int a=3;首先在栈中创建一个变量为a的引用,然后查找栈有没有字面值为3的引用,没有找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b=3;在创建完b这个引用变量后,由于在栈中已经有了3这个字面值,即将b直接指向3的地址。
  • 对象的内存模型.创建一个对象包括对象的声明和实例化两步:声明一个对象引用时,将在栈内存为对象的引用变量分配空间;对象实例化是,在堆内存中为类成员变量分配内存,并将其初始化为各数据类型默认值,接着进行显示初始化,最后调用构造方法为成员变量赋值,返回堆内存中对象的引用(相当于首地址)给应用变量,通过引用变量来引用堆内存中的对象。
  • 包装类数据的存储:基本数据类型的定义都是直接在栈中,如果是包装类型来创建对象,就和普通对象一样。
  • string数据类型是一种特殊数据类型,既可以用基本数据类型格式来创建,也可以用普通基本类型来创建。

    参数配置:

  • 在实际工作中,也可以直接将初始堆-Xms 与最大堆-Xmx 设置相等. 这样的好处是可以减少程序运行时进行的垃圾回收次数,从而提高程序的性能

  • 参数,-Xmn 可以用于设置新生代的大小。设置一个较大的新生代会减小老年代的大小,这个参数对系统性能以及GC 行为有很大的影响。新生代的大小一般设置为整个堆空间的1/3 到1/4左右
  • 参数-XX:SurvivorRatio 用来设置新生代中eden 空间和台from/to 空间的比例关系,默认8:1
  • 参数-XX:New Ratio 来设置新生代和老年代的比例
  • 在JDK 1 .8 中,永久区被彻底移除,使用了新的元数据区存放类的元数据。默认情况下,元数据区只受系统可用内存的限制,但依然可以使用参数,-XX:MaxMetaspaceSize 指定永久区的最大可用值
  • 最大可用直接内存可以使用参数-XX:MaxDirectMemorySize设置,如不设置,默认值为最大堆空间,即-Xmx 直接内存分配效率比堆低,读取效率比堆高,适合申请次数较少、访问较频繁的场合。如果内非空间本身需要频繁申请,则并不适合使用直接内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值