JVM笔记

运行时数据区域

方法区、虚拟机栈、本地方法栈、堆、程序计数器。

  • 方法区:各个线程的共享区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等信息。

  • 程序计数器:线程私有的内存区域,是当前线程所执行的字节码的行号指示器。

  • 虚拟机栈: 线程私有的内存区域,生命周期和线程相同,描述了java方法执行的内存模型:每个方法被执行时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。局部变量表存放了编译期可知的各种基本数据类型、对象引用和returnAddress类型(指向一条字节码指令的地址)。

  • 本地方法栈: 为虚拟机执行java的native方法。

  • 堆: 线程共享的内存区域,也是虚拟机所管理的内存中最大的一块,唯一目的是存放对象实例,几乎所有的对象实例都会在这里分 配内存。java堆是垃圾收集管理的主要区域。从内存回收的角度来看,java堆可分为新生代和老年代,其比例为 1:2,可通过参数 –XX:NewRatio 来指定 。新生代又分为三个区域:Eden、From、To,默认比例是8:1:1,可以通过参数 –XX:SurvivorRatio 来设定

  • 运行时常量池: 是方法区的一部分,保存class文件中描述的符号引用和各种字面量,以及翻译出来的直接引用。

垃圾收集算法

  • 标记-清楚算法:首选标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象,有效率和空间两个缺点。

  • 复制算法:将内存按容量划分为大小相等的两块,每次只使用其中的一块,当一块使用完毕后,就将还存活着的对象复制到另外一块中,然后再把已使用的内存空间一次清理掉。现代虚拟机大都采用这种算法。

  • 标记-整理算法: 标记完成后,将所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。

  • 分代收集算法: 根据对象的存活周期的不同将内存划分为几块,,然后根据每个块的特点采用最适当的收集算法。

垃圾收集器

Serial收集器

使用复制算法的单线程收集器,进行垃圾收集时,必须暂停其他所有的工作线程,适用于client模式下的虚拟机。

jvm参数:

-XX:UseSerialGC

特点:

  • 单线程
  • 独占式
  • 使用复制算法
  • client的默认收集器
  • CMS的备用处理器

ParNew收集器

新生代收集器,serial收集器的多线程版本,可和cms收集器配合使用。

jvm参数:

-XX:ParallelGCThread ##指定线程数量,默认值:当cpu数量小于8时,是cpu的数量,大与8时:3+(5*cpu数量)/8

Parallel Scavenge收集器

使用复制算法的新生代收集器,适合在后台运行而不需要太多的交互任务,以吞吐量为主,jdk8默认的收集器。

吞吐量设置:

  • 设置最大垃圾收集停顿时间-XX:MaxGCPauseMillis,大于0的毫秒数,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的,GC停顿时间缩短则吞吐量小,反之则大。

  • 设置垃圾收集时间占总时间的比率 -XX:GCTimeRatio,0-100,默认值为99,就是允许最大1%(即1 /(1+99))的垃圾收集时间。

  • 自适应的调节策略开关-XX:+UseAdaptiveSizePolicy,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整(新生代大小,eden和Survivo比例,晋升老年代阀值)等参数以提供最合适的停顿时间或最大的吞吐量。

Serial Old收集器

Serial收集器的老年代版本,使用“标记-整理”算法的单线程收集器

Parallel Old收集器

ParNew收集器的老年代版本,使用多线程和“标记-整理”算法,和 Parallel Scavenge收集器一起使用。

CMS收集器

一种以获取最短回收停顿时间的收集器,使用“标记-清除”算法,关注点是尽可能的缩短垃圾收集时用户线程的停顿时间,适用于互联网站或B/S系统。优点是并发收集,低停顿。

特点:
  • 并发标记清楚
  • 内存碎片
  • 多线程回收
  • 实现复杂
执行过程:
  • 初始标记(SWT),仅标记GC Root能直接关联的对象,速度很快。
  • 并发标记,进行GC Root的跟踪过程。
  • 预清理,清理前准备及控制停顿时间。
  • 重新标记(SWT),修正并发标记数据。
  • 并发清理
  • 并发重置
主要参数
  • -XX:+UseConcMarkSweepGC 启用CMS回收期。

  • -XX:ParallelCMSThreads,设置并发线程数量。

  • -XX:ConcGCThreads,设置并发线程数量。

  • -XX:CMSInitiatingOccupancyFraction,回收阀值,默认68,即当老年代的空间使用率到达68%时,会执行一次CMS回收。

  • -XX:+UseCMSCompactAtFullCollection,默认开启,在FGC后进行碎片整理,停顿时间会变长。

  • -XX:CMSInitiatingOccupancyFraction,默认值为0,在上一次CMS并发GC执行过后,到底还要再执行多少次full GC才会做压缩

G1收集器

使用“分区”算法的收集器,将java堆分成了多个大小相等的Region,每个Region大小是2的倍数,范围在1m-32m之间,最多可以有2048个Region,在整个jvm的生命周期内不会改变。

