JVM学习进阶
文章平均质量分 75
skye_fly
这个作者很懒,什么都没留下…
展开
-
JVM调优
1. JVM常用命令行https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.htmljava -XX:+PrintCommandLineFlags HelloGC——执行HelloGC.java同时打印出堆内存分配情况以及压缩指针启用情况;-XX:InitialHeapSize=199014080-XX:MaxHeapSize=3184225280-XX:+PrintCommandLineFlags -XX:原创 2022-01-06 20:20:52 · 566 阅读 · 0 评论 -
GC 算法与垃圾回收器
一、三种垃圾清理方法标记清除:扫描两边 + 内存碎片 — (优点)效率高,速度快复制:对象移动 + 内存利用率低 — (优点)无内存碎片,清理速度快标记整理:扫描两边 + 对象移动 + 效率低 — (优点)无内存碎片,内存利用率高二、对象的生命周期尝试在栈中分配 — 进入eden区 — 发生GC — 进入survivor1区 — 进入survivor2区 — 交替在survivor区移动 — 进入old区 — FullGC被清理三、对象所在空间栈上分配的对象线程私有的小对象对象不原创 2021-12-26 20:31:58 · 686 阅读 · 0 评论 -
Java程序执行过程+Class文件解读
学习JVM的目标(可以写到简历上):熟悉GC常用算法,熟悉常见垃圾收集器,具有实际JVM调优实战经验。1. Java程序执行过程:任何语言只要是.class文件,都能被JVM解释执行从而实现跨平台(即时编译得到的是对应操作系统的机器码文件,所以无法跨平台);JVM与java没有关系,只跟.class文件有关系。JVM执行Java语言时是同时有解释执行和即时编译执行的,JVM会对反复执行的热点方法进行即时编译从而提高程序的执行效率。2. Class文件解读用sublime或者IDEA原创 2021-12-18 21:05:16 · 1084 阅读 · 0 评论 -
JVM循环优化与向量化优化
即时编译器针对循环程序块的编译优化,生成的IR图会改变原有的循环程序块内容 — 外提与展开。(外提就是提取公因式,展开就是减少判断次数)优化一:无关代码外提 — 减少某些程序的重复执行即时编译器会将常值放到循环体外,并且计算一次后会将这些常值放入缓存,每次循环直接从缓存中取数据。int foo(int x, int y, int[] a) { int sum = 0; for (int i = 0; i < a.length; i++) { sum += x * y + a[i]原创 2021-09-23 21:56:45 · 385 阅读 · 0 评论 -
JVM字段访问优化
都是通过即时编译器优化生成的IR图来精简最后的机器码(在生成机器码前就好像人浏览了一遍代码,通过前后关联情况手动消除了一些重复或无效的代码),去掉无效代码,减少在code cache中存储的机器码的大小,节省内存,提高程序运行速度。主要包括:缓存读取、去除重复操作、分支优化、不可达分支消除一、对象字段读取优化优化一:缓存读取static int bar(Foo o, int x) { int y = o.a + x; // 将o.a存入缓存 return o.a + y; // 直接从缓原创 2021-09-22 11:03:12 · 249 阅读 · 0 评论 -
即时编译器的逃逸分析及优化
一、概念逃逸分析:指的是对象是否会逃逸出当前方法,进入堆内存中或者作为参数传入被未知方法引用。如果在堆中那么该对象会被所有线程看见并引用,未知方法包括虚方法,对象传入虚方法中就算逃逸。逃逸分析可以根据逃逸范围实现以下多个编译优化的好处,缺点是分析本身需要消耗一定的CPU资源;逃逸:因为当对象被多个线程引用或者被虚方法引用时,编译器无法定位对象的位置,所以被认为是逃逸了;逃逸范围:(范围由小到大)不逃逸:只在一个方法中被引用(支持同步消除、标量替换、栈上分配优化)方法逃逸:在同一个线程内的多个方法原创 2021-09-21 13:53:26 · 130 阅读 · 0 评论 -
Java泛型、即时编译JIT、方法内联
一、 泛型泛型的作用就是程序员不用手动进行类型强转了,但是类型转化是不能少的,只不过交给了编译器来做。ArrayList< Object >没有泛型前,在ArrayList中存入String时,编译后元素会被转化成Object,当程序中取用元素时得到的也是Object类型变量,所以要手动向下转化成String类型。有了泛型后编译后字节码中仍然为Object类型(泛型擦除),只不过程序中取用元素时,编译器会帮我们进行类型转化,得到的就直接是String类型元素了。泛型擦除的目的:泛型擦除是为原创 2021-09-20 17:08:17 · 295 阅读 · 0 评论 -
synchronized实现线程同步以及多线程堆栈空间(ThreadLocal内存分配)
一、sychronized实现线程同步底层是将Java代码编译成字节码时添加一条monitorenter和两条monitorexit指令(保证任何情况下锁都能退出),修饰代码块时字节码显式的含有这两条语句,修饰方法时字节码中用一条ACC_SYNCHROZIED声明使用以上两条指令。sychronized的锁对象(类/对象锁):修饰静态方法则获取类锁,加锁的对象是该类的所有对象(因为所有对象共享静态方法);修饰动态方法则获取对象锁,加锁的是该类的当前对象(每个对象有独立的动态方法)—由此可以实现J原创 2021-09-17 14:01:49 · 328 阅读 · 0 评论 -
Java指令重排与多线程安全
单线程内以及多线程之间的happens-before原则保证线程安全;一、volatile保证线程安全(非原子性)有序性(单线程内有序 / 多线程之间有序) + 可见性(一致性)单线程内:单线程中指令重排不会影响线程处理结果,但是可以使用volatile关键字禁止指令重排(volatile的单线程有序性性质,因为会在方法执行过程中相应程序行处加入内存屏障,会实时刷新缓存空间,即时编译器在寄存器中会按照顺序执行缓存行程序);多线程之间:多线程中指令重排会导致最终结果不一致,可以使用volat原创 2021-09-16 21:22:39 · 443 阅读 · 0 评论 -
JVM GC垃圾回收
GC Root:由堆外指向堆内的引用方法栈帧中的局部变量已加载类的局部变量JNI handles已启动且未暂停的Java线程一、GC Root可达性分析的问题多线程环境下,某些线程可能会将某对象的引用误置为null(误报,其他线程中这个对象正在被引用),或者没有将自己引用过的对象设置为被引用(漏报),可以用以下STW解决。二、Stop the World(老年代回收有时会出现卡顿)停止所有其他非GC的线程的工作,直至完成本次垃圾回收(本质上其他线程并不一定都被挂起暂停,只要运行在安全.原创 2021-09-15 11:20:24 · 65 阅读 · 0 评论 -
Java对象的内存布局
注:子类构造器需要调用父类的构造器,直到Object类,所以子类实例在建立时会同时在内存中分配它的父类的一些实例字段。16字节对象的对象头 = 8字节标记字段(hashcode、GC、Lock)+8字节类型指针(指向该对象的类)12字节压缩对象头 = 8字节标记字段(hashcode、GC、Lock)+4字节压缩指针(指向该对象的类,将原本的64指针压缩至32位)对象内存布局的三点特性:特性一:内存对齐一个字段未填满规定大小的内存空间时系统会自动填充缺失的字节数(非有效数据),造成内存原创 2021-09-14 11:28:11 · 97 阅读 · 0 评论 -
Java类的加载机制
一、有哪些类基本数据类型(虚拟机中定义好的,虚拟机启动就存在);引用类型(由类加载器加载);注:基本类型的对象不是都放置在栈中,当在类的中方法中被调用时作为成员变量,放置在栈中;当在方法外部作为全局变量时放在堆中(除了常量池中的基本数据)。二、类加载器启动类加载器:加载最重要的类(启动JVM所需的类),没有java对象,用null代替;扩展类加载器:加载次要的类;应用程序类加载器:加载用户应用程序中所需的类;用户自定义类加载器:实现用户想要的自定义的类加载操作。为什么要那么多类原创 2021-08-25 22:17:00 · 110 阅读 · 0 评论 -
Java代码是如何运行的(run time data area & JVM Instructions)
一、为什么要有Java虚拟机(好处)一次编译,处处运行,将java代码编译成java字节码(JVM中的字节码指令的操作码是一个个为字节单位的),JVM再把java字节码编译成计算机能识别的机器码然后运行;提供java代码的内存管理,也就是垃圾回收;提供编写代码时的异常检测。二、JVM怎么执行java方法基本流程如下:读取方法区.Class字节码中的java方法 —— 在栈中开辟一个栈帧(不连续)存放该线程执行该方法时要用的局部变量 ——JVM将方法的java字节码翻译成机器码交给计算机执行(原创 2021-08-23 22:06:55 · 176 阅读 · 0 评论