[jvm]螺丝刀学习笔记之——重学jvm概览(代码片段)

削尖的螺丝刀 削尖的螺丝刀     2023-01-18     481

关键词:

这里是螺丝刀本人在学习JVM专栏时,结合自己理解对一些重点概览做的提炼总结,为方便自己学习和记忆,也更加欢迎感兴趣的童鞋一起交流探讨。

JVM是如何运行JAVA文件的?
  • Java文件在打包成jar或者war后会变成Class文件,在容器里面调用JVM,时候就会加载class文件

    • 加载的过程: 加载 —— 连接(校验,准备(在这里会设置内存空间,并给static赋默认值,finalstatic直接赋值放在常量池,这个必须记住),解析) —— 初始化(在这里会调用静态方法) —— 使用 —— 销毁
    • 加载方式: 双亲委派
    • 加载时机:
      • main方法中
      • new 对象的时候
      • 加载对象的时候发现有父类没加载也会加载
  • Tomcat的web容器是如何加载Java文件的?

JVM内存模型的一些介绍
  • class文件在1.8以前是放在永久代方法区1.8以后取消了永久代,放在了元空间(系统内存大小)
  • 线程私有
    • 程序计数器: 因为我们编译好的代码都是在字节码文件中的,而字节码文件中标明了各代码的执行顺序,JVM会根据 字节码引擎运行程序计数器执行字节码中的代码,这个程序计数器是各线程私有的
    • 虚拟机栈: 为什么叫栈呢?因为线程每执行一个方法就调用对应的栈帧做一次压栈。栈帧里有:
      • 栈帧中保存了局部变量表(这也是为什么局部变量是线程私有的,线程安全),这里面的变量指向堆中的具体对象。
      • 操作数栈
      • 动态链接
      • 方法出口
    • 本地方发栈: 里面的所有代码都不是JAVA写的,而是C写的native方法。

在说到内存模型的时候,一定脑子里要有一个动的图,比如

1.类会被加载到metaSpace,然后初始化等 —— 2.线程启动会有程序计数器指定方法的执行的顺序 ——> 3.每个线程中有栈帧(包含局部变量表、操作数栈、动态链接、方法出口),每个方法执行的时候都会和局部变量被压入栈中。4 ——> 每个栈帧中的局部变量都会指向堆中的具体对象。 ——> 5. 如果是执行的本地native方法则会在本地方法栈中做压栈。

一个方法执行完后会怎样?
  • 虚拟机栈中的栈帧全部会出栈,这时没有对象再指向堆中了,也就是说没有了GCROOT(局部变量可作为GCROOT)的引用,可以被回收

为什么要区分内存空间?

  • 因为内存资源是有限的,我们要做合理的区分和管理,比如有些对象是朝生夕死的,所以就要放再年轻代中做多次GC来判定是否该去老年代存储。
一个Java对象在堆内占多少内存空间?
  • 首先,内存空间占用分为两块(1.对象本身信息、2.对象中的变量数据所占用的空间)

对其填充: jvm内存占用是8的倍数,所以结果要向上取整到8的倍数

方法区(mataSpace内会不会进行回收?)

关于垃圾回收(题目为:对象在JVM如何分配的?如何流转的?)
  • 回收时间,空间快满(Eden和S1都满了)的时候会发生回收,分配是会先在年轻代(Eden)分配,如果满了回收后的晋升机制如下
    • 新生代回收后的晋升机制:
      • 年龄回收机制: 一次回收代表一次年龄增长,如果躲过15次回收就代表15岁了,在JVM中,新生代默认躲过15次回收的会被放入老年代(可通过-XX: MaxTenuringThreshold设置这个阈值)。
      • 大对象回收机制: 特别大的对象(默认超过1M,-XX: PretenureSizeThreshold可设置)会直接进入老年代
      • 动态年龄判断机制 : Suviver中的数据量总大小 超过了这块Suviver**区域的50%**会直接进入老年代
      • 空间担保机制: (暂时这样写,之后可能要改和完善),如果超过了整个年轻代可回收的数据量,则全部会直接进入老年代,如果老年代也满了则会发生MajorGC或者OOM