特点
  • 并行性(多个GC线程同时工作)。
  • 并发性(和应用程序并发执行)。
  • 分代GC,同时兼顾老年代和年轻代,和之前的GC收集器完全不同。
  • 空间整理,CMS在若干次GC后必须进行一次碎片整理,而G1不同,它每次回收都会有效的复制对象,减少空间碎片。
  • 可预见性,由于分区的原因,G1可以只选取部分分区区域进行内存回收,缩小了范围,相应的减少了系统停顿。
执行过程
  • 新生代GC
  • 并发标记周期
  • 混合收集
  • 如果需要,可能进行FGC

类加载机制

类的生命周期:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用和卸载七个阶段。
在这里插入图片描述

即时编译器的“热点代码分类”:

  1. 被多次调用的方法。
  2. 被多次执行的循环体;

触发即时编译的热点探测判定方式:

  1. 基于采样的热点探测(Sample Based Hot Spot etection),虚拟机会周期性的检测各个线程的栈顶,如果发现某些方法经常出现在栈顶,那这个方法就是热点方法。优点是实现简单高效很容易获取方法的调用关系,缺点是很难精确的确认一个方法的热度,容易因为受到线程阻塞或别的外界因素的影响而扰乱热点探测。
  2. 基于计数器的热点探测(Counter Based Host Spot Detection) ,虚拟机为每个方法建立计数器,统计方法的执行次数,如果执行的次数超过一定的阙值就认为它是热点方法。优点是统计的结果更加精确严谨,缺点是需为每个方法建立并维护计数器,而且不能直接获取到方法的调用关系。设置阙值的参数:-XX:CompileThreshold;

即时编译优化技术

语言无关的经典优化技术之一:公共子表达式消除
语言相关的经典优化技术之一:数组范围检查消除
最重要的优化技术之一:方法内联
最前沿的优化技术之一:逃逸分析

java内存模型

java内存模型的主要目标是定义程序中各个变量(实例字段,静态字段和构成数组对象的元素,不包含局部变量和方法参数)的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量的底层细节。主内存存储了所有的变量,每条线程有自己的工作内存,工作内存保存了变量的主内存的副本拷贝,线程对变量的所有操作必须在工作内存中进行。

主内存和工作内存交互协议

  • lock(锁定):作用于主内存的变量,它把一个变量标示为一条线程的独占状态
  • unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放出来的变量才可以被其他线程锁定
  • read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load使用
  • load(载入):作用于工作内存的变量,它把read操作从主内存得到的变量值放入到工作内存的变量副本中国
  • use(使用):作用于工作内存的变量,它把一个工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值得字节码指令时将会执行这个操作
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接受到的值赋值给工作内存的变量,每当虚拟机遇到一个需要给变量赋值的字节码指令时将会执行这个操作
  • store(存储):作用于工作内存的变量,它把工作内存中的一个变量的值传送到主内存中,以便随后的write操作
  • write(写入):作用于主内存的变量,它把sotre操作从工作内存得到的变量的值放入主内存的变量之中

java内存模型特征:原子性(atomicty)、可见性(visibility)、有序性(ordering)

对于volatile型变量的特殊规则

当一个变量被定义成volatile 之后,将具备两种特性

  1. 保证此变量对所有线程的可见性,当一条线程修改了这个变量的值,新值对于其他线程是立刻得知的

  2. 禁止指令重排序

由于valatile变量只保证可见性,在不符合以下两条规则的运算场景中,仍然要通过加锁(使用synchronized或java.util.concurrent中的原子类)来保证原子性:a、运算结果不依赖于变量的当前值,或者能够确保只有单一线程修改变量的值。b、变量不需要于其他的状态
变量共同参与不变约束。

先行发生原则的规则
程序次序规则(program order rule)
管程锁定规则(monitor lock rule):一个unlock操作先行发生于对同一个锁的lock操作
volatile规则( volatile variable rule) :对一个volatile变量的写操作先行发生于后面对这个变量的读操作
线程启动规则(thread start rule):Thread对象的start 方法先行发生于此线程的每一个动作
线程中断规则(Thread termination Rule):线程中的所有操作都先行发生于对此对象的终止检测
对象终结规则(Finalizer Rule):一个对象的初始化完成先行发生于它的finalize 方法的开始
传递性(Transitivity):如果操作a先行发生于操作b,操纵b先行发生于操作c,那么操作a先行发生于操作c

线程

线程实现的三种方式

使用内核线程实现(一对一的线程模型),使用用户线程实现(一对多的线程模型),使用用户线程加轻量级进程混合实现 (多对多的线程模型)
sun jdk的window版和linux使用一对一的线程模型实现 ,一条java线程映射于一条轻量级的进程之中。

java线程调度的两种方式

协同式线程调度(cooperative threads-scheduling)、抢占式线程调度(preemptive threads-scheduling) 。

线程安全定义:

当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,单此调用都能获取正确的结果,那么这个对象就是线程安全的。

线程安全的实现方法

1、互斥同步(悲观并发策略):使用synchronized关键字、java.util.concurrent.ReenrrantLock(重入锁)
2 、非阻塞同步(乐观并发策略)
3、无同步方案: 可重入代码、线程本地存储(消费者模式、volatile变量)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值