JVM基础知识总结(一)

一、CLASS文件结构初识

1、Class文件结构

magic–>CA FE BA BE、minor version–>00 00、major version–>00 34(16进制,jdk8编译)、constant_pool_count-1–>00 10
Constant Pool:1、CONSTANT_Methodref_info常量池入口,标记、index 2个字节指向声明方法的类或者接口描述的CONSTANT_Class_info的索引项; 后面的index 占2个字节 指向字段描述符CONSTANT_NameAndType的索引项。2、CONSTANT_Class_info
感兴趣的话自己研究下,想要看到如下图所示的的class文件结构需要在你的idea上装插件(jclasslib Bytecode viewer)

二、类加载过程

1、Loading

把一个calss文件load到内存,类的加载就是将class文件中的二进制数据读取到内存中,然后将该字节流所代表的静态数据结构转化为方法区中运行的数据结构,并且在堆内存中生成一个java.lang.Class对象作为访问方法区数据结构的入口;1、使用双亲委派机制,为什么使用双亲委派机制呢?就是为了安全。2、lazyloading的五种情况: –new getstatic putstatic invokestatic指令,访问final变量除外、–java.lang.reflect对类进行反射调用时、–初始化子类的时候,父类首先初始化、–虚拟机启动时,被执行的主类必须初始化、–动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化。
双亲委派中父加载器之间并不是继承关系
classloader的源码分析: 1. findInCache -> parent.loadClass -> findClass()
自定义类加载器:1、继承ClassLoader;2、overwrite findClass() -> defineClass(byte[] -> Class clazz);3、加密;4、打破双亲委派重写loadClass(); ThreadContextClassLoader可以实现基础类调用实现类代码,通过thread.setContextClassLoader指定(热启动、热部署)osgi tomcat 都有自己的模块指定classloader(可以加载同一类库的不同版本)
Java混合执行 编译执行 解释执行;检测热点代码:-XX:CompileThreshold = 10000

2、Linking

linking分为三步分别是验证(校验是否符合JVM的规范)、准备(静态变量赋默认值)、解析(将类、方法、属性等符号引用解析为直接引用;常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用);

3、Initialzing

执行静态代码块,给静态变量赋初始值

三、运行时数据区

1、程序计数器ProgramCounter简称PC(线程私有);2、直接内存:直接操作os的内存(nio);3、本地方法栈;4、JVM stack;5、heap;6、运行时常量池;7、元数据区

四、JMM

Java Memory Model,Java内存模型的主要目的,定义程序中各种变量的访问规则,关注在虚拟机中把变量存储到内存和从内存中读取变量值这样的底层细节。关于主内存和工作内存之间的具体的交互协议,即一个变量从主内存到工作内存、如何从从工作内存同步到主内存这一实现细节,Java内存模型中定义了8种操作来完成。
CPU的速度比内存快100倍,CPU中有L1和L2 高速缓存(速度很快但是很小),intel 用MESI(缓存一致性)Modified、Exclusive、Shared、Invalid
cache line:读取缓存以Cache Line为基本单位,目前64byte。
伪共享:位于同一缓存行的两个不同的数据,被两个不同的cpu锁定,产生相互影响的伪共享问题。使用缓存行对齐来解决,会浪费一定的内存空间。

五、垃圾回收

1、什么是垃圾?没有任何引用指向的一个对象或者多个对象(循环引用)。2、如何定位垃圾?引用计数法、根可达算法。3、常见的垃圾回收算法:1. 标记清除(mark sweep) - 位置不连续 产生碎片 效率偏低(两遍扫描)2. 拷贝算法 (copying) - 没有碎片,浪费空间3. 标记压缩(mark compact) - 没有碎片,效率偏低(两遍扫描,指针需要调整)4.JVM内存分代模型(用于分代垃圾回收算法)
新生代 + 老年代 + 永久代(1.7)Perm Generation/ 元数据区(1.8) Metaspace;永久代 元数据 - Class;久代必须指定大小限制 ,元数据可以设置,也可以不设置,无上限(受限于物理内存);字符串常量 1.7 - 永久代,1.8 - 堆;MethodArea逻辑概念 - 永久代、元数据。

垃圾回收器Garbage Collectors:线上的调优,首先,确定是哪个版本,第二,确定哪一种垃圾回收器
使用命令来确定生产环境使用的垃圾回收器:java -XX:+PrintCommandLineFlags -version
eden+survitor+survivor = YGC一次垃圾回收时大约只有10%存活Mark-Sweep和Mark-Compact都不合适,所以使用Copying算法把“活着的对象”拷贝到survivor区。eden+survitor+survivor通过-Xmn配置参数,MinorGC/YGC年轻代空间耗尽的时候触发。
tenured老年代:通过Mark-Sweep或者Mark-Compact算法回收;eden+survitor+survivor+old通过-Xms -Xmx配置参数;MajorGC/FullGC,在老年代无法继续分配空间的时候触发,新生代老年代同时进行垃圾回收。
新生代 = Eden + 2个suvivor区;YGC回收之后,大多数的对象会被回收,活着的进入s0;再次YGC,活着的对象eden + s0 -> s1;再次YGC,eden + s1 -> s0;年龄足够 -> 老年代 (15 CMS 6)s区装不下 -> 老年代
老年代:老年代满了FGC Full GC
对象内存分配:

六、常见的垃圾回收器

Serial 年轻代 串行回收、PS 年轻代 并行回收、ParNew 年轻代 配合CMS的并行回收、SerialOld、ParallelOld、ConcurrentMarkSweep 老年代 并发的, 垃圾回收和应用程序同时运行,降低STW的时间(200ms),CMS问题比较多,所以现在没有一个版本默认是CMS,只能手工指定、CMS既然是MarkSweep,就一定会有碎片化的问题,碎片到达一定程度,CMS的老年代分配对象分配不下的时候,使用SerialOld 进行老年代回收、G1(10ms),算法:三色标记 + SATB、ZGC (1ms) PK C++,算法:ColoredPointers + LoadBarrier

1.8默认的垃圾回收:PS + ParallelOld

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值