偏门问题:方发栈中的对象会被回收吗? —— 当出栈以后,局部变量就直接从内存中清理掉了
关于参数设置:
  • 如何设置?

    • 开发环境,IDEA中有一个Debug Configuration,设置好参数启动就好。
    • 线上,如果是jar包启动,那就java -jar 带上参数即可。
    • 线上,如果是SpringBoot启动
  • 关键参数:

    • Xms(初始堆内存大小)、Xmx(最大堆内存大小)【这两个一般设为同样大小】
    • Xmn(年轻代大小)
    • Xss(栈大小)
    • MetaspaceSize(初始元空间大小)、MaxMetaspaceSize(最大元空间大小)【这两个一般设为同样大小】
  • 广义上来说:一般是系统内存的一半分配给JVM(因为操作系统要用),比如8G的话,可以3G分给堆,2G分给年轻代,256M分给元空间(因为元空间存的大多是Class类信息),1M分给栈【一般元空间和栈是不会特别去预估设置的,在这个范围即可】

  • 狭义上来说: 这个要具体根据场景来定义的,比如算出高峰期、低峰期,然后每秒大概用多少内存,然后放大多少倍估算等,但是这个据我了解一般大公司都有固定的模板,在这个模板的基础上进行内存的设置和调优,这个我确实没具体的经验。

题外话: 建议不要手动触发,依托合理的内存设置以及参数优化,让系统自行运转(默认自行调节)

关于STW(Stop the World)
  • JVM在回收的时候不能再写入对象,这个就是Stop the World,虽然都有STW,但是不同垃圾回收器对STW的影响不同
关于GC的选择:
  • Serial和Serial Old:分别对应新生代和老年代,单线程的运行,回收的时候会阻塞系统的其他线程,现在Java系统功能几乎不用。
  • ParNew(新生代,多线程,标记复制) + CMS(老年代,多线程,且可和工作线程尽量同时工作处理,标记清除),这一套几乎是现在线上生产系统的标配组合
  • G1(整体标记整理。局部标记复制) —— 可统一手机新生代和老年代,不再具体区分这两代,而是动态的区分和设置。
JVM中有哪些垃圾回收算法,每个算法各自的优劣?
  • 标记复制 —— 当S1满了以后会做清除,然后存活的10%对象复制到新的S2中去(但是内部命名还是把这个新的位置改为S1了),所以S1/S2中永远有一块是空的也就是10%的空闲位置。
    • 因为在年轻代中,Eden和S1、S2的分配比例为8:1:1,因为很多对象都是朝生夕死的,我看过的专栏文章上说大概率超过1毫秒就没有引用了,最终存活的对象只有10%,所以这样分配,保证有Eden+S1,这个标记复制算法的最大好处是 —— 有90%的空间是被使用的,而10%的空间用来做空闲转换空间
    • 年轻代发生该算法的时机 —— Eden和S1都满了
  • 标记整理
    • 在完成标记-清除的算法基础上,将所有存活的对象向一端移动,这样不会有空间碎片(一根指针区分开已用和未用内存,作为指针碰撞 [ 新来对象,则向未用方向分配新来对象的内存个大小数 ] 的内存分配手段)
    • 老年代发生该算法的时机 —— 1.年轻代满了直接晋升老年代时判断是否要MajorGC。2.老年代确实满了发生MajorGC
  • 标记清除
    • 将所以可回收的对象标记,然后统一清除。清除的空间会被空闲空间表维护,作为内存分配的手段(最基础法,后面算法都是对其的改进)

[jvm]螺丝刀学习笔记之——重学jvm概览

这里是螺丝刀本人在学习JVM专栏时,结合自己理解对一些重点概览做的提炼总结,为方便自己学习和记忆,也更加欢迎感兴趣的童鞋一起交流探讨。JVM是如何运行JAVA文件的?Java文件在打包成jar或者war后会变成Class... 查看详情

[elasticsearch]螺丝刀学习笔记之——elasticsearch(7.0up学习概览)(代码片段)

在此1024广大猿人欢度佳节之际,作为广大猿族的一员怎能不拿出点东西庆祝庆祝呢?这不,压箱底的两篇学习笔记其中之一——ElasticSearch学习概览,就此JI出~~,祝自己和各位猿族兄嘚们节日快乐,同时欢迎各... 查看详情

[elasticsearch]螺丝刀学习笔记之——elasticsearch(7.0up学习概览)(代码片段)

在此1024广大猿人欢度佳节之际,作为广大猿族的一员怎能不拿出点东西庆祝庆祝呢?这不,压箱底的两篇学习笔记其中之一——ElasticSearch学习概览,就此JI出~~,祝自己和各位猿族兄嘚们节日快乐,同时欢迎各... 查看详情

b站学习笔记之初探jvm学习笔记(代码片段)

写在前面本次笔记整理学习来源–>B站传送门–>【狂神说Java】JVM快速入门篇感谢狂神❤这位up的短视频知识点教学也很棒–>B站up主较真的度[程序员5分钟]白话JVM内存结构,死也忘不了;[程序员5分钟]带你认识java中jvm虚... 查看详情

java之jvm介绍(学习笔记入门)(代码片段)

