jvm原理

[TOC]

java虚拟机

以太坊,区块链1.0版本 比特币是1.0 以太坊2.0 -EVM

jvm就是对字节码的翻译

虚拟机的发展 go语言写jvm非常的简单

hotSpot VM
目前最广的java虚拟机

JRockit VM
号称最快的java虚拟机

J9 VM ibm公司的

Dalvik VM

未来java技术

模块化, GFGI 模块化,微服务

混合语言(java,Scala)

多核并行(函数式编程)

丰富语法

64位

更强的垃圾回收 回收gb级的 jdk11可以是tb级别

所有的东西都是放内存的 内存的划分,

程序计数器:指向当前线程的字节码,线程间切换来切换去
FILO first in last out

非常符合java间的方法调用

虚拟机栈 -Xss 里面有栈帧
javap

局部变量表,只能放32位的数据,局部变量表, this,money

​ 持有引用,

操作数栈
出栈进行相减
count++, dup - idd 总共4不
操作的入栈,

返回地址return,正常执行

异常会在一个叫 异常处理器表 处理

多态的的话,就要使用动态连接, java动态运行性,

局部变量表一个引用

​ native栈 hotspot吧本地方法栈和虚拟机栈合二为一的

​ 加了入参,可能有点影响

为什么jvm要用栈,因为:非常符合java间的方法调用

指令 + 数据,

虚拟机栈帧,默认是1m, 可以进行修改

方法区: 类信息,常量,静态变量,即时编译器编译后的代码

java堆: 对象的实例(几乎所有) 数组

​ -xmx 最大
​ -xms 最小

直接内存: nio会使用

​ 不超过,内存调用
​ 每个线程归属于单个线程,栈

堆内存是对所有线程可见的

空间大小:并发可以跑一个100个线程,就100m

java虚拟机中的对象

分配内存

指针碰撞 和 空闲列表
规整用指针碰撞,不规整用空闲列表

如果相同地址时:要使用cas锁

cas锁:比较和交换 乐观锁

cas操作带来的ABA

ABA 问题 中间状态,被用了,不管, 只要管再次分配的时候 b这个状态不管

char的初始值 \u0000 ???

对象初始化、

设置是那些类的, 然后对象初始化

对象内存的布局

对齐填充
对象头:线程 垃圾回收也有点关系

。。。

对象的访问定位

​ 句柄方式访问对象
​ 直接指针访问对象

虚拟机优化技术 — 逃逸分析

有对象可以在栈上分配的,几乎所有对象在栈上分配

hotSpot 默认有逃逸分析

本地线程缓冲区
如果有逃逸分析,对象可能会在栈上分配,这是虚拟机的优化的技术
本身这个对象,没有在其他地方使用,所以就直接在栈上分配了

逃逸分析使用了可见性???,其他的线程也是可见的

热点跟踪,使用频繁就会保存起来

静态方法是也在栈帧里面吗?????

逃逸分析为什么快????

异常处理表??? 出现异常了,异常处理表

oom 和栈溢出区别
混合模式,

直接内存,元空间(直接内存) 直接内存会挤压堆, 2面性

一个进程只能开启一个虚拟机吗

静态属性和静态方法 ,

当不持有引用的时候可以使用静态方法

逃逸分析和栈上分配

静态属性和静态方法

内存溢出OOM和内存泄露memory leak 小结

需求管理做不好,等着9-12-7吧

CAS中的ABA问题解决方案

深入分析对象的内存布局
JVM–详解虚拟机字节码执行引擎之静态链接、动态链接与分派

2019-04-16 jvm

内存分配与回收策略

深入理解垃圾回收器
1.jvm垃圾回收及案例分析

  • 学习垃圾回收的意义,
  • java与C++之间的区别:

GC

  • 谁需要垃圾回收

栈=不需要,凡是共享的对象

堆-重点, 方法区,元空间(也有)

  • GC要做的事
  • 为什么我们要去了解GC和内存分配?

堆里面继续划分

eden

from Survivor

To Survivor

ODEGEn , 堆 -xmn

回收效率低,就抛出了oom GC overhead limit exceeded

交换区 是 1:1的比列
两个交换区始终占两份,所以,当eden为2时, 就是 2:1:1

-XX:SurvivorRatio =8

引用计数:JVM早期使用

A == > B (1)

C ==> B (1+1)=2

取消引用 -1 引用+1

缺点,
相互引用
A ==》 B 同时 b ==》 a 很难判断是不是该回收 (PHP在使用)

可达性算法(java)
GC Roots 是因为多加了个 s

1.方法区:类静态属性的对象

2.方法区:常量

3.虚拟机栈(本地变量表)中的对象 (方法没完)

本地栈jni对象

只要方法没跳出来,就是gc roots

new 出来的都是强引用

软引用:softreference 当系统要oom了,就会去回收
–图片使用内存,然后要oom要释放了

System.gc主动回收 //gc会消耗性能

-XX:+printGCDetails

弱引用

弱引用只要垃圾回收,就会被回收

weakHashMap
ThreadLocal 线程隔离

虚引用:PhantomReference 用得非常少 jvm层开发容易用到,回收了会告诉你我要回收了,回收会通知你一下

新生代:

复制回收算法,每次只能用一半

  • 利用率只有一半,

  • 实现简单,运行高效

  • 内存复制,没有内存碎片

90%的对象不需要进行主动回收,10% 8:1:1
很多对象不用去主动回收,使用完了,就释放了

8:1:1?????理解

是取eden里面的对象,是通过对象在serviver区间的移动

90%对象会被回收,10%不回收,所以复制只有10%

空间担保:放不下了怎么办

标记-清除算法,会产生内存碎片

标记-整理算法,内存移动,一定会涉及到效率问题 效率一般般

minor GC FUllGc
1m只是数据,所有大约占据1.5m空间,对象头和填充

新生代会带一些头的信息所以大一些
新生代为什么会大一点????

老年区实际大小差不多???

GC的时候才会去交互区吗

eden存新创建的对象
eden经过回收,就去交换区

eden快满了,就触发GC,然后就交换区间复制

堆内存的分配策略:

  1. 对象优先在Eden分配 一开始这个区分配
  2. 大对象直接进入老年代 (eden区放不下,就相当于大对象)
  3. 长期存活的对象进入老年代
  4. 动态年龄判断判断
  5. 空间担保

gc触发条件,就是空间不够了

分带收集:

Serial 单线程

cms 老年代,标记清除算法, (效率很好,空间碎片严重,主流移动互联网用的多)

GC的时候,出来GC线程,会把所有的线程暂停

CMS垃圾回收器工作示意图

cms给予并行收集与并发收集的
并发标记,和用户线程一起进行的

COncMarkSweep

怎么设置自己的项目使用哪个收集器。

初始标记 — 暂停

并发标记 — 同时进行

重新标记 — 暂停

并发清除 — 同时进行

有浮动垃圾

jps -v 看垃圾回收命令

G1垃圾回收器是 1.7提出来的, 可预测性停顿
标记整理 + 化整为零

垃圾回收,都有个内存停顿

吞吐量 = cpu时间 100% gC 10% 业务线程90% 业务线程/总的时间

内存不够了,垃圾回收不成功了,所以就oom了

需要的分配空间不够了,

gc回收不了了,还有对象要进来

内存泄漏,
MAT GC ROOT 引用的线程是否在频繁调用, monitor

Leakcanary, 代码可以追踪内存

空间不够了,就触发GC