栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JVM系列——垃圾回收调优,类加载和字节码技术day2-1

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JVM系列——垃圾回收调优,类加载和字节码技术day2-1

JVM系列——垃圾回收调优,类加载和字节码技术day2-1
  • 垃圾回收调优
    • 如何确定自己使用了哪些垃圾回收器
    • 垃圾回收调优涉及目标
    • 新生代调优
      • 新生代特点
      • 设置新生代的空间大小
        • 新生代中的幸存区
    • 老年代调优
  • 类加载
    • 类文件结构
    • 编译查看字节码文件
    • 分析16进制字节码文件
      • 使用notepad进行转码
      • 第一行:魔数(前4个字节)我是以索引看的,第一个字节就是第0字节
      • 第一行:版本(4~7字节)
      • 第一行:常量池(自8字节开始)
        • 常量池中的#1
        • 常量池中的#2
      • 第二行
        • 常量池中的#3
        • 常量池的#4
        • 常量池的#5
        • 常量池的#6
        • 第三行
        • 常量池的#7
      • 访问标识与继承信息
      • field成员变量信息
      • Method 信息
      • 附加属性
      • 文档

垃圾回收调优
-XX:+PrintGCDetails -verbose:gc
如何确定自己使用了哪些垃圾回收器

若你是在项目中,可以直接使用编辑器的终端查看对应版本的垃圾回收器
1.打开cmd
2.输入以下内容

java -XX:+PrintFlagsFinal -version | findstr "GC"


垃圾回收调优涉及目标
  1. 低延迟?(使用CMS,G1[jdk9],ZGC[jdk12])
  2. 高吞吐量?(使用ParallelGC)
  3. 使用何种垃圾回收器?
  4. 使用的JDK版本?
  5. 使用哪个Java虚拟机?
新生代调优 新生代特点
  1. 所有的new操作的内存分配非常廉价
  2. 有TLAB thread-local allocation buffer进行对象的缓存分配
  3. 死亡对象的回收代价是零
  4. 大部分对象用过即死
  5. Minor GC的时间远远低于Full GC
设置新生代的空间大小

推荐设置的大小为整个堆内存的25% ~ 50%之间,但尽量靠近50%
计算公式:空间大小大于等于 并发量×(请求 - 响应)
例如:并发量为1000,则设置的内存大小就是 > = 512k×1000 = 500M

-Xmn

将新生代的空间扩大当然是最简单直接的方法,但是并不是越大越好
若新生代空间过大,则会导致老年代的空间变小,导致老年代的垃圾回收Full GC的次数增多,而老年代的垃圾回收时间比新生代长的多,这样程序的效率也就变得很低,若进行吞吐量优先的程序,则会导致数据计算缓慢,长时间得不到结果,若进行需要低延迟的网络应用,则表现为请求响应速度慢,这样又会涉及到前端的渲染问题(常见为渲染快于响应数据,导致数据无法完全渲染而网页内容丢失)

新生代中的幸存区

我们规定幸存区需要大到能够保留当前活跃对象+需要晋升对象
我们常希望晋升阈值配置得当,让长时间存活的对象尽快晋升

-XX:MaxTenuringThreshold=threshold:设置晋升阈值
-XX:+PrintTenuringDistribution:打印详细页(垃圾回收次数,幸存占用空间数,总空间占用)
老年代调优

老年代内存空间要尽量大
我们常采取的策略是:先不进行调优,若发现Full GC频繁则需要先调优新生代,再次测试,若依然发现此问题再调整老年代
观察FUll GC时老年代的内存占用,适应调大原始内存+溢出内存大小的1/4~1/3

-XX:CMSInitiatingOccupancyFraction=percent
类加载 类文件结构

编译查看字节码文件
//编译并保留参数信息
javac -parameters -d . .Hello.java
//查看分析字节码文件
javap -verbose Hello



分析16进制字节码文件 使用notepad进行转码

以下就是hello world编译出来的字节码文件了
一行共16个字节

借一下@Moonxiyue的这张图

这里表格中的常量池占位包含2位的标志名+内容占位/内容引用
这个信息是按照1个字节的16进制作为标志名(分为,方法,常量,成员变量,类。。。)标志名占的字节数不一样,比如方法就是占4个字节,这样的话就是3个字节或5个字节是一个常量池的项,只要看标志名就能确定项的编号

