【JVM Ⅰ】内存与垃圾回收学习笔记

推荐一本书:《深入理解JVM》

再来一本:《自己动手写Java虚拟机》

这篇文章写得是挺乱的,但还是按照理解来写了一些比较重要的东西,有很多还不能够完全理解,等到时候去二刷吧,立一个Flag【2021年6月6日】

前言:

JVM不关心各种语言(不管是Java还是其他语言,都可以在JVM上面运行),JVM只关心字节码文件,需要符合JVM字节码规范。

11年出来了G1:包含了自动的内存管理 and 自动的垃圾回收功能

JVM架构:

stack:适配小设备,跨平台(各种平台都可以重复使用),可移植,指令更多,指令集更小,性能更差。

register:指令更少,性能比stack高

各种JVM版本:

classic VM(sun) :只有解释器,只会运行,没有热点探测,没有优化

EXACT VM :热点探测,混合工作(编译器,解释器)

HotSpot VM :热点探测,融合了JRockit 的优势

JRockit VM :最快的JVM,直接面向服务端

J9 VM :

Graal VM

JIT即时编译器:

探测热点代码,暂停时间过长(因为JVM需要给他的内部进行优化)~等公交

时间与性能(运行效率)的博弈

分类:

很重要:

类加载子类系统:

引导类加载器

拓展类加载器

应用类加载器

自定义类加载器

运行时数据区域:

堆区、栈区、方法区、寄存器区

执行引擎:

垃圾回收、编译器、即时编译器

类加载器子类系统:

各个ClassLoader类加载器简介:

包含了引导类、拓展类、应用类引导器

引导类是由c/c++编写的,在程序内不可获取;Java的核心类库都是在这里加载的(只加载java、javax、sun开头的类)

拓展类是由Java语言编写的,都是在lib\ext包下的。

自定义类:可以对源码进行加密,可以防止源码泄露

继承URLClassLoader可以更加方便的测试(不用像继承ClassLoader一样需要编写findClass方法和字节流……)

类的加载

加载:生成Class对象,加载各种类(引导、拓展、应用/系统类)

连接:

验证:确保Class文件满足JVM字节码的要求

准备:先准备好变量容器(变量就是容器,先赋零值),static final修饰的在编译的时候已经分配好了。

解析:将符号转变为直接引用

初始化:

【0】init执行默认构造器,子类加载init之前,父类完成加载(一个类只会被加载一次

【1】clinit == 执行方法:== class init

Tips:执行静态代码块 static {}/静态的变量会在编译的时候就给予赋值

ClassLoader的获取方法:

publicstaticvoidmain(String[]args)throwsException{// 【1】当前类的类加载器ClassLoaderclassLoader1=Class.forName("java.lang.String").getClassLoader();System.out.println(classLoader1);// 【2】当前线程上下文加载器ClassLoadercontextClassLoader2=Thread.currentThread().getContextClassLoader();System.out.println(contextClassLoader2);// 【3】引导类加载器(当前类的父级)ClassLoadersystemClassLoader=ClassLoader.getSystemClassLoader().getParent();System.out.println(systemClassLoader);}

双亲委派机制:(加载class文件的方式)

如果一个类加载器接收到了请求,不会自己先去加载,而是会把请求交给父类加载器,直至顶层的类加载器

顶层的类加载器如果能够处理,那么就返回成功,不能处理则交给子类加载,层层下传直到最底层的自定义类加载器。

好处

防止类的重复加载,保证Java核心包的类不被替换

按需请求:只有用某个类的时候才会去请求加载某个类,并且将这个类加载到内存中。

区分类:同时双亲委派机制也可以帮助我们去区分两个类,两个类的包名不一样是不同的类,两个类的加载器不一样也不是同一个类。

沙箱安全机制:

进入方法我们就需要执行main方法,但是此时main方法所在的类需要被加载,而String没有main方法,所以报错。

开始使用的时候,我们自定义的String类会使用引导类加载器加载;而引导类加载器会使用rt.jar包下的String类,因为rt.jar包下的String类里面没有对应的方法,所以报错,这也体现了对源码的保护功能 == 沙箱安全机制

运行时数据区:

包含了【本地方法栈、虚拟机栈、堆、方法区、PC寄存器(计数器)】

我们最常用的就是运行时数据区,“厨子”就是执行引擎

共享:方法区、堆区【主要的GC对象】

私有的:程序计数器,本地方法栈(本地方法接口、本地方法接口),虚拟机栈

内存】就是CPU和网络/硬盘的 桥梁

1、PC寄存器

Program Counter Register 程序计数器

Def:存储了下一条指令的地址(就像一个游标一样,告诉程序下一步应该怎么走。)

被Thread私有,每个线程独有一个程序计数器

不存在【GC、OOM】

2、JVM虚拟机栈

栈中包含了栈帧,一个栈帧对应着一个方法。

就像Stack一样,来一个就放一个,只处理栈顶元素,管理【调用&返回】,【不存在GC】,但是有【栈溢出】

使用的指令架构:【

栈溢出:

内存溢出:栈溢出,但存在动态扩展机制,直到内存占满了才会出现OOM

线程:独有栈,之间的栈帧不共用。

栈帧:LV OS DL RA andsoon

局部变量表(Local Variables)、操作数栈(operand Stack)、动态链接(指向常量池)、方法返回地址(Return Address)、符加信息

动态链接:访问/指向【运行时常量池】的方法引用

Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(Symbolic Reference )保存在class文件的常量池里,此时我们就需要一个动态连接符号引用转变为方法的直接引用

Constant Pool : #1 = ……

方法调用的原理:

静态绑定:早期绑定——编译时——构造方法

动态绑定:晚期绑定——运行时——上转型对象(多态)

前提:1.父子关系;2.重写(三方API)

静态方法不可被重写,不加super/this == 虚方法(编译的时候不确定。)

同时有俩方法,接口的优先级比较低,父类重写就用自己的。

局部变量表:方法结束就销毁,表是一维的表

变量表需要显式赋值,否则无法使用。

Slot 变量槽

byte、short、boolean、char == > int,都是占用一个slot

long、double、float 占用两个slot

操作数栈:基于栈的执行引擎

栈= 【数组】{链表实现}

拿到数据到执行引擎之后,执行引擎读到iadd指令,交给CPU进行运算,返回操作数给栈,再返回局变表。

对值进行push、pop、add操作

TOS技术:Top-of-Stack Cashing技术 == 栈顶缓存技术

将操作数缓存在【cpu寄存器中】,执行效率up(因为降低了内存的读写操作。)

方法返回地址:带有return信息

正常就是一个返回地址,里面包含了PC程序计数器的值。

附加信息

3、本地方法栈:

很多是底层由C语言写的,执行效率较高。

本地方法接口:

Native Method就是一个java调用非java代码的接口,调用的是非Java代码,没有具体的实现。

**native **是有方法体的,只是我们看不到,和abstract互斥。【非Java代码实现】

优点:执行效率高;与外界交互(底层);解释器也用到C库

4、堆

所有的实例对象+数组都存放在堆中,进程对应着实例,一个进程中的线程共享堆,共享实例对象。

GC流程:对于一个用户线程,不够用再GC(给大内存,减少频繁GC),减少STW,可以去优化用户线程的体验

逻辑连续:新生区+养老区+永久代/元空间

参数设置

-Xmx  最大堆内存大小

-Xms  初始堆内存大小

-Xmn  年轻代大小

-XXSurivivorRatio=3 年轻代被划分为 3:1:1

-Xms10m ; -Xmx10m设置相同的值可以去除扩展和减少的过程,

<==>  memory start  使初始堆内存大小 = 最大内存大小

默认参数:物理电脑内存/64;最大:电脑内存/4

jps

jstat -gc  进程id

- 设置-XX:PrintGCDetail 读取详细参数

OOM(OutOfMemory)

old区满了,装不下新创建的实例对象——Full GC

Default:

-XX:NewRatio=2,新生代和老年代比例为1:2

-XX:+UseAdaptiveSizePolicy,内存分配策略

-XX:SurvivorRatio=8,设置Eden和Survivor的比例

YGC/Minor GC:

过程:

Eden区满了找垃圾,将Eden和S0一起回收,总有一个s区是空的(为to区)

阈值默认为15,满了之后会promotion到永久代/元空间中

未达到阈值的对象,把幸存的对象放入s区

GC:我们可以频繁的回收新生代,但是尽量不要对养老区进行垃圾回收(比较浪费资源)

Full GC:整堆回收

Major GC:老年区垃圾回收FGC

Minor GC:新生代垃圾回收YGC(占用的时间最短)

Promotion原则:

优先Eden区

大对象直接老年代(但是朝生夕死就很难受)

晋升规则:

长期存活达到阈值就晋升为老年代

动态对象年龄判断

空间分配担保

TLAB:Thread Local Allocation Buffer

堆共享,多个线程同时操作是不安全的,-XX:UseTLAB 内存分配机制

我们给每个线程都留下一些私有的TLAB空间

空间分配担保:

老年代连续空间大于新生代对象的总大小 or 大于之前晋升的平均大小 == YGC,否则Full GC

JIT:

若新建的对象没有逃逸出方法区,优化的方式是【栈上分配

可用局部变量就不在外面定义。

基于逃逸分析:

栈上分配

线程同步省略

标量替换(默认使用)

5、方法区

待写……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容