当前位置:网站首页>[100 cases of JVM tuning practice] 04 - Method area tuning practice (Part 1)
[100 cases of JVM tuning practice] 04 - Method area tuning practice (Part 1)
2022-07-07 01:00:00 【Half old 518】
front said
Author's brief introduction : Half old 518, Long distance runner , Determined to persist in writing 10 Blog of the year , Focus on java Back end
Column Introduction : Case driven introduction JVM knowledge , Teach you how to use JVM Troubleshooting 、 Evaluation code 、 Optimize performance
The article brief introduction : Introduce the concept of method area 、 Help you understand constant pool 、String table Adjustment
List of articles
7. Method area
7.1 Definition
The method area is java Shared area shared by all threads in the virtual machine , It mainly stores information about the structure of classes ( Member variables , Method 、 Constructor code ), Runtime constant pool , Class loader . The method area is created when the virtual machine is started , Logically, it is part of the heap ( Specific manufacturers may not follow the logical division standard when implementing ).
stay jdk1.8 before , The method area is located in jvm Permanent generation of , The string is stored in the constant pool . stay jdk1.8 in the future , The method area is located in the meta space of local memory , No longer occupy JVM Of memory space , The string exists in the heap . Refer to the following figure for details. .
Tip:
Method area is actually a logical concept , Because you can find , stay jdk1.8 in the future , It is even split in physical storage space .
7.2 Method area memory overflow
The following code can demonstrate the method area memory overflow .
public class Demo1_8 extends ClassLoader { // Binary bytecode that can be used to load classes
public static void main(String[] args) {
int j = 0;
try {
Demo1_8 test = new Demo1_8();
for (int i = 0; i < 10000; i++, j++) {
// ClassWriter The function is to generate the binary bytecode of a class
ClassWriter cw = new ClassWriter(0);
// Parameter meaning : Version number , The access level is public, Class name , Package name , Parent class , Interface
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
// return byte[]
byte[] code = cw.toByteArray();
// Class loading is performed
test.defineClass("Class" + i, code, 0, code.length); // Class object
}
} finally {
System.out.println(j);
}
}
}
stay jdk1.8 Previous versions , Set the permanent generation to 8m: -XX:MaxPermSize=10m
, stay jdk1.8 in the future , Set the meta space to 8m: -XX:MaxMetaspaceSize=8m
, It will be reported OutOfMemoryError
.
In the actual work scenario ,spring、mybatis And other frameworks are used cglib To generate dynamically class, Therefore, improper use of the framework may lead to memory overflow in the method area . But in the jdk1.8 Later, the method area is moved to the meta space , Plenty of space , Garbage collection is also carried out by meta space , The possibility of memory overflow is reduced .
7.3 Constant pool
Here's a helloworld Code for .
// Binary bytecode ( Class basic information , Constant pool , Class method definition , Contains virtual machine instructions )
public class HelloWorld {
public static void main(String[] args) {
System.out.println("hello world");
}
}
The computer will eventually convert this code into binary code and execute , This binary code contains the basic information of the class 、 Class method definition ( Contains instructions )、 Constant pool . Let's switch to out The corresponding class File directory , Use the decompile command javap -v xxx.class
Turn the contents of binary code into readable code to find out .
Classfile /F:/ Information Decrypt JVM/ Code /jvm/out/production/jvm/cn/itcast/jvm/t5/helloworld.class
Last modified 2021 year 9 month 9 Japan ; size 567 bytes
SHA-256 checksum 37204bf6e654f64ae56660a1e8becfaa98b3ae7592b81b4b6e331de92a460b96
Compiled from "HelloWorld.java"
public class cn.itcast.jvm.t5.HelloWorld
minor version: 0
major version: 52
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #5 // cn/itcast/jvm/t5/HelloWorld
super_class: #6 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #6.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #21.#22 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #23 // hello world
#4 = Methodref #24.#25 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #26 // cn/itcast/jvm/t5/HelloWorld
#6 = Class #27 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcn/itcast/jvm/t5/HelloWorld;
#14 = Utf8 main
#15 = Utf8 ([Ljava/lang/String;)V
#16 = Utf8 args
#17 = Utf8 [Ljava/lang/String;
#18 = Utf8 SourceFile
#19 = Utf8 HelloWorld.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = Class #28 // java/lang/System
#22 = NameAndType #29:#30 // out:Ljava/io/PrintStream;
#23 = Utf8 hello world
#24 = Class #31 // java/io/PrintStream
#25 = NameAndType #32:#33 // println:(Ljava/lang/String;)V
#26 = Utf8 cn/itcast/jvm/t5/HelloWorld
#27 = Utf8 java/lang/Object
#28 = Utf8 java/lang/System
#29 = Utf8 out
#30 = Utf8 Ljava/io/PrintStream;
#31 = Utf8 java/io/PrintStream
#32 = Utf8 println
#33 = Utf8 (Ljava/lang/String;)V
{
public cn.itcast.jvm.t5.HelloWorld();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 4: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcn/itcast/jvm/t5/HelloWorld;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String hello world
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
}
SourceFile: "HelloWorld.java"
Above , The constant pool is a constant table . Notice the method definition part, such as #2
The content such as , This actually corresponds to the constant pool ( surface )Constant pool
The constant .
The constant pool is .class In the document , When the class is loaded , The contents of the constant pool will be put into the runtime constant pool , And the symbolic address will become the real address .
7.4 String table
Let's look at an interview question .
String s1 = "a";
String s2 = "b";
String s3 = "ab";
String s4 = s1 + s2;
String s5 = "a" + "b";
System.out.println(s3 == s4);
System.out.println(s3 == s4);
Answer that question , It needs to be made clear string table, Let's start with the simplest , Decompile the following code .
public class Demo1_22 {
public static void main(String[] args) {
String s1 = "a"; // Lazy
String s2 = "b";
String s3 = "ab";
}
}
Interception part . You can see jvm from #2
take String a It's in storage LocalVariableTable
Of Slot1, Other strings are similar .
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=4, args_size=1
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: ldc #4 // String ab
8: astore_3
9: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 6
line 21: 9
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 args [Ljava/lang/String;
3 7 1 s1 Ljava/lang/String;
6 4 2 s2 Ljava/lang/String;
9 1 3 s3 Ljava/lang/String;
stay jvm Startup time , The contents of the constant pool are loaded into the runtime constant pool , But at this time a,b,ab It's just a symbol , Instead of string objects . Only when specific instructions are executed , Such as 0: ldc #2
Will create a string object "a". At the same time ,jvm Still going String table[]
Find out if there is "a" This string , If not, add it to String table[]
. notes :String table[] It's actually hashtable structure , It can't be expanded .
stay java New in the code s4, And decompile .
String s4 = s1 + s2;
The result of decompilation is as follows .
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: astore 4
The above operation is equivalent to .
new StringBuilder().append("a").append("b").toString()
among toString()
The implementation of the method is :new String("ab")
. therefore s3 == s4 As the result of the fasle.
System.out.println(s3 == s4); //false
Then we add... To the code s5.
String s5 = "a" + "b";
The result of decompilation is as follows .
29: ldc #4 // String ab
31: astore 5
original ,javac Compile time helps us optimize , It thinks “a”,“b” Is a constant , The result is unlikely to change , So the result is directly determined as ab 了 . also , because "ab" stay String table There is already , So no new string objects will be created .
System.out.println(s3 == s4); //true
intern() Method can put the string object in the heap into the string , Refer to the following code .
public class Demo1_23 {
// String table["ab", "a", "b"]
public static void main(String[] args) {
String x = "ab";
String s = new String("a") + new String("b"); // Pile up new String("a") new String("b") new String("ab")
String s2 = s.intern();// Try to put this string object into the string pool , If there is one, it will not put , If not, put it into the string pool , Will return the objects in the string pool
System.out.println( s2 == x); //true,s2 And x Are all objects in the string pool
System.out.println( s == x ); //false,s It's objects in the heap , Different from the objects in the string pool
}
}
This is the case x2 You can successfully join the string pool , So the result is true.
String x2 = new String("c") + new String("d"); // new String("cd")
x2.intern();
String x1 = "cd";
System.out.println(x1 == x2); //true
however jdk1.6 Call in intern() Method , Will try to put the string into the string pool , If so, it will not be put in , If not, a copy will be copied and put into the string pool , therefore , The object in the string pool is not the same object as the object in the heap . The same code above again jdk1.6 in x1 == x2
return false.
The characteristics of string pool are summarized as follows .
7.5 String table The location of
stay jdk1.6,string table Put in constant pool , The constant pool is located in the method area of the permanent generation . Permanent generation only full gc Only when triggered will it be recycled , This leads to string table The recovery efficiency of is low .jdk1.7 take string table Moved to the pile .
7.6 String table The garbage collection of
Refer to the following code to configure parameters and run .
/**
* demonstration StringTable Garbage collection
* -Xmx10m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc
*/
public class Demo1_7 {
public static void main(String[] args) throws InterruptedException {
int i = 0;
try {
for (int j = 0; j < 100000; j++) { // j=100, j=10000
String.valueOf(j).intern();
i++;
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
System.out.println(i);
}
}
}
The printed information is as follows
[GC (Allocation Failure) [PSYoungGen: 2048K->488K(2560K)] 2048K->875K(9728K), 0.0028226 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 2536K->512K(2560K)] 2923K->958K(9728K), 0.0039494 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 2560K->512K(2560K)] 3006K->1006K(9728K), 0.0020900 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
...
StringTable statistics:
Number of buckets : 60013 = 480104 bytes, avg 8.000
Number of entries : 26231 = 629544 bytes, avg 24.000
Number of literals : 26231 = 1548152 bytes, avg 59.020
Total footprint : = 2657800 bytes
Average bucket size : 0.437
Variance of bucket size : 0.418
Std. dev. of bucket size: 0.646
Maximum bucket size : 4
string table The bottom is hashtable, Data is stored in the form of array and linked list , You can see that the number of buckets for storing strings is 60013 individual , The number of strings is 26231 individual . The number of strings we actually create is 10 0000 individual , Why does the printed quantity not match ? According to the printed information , It's because it triggered GC operation .
7.7 String table tuning
string table The essence is hashtable, and hashtable The performance of is closely related to the number of barrels , about string table Tuning is actually about hashtable Adjust the number of barrels .
/**
* Demonstrate the impact of string pool size on performance
* -XX:+PrintStringTableStatistics
*/
public class Demo1_24 {
public static void main(String[] args) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if (line == null) {
break;
}
line.intern();
}
System.out.println("cost:" + (System.nanoTime() - start) / 1000000);
}
}
}
Configure and run the above code , The printed information is as follows .
cost:439
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, avg 8.000
Number of entries : 13697 = 328728 bytes, avg 24.000
Number of literals : 13697 = 609024 bytes, avg 44.464
Total footprint : = 1097840 bytes
Average bucket size : 0.684
Variance of bucket size : 0.684
Std. dev. of bucket size: 0.827
Maximum bucket size : 6
StringTable statistics:
Number of buckets : 60013 = 480104 bytes, avg 8.000
Number of entries : 481494 = 11555856 bytes, avg 24.000
Number of literals : 481494 = 29750344 bytes, avg 61.788
Total footprint : = 41786304 bytes
Average bucket size : 8.023
Variance of bucket size : 8.084
Std. dev. of bucket size: 2.843
Maximum bucket size : 23
Configuration parameters -XX:StringTableSize=200000
, The printed information is as follows .
cost:393
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, avg 8.000
Number of entries : 13697 = 328728 bytes, avg 24.000
Number of literals : 13697 = 609024 bytes, avg 44.464
Total footprint : = 1097840 bytes
Average bucket size : 0.684
Variance of bucket size : 0.684
Std. dev. of bucket size: 0.827
Maximum bucket size : 6
StringTable statistics:
Number of buckets : 200000 = 1600000 bytes, avg 8.000
Number of entries : 481494 = 11555856 bytes, avg 24.000
Number of literals : 481494 = 29750344 bytes, avg 61.788
Total footprint : = 42906200 bytes
Average bucket size : 2.407
Variance of bucket size : 2.420
Std. dev. of bucket size: 1.556
Maximum bucket size : 12
Configuration parameters -XX:StringTableSize=1009
, The printed information is as follows .
cost:4870
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, avg 8.000
Number of entries : 16327 = 391848 bytes, avg 24.000
Number of literals : 16327 = 698456 bytes, avg 42.779
Total footprint : = 1250392 bytes
Average bucket size : 0.816
Variance of bucket size : 0.811
Std. dev. of bucket size: 0.901
Maximum bucket size : 6
StringTable statistics:
Number of buckets : 1009 = 8072 bytes, avg 8.000
Number of entries : 482764 = 11586336 bytes, avg 24.000
Number of literals : 482764 = 29845512 bytes, avg 61.822
Total footprint : = 41439920 bytes
Average bucket size : 478.458
Variance of bucket size : 432.042
Std. dev. of bucket size: 20.786
Maximum bucket size : 547
You can find , When there are more barrels , The likelihood of hash conflicts will be reduced , This will take less time to enter the pool .
Why use string table To store strings ? Because it saves space , Avoid duplicate creation of string objects . Spread on the Internet twitter The user information stored in the contains address items , If not used string table Storage , Need about 30G Memory , However, these addresses may contain a large number of duplicate addresses , Maybe many users are from Zhongguancun, Beijing , therefore twitter Pool address information , from string table Create storage , Reduce this memory space to tens of M.
Feel this process through the following examples .
/**
* demonstration intern Reduce memory usage
* -XX:StringTableSize=200000 -XX:+PrintStringTableStatistics
* -Xsx500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=200000
*/
public class Demo1_25 {
public static void main(String[] args) throws IOException {
List<String> address = new ArrayList<>();
System.in.read();
for (int i = 0; i < 10; i++) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if(line == null) {
break;
}
address.add(line);
}
System.out.println("cost:" +(System.nanoTime()-start)/1000000);
}
}
System.in.read();
}
}
Before typing on the keyboard , There is no data read operation , After typing, the data is read and stored in address in . At these two time nodes jvisualvm in sampler Take samples . give the result as follows .
Modify the code address.add()
address.add(line.intern());
边栏推荐
- 【JVM调优实战100例】05——方法区调优实战(下)
- Trace tool for MySQL further implementation plan
- 接口(接口相关含义,区别抽象类,接口回调)
- Advanced learning of MySQL -- basics -- multi table query -- external connection
- Link sharing of STM32 development materials
- Summary of being a microservice R & D Engineer in the past year
- 迈动互联中标北京人寿保险,助推客户提升品牌价值
- Attention SLAM:一種從人類注意中學習的視覺單目SLAM
- Stm32f407 ------- SPI communication
- Dell Notebook Periodic Flash Screen Fault
猜你喜欢
Slam d'attention: un slam visuel monoculaire appris de l'attention humaine
英雄联盟|王者|穿越火线 bgm AI配乐大赛分享
Deep understanding of distributed cache design
学习光线跟踪一样的自3D表征Ego3RT
Lombok makes ⽤ @data and @builder's pit at the same time. Are you hit?
[C language] dynamic address book
Memory optimization of Amazon memorydb for redis and Amazon elasticache for redis
ActiveReportsJS 3.1中文版|||ActiveReportsJS 3.1英文版
Part IV: STM32 interrupt control programming
threejs图片变形放大全屏动画js特效
随机推荐
Data sharing of the 835 postgraduate entrance examination of software engineering in Hainan University in 23
详解OpenCV的矩阵规范化函数normalize()【范围化矩阵的范数或值范围(归一化处理)】,并附NORM_MINMAX情况下的示例代码
A brief history of deep learning (I)
Lombok 同时使⽤ @Data 和 @Builder 的坑,你中招没?
Telerik UI 2022 R2 SP1 Retail-Not Crack
Dr selection of OSPF configuration for Huawei devices
学习光线跟踪一样的自3D表征Ego3RT
ActiveReportsJS 3.1中文版|||ActiveReportsJS 3.1英文版
【软件逆向-自动化】逆向工具大全
[牛客] [NOIP2015]跳石头
【JokerのZYNQ7020】AXI_ EMC。
[software reverse - solve flag] memory acquisition, inverse transformation operation, linear transformation, constraint solving
What is time
批量获取中国所有行政区域经边界纬度坐标(到县区级别)
Leetcode(547)——省份数量
「精致店主理人」青年创业孵化营·首期顺德场圆满结束!
New feature of Oracle 19C: automatic DML redirection of ADG, enhanced read-write separation -- ADG_ REDIRECT_ DML
Chenglian premium products has completed the first step to enter the international capital market by taking shares in halber international
以机房B级建设标准满足等保2.0三级要求 | 混合云基础设施
Distributed cache