为自己的学习笔记,图形说话java之所以这么强大是因为跨平台,最直接的就是jvm,每天我们都是写代码,CV大法。java->lcass-->jvm是如何演变呢?中间发生了啥?一、整个java的演变 图直观的看到如下:从... 查看详情

jvm学习笔记--方法调用之静态分配和动态分配(代码片段)

本篇文章从JVM的角度来理解Java学习中经常提到的重载和重写。方法调用:方法调用不等同于方法执行,在Java虚拟机中,方法调用仅仅是为了确定调用哪个版本的方法。方法调用分为解析调用和分派。解析调用一定是静态的,而... 查看详情

jvm之方法区和堆的总结(学习笔记)(代码片段)

文章目录1、方法区1.1、方法区、永久代(`PermGenspace`)、`Metaspace`(元空间)的区别1.2、方法区的使用1.3、方法区和`字符串常量池存`的变化2、堆(heap)2.1、新生区(New/YoungGeneration&#x... 查看详情

大数据技术之_30_jvm学习_01_jvm位置+jvm体系结构概览+堆体系结构概述+堆参数调优入门+jvm的配置和优化+tomcat的配置和优化

1、JVM位置2、JVM体系结构概览3、堆体系结构概述4、堆参数调优入门5、JVM的配置和优化6、Tomcat的配置和优化熟悉JVM架构与GC垃圾回收机制以及相应的JVM调优,有过在Linux系统下的调优经验。淘宝的周志明《深入理解Java虚拟机》中... 查看详情

目录jvm目录

JVM学习目录为了方便园友,现对JVM序列笔记做了归档,园友们可以一口气读完整个JVM的笔记1. 【JVM】JVM系列之JVM体系(一)2. 【JVM】JVM系列之垃圾回收(二)3. 【JVM】JVM系列之Class文件(三)4. 【JVM】JVM系列之类... 查看详情

(2021-05-28)jvm概览学习

面试准备,jvm也需要再回顾一下。目录1.什么是JVM2.JVM的组成2.1类加载子程序1.加载2.验证3.准备4.解析5.初始化2.2运行时数据区1.线程私有数据2.线程共享数据2.3执行引擎3.GC3.1GC的判断方法3.2GCROOT3.2内存泄漏和内存溢出4.分代机... 查看详情

jvm学习笔记

JVM学习笔记准备中 查看详情

jvm学习笔记(自用)(代码片段)

1.jvm内存模型2.类加载器作用:加载Class文件类加载器分类:1.虚拟机自带的加载器2.启动类(根)加载器3.扩展类加载器4.应用程序(系统)加载器加载步骤:1.类加载器收到类加载的请求2.将这个请求向... 查看详情

jvm系统优化实践:jvm概览

...51CTO博客,欢迎您来,欢迎您再来~这是多年之前做过的学习笔记,今天再翻出来,觉得仍然是记忆犹新。「独乐乐不如众乐乐」,就拿出来分享给「众乐乐」吧。目前大多数Java工程师都面临一个共同的问题:对JVM的了解非常贫... 查看详情

jvm之逃逸分析技术(代码片段)

引言我在面试别人的过程中,JVM内存模型我几乎必问,虽然有人说问这些就是面试造航母,工作拧螺丝。如果你想当一名CRUD码农,你可以选择不用了解这些。在JVM内存模型的问答中,有些人能说出对象是在堆... 查看详情

jvm学习笔记对象创建直接内存与执行引擎(代码片段)

一、对象的创建1对象实例化的几种方式2从字节码角度看对象的创建packagecom.spd.jvm;publicclassTest publicstaticvoidmain(String[]args) Objectobj=newObject();   对应字节码:0new#2 //创建Object对象3dup //复制一份栈顶slot并压入栈中4invokes... 查看详情

jvm学习笔记字节码指令集解析(代码片段)

一、class的文件结构1前端编译器  AOT效率较高,但只支持Linux平台。2透过字节码查看代码执行细节-1  源代码如下:publicclassTest publicstaticvoidmain(String[]args) Integerx=5; inty=5; System.out.println(x==y); Integ 查看详情

jvm学习笔记类的加载过程(代码片段)

一、类的生命周期概述二、类的加载阶段Loading1加载完成的操作2二进制流的获取3类模型与class实例的位置  反射的使用:importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;publicclassTest publicstaticvoidmain(String[]args) try Class&l 查看详情

jvm学习笔记类的加载过程(代码片段)

一、类的生命周期概述二、类的加载阶段Loading1加载完成的操作2二进制流的获取3类模型与class实例的位置  反射的使用:importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;publicclassTest publicstaticvoidmain(String[]args) try Class&l 查看详情