16进制标志名对应的10进制常量池占位(字节数)
1utf-81取决于后4个字节的长度,例如 01 00 08 表示长度为8字节,那么总占位就是8+3 = 11字节,此时我们要往后11个字节才能找到下一个常量池项
3Integer33
4Float43
5Long53
6Double63
7Class73
8String83
9Field95
AMethod105
BInterfaceMethod115
CNameAndType125
FMethodHandle155
10MethodType163
12InvokeDynamic185
第一行:魔数(前4个字节)我是以索引看的,第一个字节就是第0字节
CAFEBABE

第一个字节显示CAFEBABE表示Java
因为Java=爪洼,咖啡盛产地,Java名字的由来

第一行:版本(4~7字节)
00 00 00 37

其中第八个字节:37转为10进制就是55,52表示Java8,55则表示Java11

第一行:常量池(自8字节开始)
00 1F

表示常量池中有35项从#1~#34

常量池中的#1
0A 00 06 00 11 

0A:表示一个Method
00 06 :Method中的类名 ,表示引用常量池中的#6作为类名
00 11:Method的方法名,表示引用常量池中的#17作为方法名

常量池中的#2
09 00 12 00 13(0012 0013已经是第二行了)

09:作为Method的一个Field信息,含有成员变量的所属类和成员变量名
0012:表示引用#18作为所属类
0013:表示引用#19作为成员变量名

第二行 常量池中的#3
08 00 14

08:表示字符串常量名称
0014:表示引用#20作为其名称

常量池的#4
0A 00 15 00 16

0A又表示一个方法

常量池的#5
07 00 17

07表示Class,引用#23

常量池的#6
07  00 18

07又表示一个Class,引用#24

第三行 常量池的#7
01 00 06 3C 69 6E 69 74 3E

01 00 06 表示一个UTF-8串,占6*2 = 12字节,内容是3C 69 6E 69 74 3E

下面就以此类推找到最终的结果

访问标识与继承信息
标识名16进制值
public0001
final0010
super0020
interface0200
abstract0400
synthetic1000
annotation2000
enum4000
field成员变量信息
fieldType类型类型
Bbyte
Cchar
Ddouble
Ffloat
Iint
Jlong
L ClassName;reference
Sshort
Zboolean
[reference
Method 信息

一个方法由访问修饰符,名称,参数描述,方法属性数量,方法属性组成
红色代表访问修饰符(本类中是public)
蓝色代表引用了常量池#07项作为方法名称
绿色代表引用了常量池#08项作为方法参数描述
黄色代表方法属性数量,本方法是1
红色代表方法属性
00 09表示引用了常量池#09项,发现是【code】属性
00 00 00 2f表示此属性的长度是47
00 01表示【操作数栈】最大深度
0001表示【局部变量表】最大槽(slot)数
00 00 00 05表示字节码长度,本例是5
2a b7 00 01 b1是字节码指令
00 00 00 02表示方法细节属性数量,本例是2
00 oa表示引用了常量池#10项,发现是【LineNumberTable】属性- 00 00 00 06表示此属性的总长度,本例是6
00 01表示【LineNumberTable】长度
00 00表示【字节码】行号0004表示【java源码】行号
00 0b表示引用了常量池#11项,发现是【LocalVariableTable】属性
00 00 00 0c表示此属性的总长度,本例是12
00 01表示【LocalVariableTable】长度
00 00表示局部变量生命周期开始,相对于字节码的偏移量
00 05表示局部变量覆盖的范围长度心
00 0c表示局部变量名称,本例引用了常量池#12项,是【this】
00 0d表示局部变量的类型,本例引用了常量池#13项,是【Lcn/itcast/jvm/t5/HelloWorld;】
00 00表示局部变量占有的槽位(slot)编号,本例是0

附加属性

00 01 00 0F 00 00 00 02 00 10

00 01:标识附加属性数量为1
00 0F:引用#15
00 00 00 02:表示此属性的长度为2
00 10:表示引用了#10

文档

Java8虚拟机文档

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008825.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号