éåäººçŸ€ïŒ Javaå·¥çšåžãæ§èœè°äŒå·¥çšåžã奜å¥å®å®
éŸåºŠççº§ïŒ ââââ (äžé«çº§)
é 读æ¶éŽïŒ 20åé
æ¶çïŒ åœ»åºææå¯¹è±¡å åïŒäŒåå åå çšïŒé¢è¯å åïŒ
ð åŒèšïŒäžäžª"ç䌌ç®å"çé®é¢
public class User {
private int age;
private String name;
}
User user = new User();
é®é¢ïŒè¿äžªuser对象åšå åäžå å€å°åèïŒ
é项A: 4åèïŒint ageïŒ
é项B: 8åèïŒint + StringåŒçšïŒ
é项C: 16åèïŒå·®äžå€å§ïŒ
é项D: 32åèïŒéèŠå¯¹éœïŒ
æ£ç¡®çæ¡ïŒDïŒåš64äœJVMïŒåŒå¯æéå猩çæ
åµäžïŒ
ä»ä¹ïŒ32åèïŒè¿ä¹å€§ïŒð±
嫿¥ïŒä»å€©æä»¬å°±åè§£åéèäžæ ·ïŒæJava对象圻åºè§£åïŒççè¿32åèéœæ¯æä¹æ¥çïŒð¬
ðïž ç¬¬äžç« ïŒå¯¹è±¡çäžå±ç»æ
1.1 对象å ååžå±æ»è§ ðºïž
äžäžªJava对象åšå åäžçç»æå°±åäžäžªäžææ²»ð¥ªïŒ
âââââââââââââââââââââââââââââââââââââââ
â 对象倎 (Object Header) â â 第1å±ïŒæ è®°ä¿¡æ¯
â - Mark Word (8åè) â
â - Class Pointer (4åèïŒå猩å) â
âââââââââââââââââââââââââââââââââââââââ€
â å®äŸæ°æ® (Instance Data) â â 第2å±ïŒåæ®µæ°æ®
â - int age (4åè) â
â - String name (4åèïŒåŒçš) â
âââââââââââââââââââââââââââââââââââââââ€
â 对éœå¡«å
(Padding) â â 第3å±ïŒåæŽ
â - å¡«å
åè (12åè) â
âââââââââââââââââââââââââââââââââââââââ
æ»è®¡ïŒ8 + 4 + 4 + 4 + 12 = 32åè
çæŽ»æ¯å»ïŒ ðŠ
- 对象倎 = å¿«éçäžçæ çŸïŒè°å¯çãå¯å°åªãä»ä¹æ¶åå¯çïŒ
- å®äŸæ°æ® = å¿«éçéçå®é ç©åïŒäœ ä¹°çäžè¥¿ïŒ
- 对éœå¡«å = 泡沫填å ç©ïŒä¿è¯çå倧å°ç¬Šåè§æ ŒïŒ
ð¯ 第äºç« ïŒå¯¹è±¡å€Ž - èç倧ç§å¯ç"æ çŸ"
2.1 对象倎çç»æ ð·ïž
对象倎 = Mark Word + Class Pointer (+ Array Length)
(8åè) (4åè,å猩) (åŠææ¯æ°ç»,4åè)
2.2 Mark Word - 8åèéè£ äºå¥ïŒð€
Mark Wordæ¯äžäžªç¥å¥ç8åèïŒå å®¹äŒæ ¹æ®å¯¹è±¡ç¶æååïŒ
64äœJVMçMark Wordåžå±ïŒæ éç¶æïŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Mark Word (64 bits) â
ââââââââââââ¬âââââââââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââââââââââââââââââ€
â unused â hashCode âage â 0 â 0 â 0 â 1 â éæ å¿äœ â
â 25 bits â 31 bits â4äœ â1äœ â1äœ â1äœ â2äœ â â
ââââââââââââŽâââââââââââŽâââââŽâââââŽâââââŽâââââŽâââââââââââââââââââââââââ
â â â â
â â â ââ 01 = æ éç¶æ
â â ââ å代幎éŸïŒ0-15ïŒGCçžå
³ïŒ
â ââ hashCodeïŒè°çšhashCode()åçæïŒ
ââ æªäœ¿çšçäœ
Mark Wordçå€ç§åœ¢æ ð
å¯¹è±¡ç¶æäžåïŒMark Wordå
容就äžåïŒ
1ïžâ£ æ éç¶æ (001)
ââââââââââââ¬âââââââââââ¬âââââ¬ââââââ
â unused â hashCode âage â 001 â
ââââââââââââŽâââââââââââŽâââââŽââââââ
2ïžâ£ ååé (101)
âââââââââââââââââââââââ¬âââââ¬ââââââ
â 线çšID + Epoch âage â 101 â
âââââââââââââââââââââââŽâââââŽââââââ
3ïžâ£ 蜻é级é (00)
ââââââââââââââââââââââââââââ¬ââââââ
â æåæ äžéè®°åœçæé â 00 â
ââââââââââââââââââââââââââââŽââââââ
4ïžâ£ éé级é (10)
ââââââââââââââââââââââââââââ¬ââââââ
â æåMonitorçæé â 10 â
ââââââââââââââââââââââââââââŽââââââ
5ïžâ£ GCæ è®° (11)
ââââââââââââââââââââââââââââ¬ââââââ
â GCæ è®°ä¿¡æ¯ â 11 â
ââââââââââââââââââââââââââââŽââââââ
çæŽ»æ¯å»ïŒ ð·ïž Mark Wordå°±åäžäžª"æºèœæ çŸ"ïŒ
- å¹³æ¶æŸç€ºååä¿¡æ¯ïŒhashCodeã幎éŸïŒ
- 被人æ¿èµ·æ¶æŸç€º"è°åšçš"ïŒååéïŒ
- è¢«æ¢æ¶æŸç€º"éå®äž"ïŒèœ»é/éé级éïŒ
- èŠæææ¶æŸç€º"åŸ å€ç"ïŒGCæ è®°ïŒ
2.3 Class Pointer - æå"身仜è¯" ð
Class Pointer (ç±»åæé)
â
æå对象çClasså
æ°æ®
64äœJVMïŒ
- äžå猩ïŒ8åè
- å猩åïŒ4åè â
ïŒé»è®€åŒå¯ïŒ
åŒå¯æéå猩ïŒ
-XX:+UseCompressedOops (é»è®€åŒå¯)
å
³éæéå猩ïŒ
-XX:-UseCompressedOops
æéå猩çåç ðïž
䞺ä»ä¹èœå猩ïŒ
Java对象å°åéœæ¯8åè对éœçïŒ
å°åçå3äœæ°žè¿æ¯0ïŒ
åå§64äœå°åïŒ
0x0000 0000 1234 5000
^^^â è¿3äœæ°žè¿æ¯0ïŒ
å猩çç¥ïŒ
ååšæ¶ïŒå°å >> 3ïŒå³ç§»3äœïŒå»æå3䞪0ïŒ
è¯»åæ¶ïŒå°å << 3ïŒå·Šç§»3äœïŒè¡¥å3䞪0ïŒ
ç»æïŒ32äœå°±èœè¡šç€º 2^35 = 32GB çå°å空éŽïŒ
åŠæå > 32GBïŒæéå猩èªåšå€±æïŒ
2.4 æ°ç»é¿åºŠ - æ°ç»ç"ç¹æ" ð
åŠæå¯¹è±¡æ¯æ°ç»ïŒå¯¹è±¡å€Žå€4åèïŒ
æ®é对象ïŒ
âââââââââââââ¬ââââââââââââââ
â Mark Word â Class Ptr â
â 8åè â 4åè â = 12åè
âââââââââââââŽââââââââââââââ
æ°ç»å¯¹è±¡ïŒ
âââââââââââââ¬ââââââââââââââ¬ââââââââââ
â Mark Word â Class Ptr â Length â
â 8åè â 4åè â 4åè â = 16åè
âââââââââââââŽââââââââââââââŽââââââââââ
â
ââ æ°ç»é¿åºŠïŒintç±»åïŒ
ðš 第äžç« ïŒå®äŸæ°æ® - çæ£ç"莧ç©"
3.1 åºæ¬ç±»åå çšå€§å° ð
ââââââââââââ¬ââââââââââ¬âââââââââââââ
â ç±»å â å€§å° â ç€ºäŸ â
ââââââââââââŒââââââââââŒâââââââââââââ€
â boolean â 1åè â true/false â
â byte â 1åè â 127 â
â char â 2åè â 'A' â
â short â 2åè â 32767 â
â int â 4åè â 123456 â
â float â 4åè â 3.14f â
â long â 8åè â 123456789L â
â double â 8åè â 3.14159 â
â åŒçš â 4åè* â String ref â
ââââââââââââŽââââââââââŽâââââââââââââ
* åŒå¯æéå猩æ¶ïŒåŒçš4åèïŒåŠå8åè
3.2 åæ®µæåè§å ð¯
JVMäŒèªåšéæå段ïŒäŒåå ååžå±ïŒ
è§å1ïŒé¿åºŠçžåçåæ®µåé åšäžèµ· ð
public class Example {
private byte b1; // 1åè
private int i1; // 4åè
private byte b2; // 1åè
private int i2; // 4åè
}
// å®é
å
ååžå±ïŒJVMäŒååïŒïŒ
ââââââââââ¬âââââââââ¬âââââââââ¬âââââââââ
â i1 â i2 â b1 â b2 â
â 4åè â 4åè â 1åè â 1åè â
ââââââââââŽâââââââââŽâââââââââŽâââââââââ
â
ââ 4åèçæŸåé¢ïŒ1åèçæŸåé¢
è§å2ïŒç¶ç±»å段åšåïŒåç±»åæ®µåšå ðšâðŠ
class Parent {
private int parentField; // 4åè
}
class Child extends Parent {
private int childField; // 4åè
}
// å
ååžå±ïŒ
âââââââââââââââ¬ââââââââââ¬âââââââââââââ
â 对象倎 â parent â child â
â 12åè â Field â Field â
â â 4åè â 4åè â
âââââââââââââââŽââââââââââŽâââââââââââââ
è§å3ïŒåç±»åæ®µèŸçªæ¶å¯èœæå ¥ç¶ç±»å段éŽé ð§©
class Parent {
private long l; // 8åè
// è¿éæ4åèéŽé
}
class Child extends Parent {
private int i; // 4åè
}
// äŒååçåžå±ïŒ
âââââââââââââââ¬ââââââââââ¬ââââââââââ¬ââââââââââ
â 对象倎 â long l â int i â padding â
â 12åè â 8åè â 4åè â 4åè â
âââââââââââââââŽââââââââââŽââââââââââŽââââââââââ
â
ââ int i æå
¥äºéŽéïŒ
ð 第åç« ïŒå¯¹éœå¡«å - 区迫ççäžç
4.1 䞺ä»ä¹èŠ8åè对éœïŒð€
JVMè§å®ïŒå¯¹è±¡å€§å°å¿
é¡»æ¯8åèçåæ°ïŒ
åå ïŒ
1. CPU读åå
åæŽé«æïŒäžæ¬¡è¯»8åèïŒ
2. çŒåè¡å¯¹éœïŒCache LineïŒéåžž64åèïŒ
3. æéå猩çåæïŒå°åå3äœæ¯0ïŒ
䞟äŸïŒ
对象å®é
å€§å° â 对éœå倧å°
13åè â 16åè (å¡«å
3åè)
18åè â 24åè (å¡«å
6åè)
27åè â 32åè (å¡«å
5åè)
çæŽ»æ¯å»ïŒ ðŠ å°±åå¿«éç®±åªææ å尺寞ïŒå°ãäžã倧ãç¹å€§ïŒïŒäœ çäžè¥¿13cmïŒä¹åŸçš16cmçç®±åïŒå©äžç空éŽå¡æ³¡æ²«ïŒ
4.2 计ç®å¯¹éœå¡«å ð§®
å
¬åŒïŒ
对éœå¡«å
= (8 - (对象倎 + å®äŸæ°æ®) % 8) % 8
瀺äŸïŒ
对象倎ïŒ12åè
å®äŸæ°æ®ïŒ10åè
æ»è®¡ïŒ22åè
对éœå¡«å
= (8 - 22 % 8) % 8
= (8 - 6) % 8
= 2åè
æç»å€§å°ïŒ22 + 2 = 24åè â
ð¬ 第äºç« ïŒå®ææ¡äŸ - 计ç®å¯¹è±¡å€§å°
æ¡äŸ1ïŒç©ºå¯¹è±¡ - æå°ç对象 ð
public class Empty {
// 没æä»»äœå段
}
Empty obj = new Empty();
计ç®è¿çšïŒ
âââââââââââââââââââââââââââââââ
â 对象倎 (Mark Word) 8åè â
â ç±»åæé (å猩) 4åè â
â å®äŸæ°æ® 0åè â
â å°è®¡ 12åè â
â 对éœå¡«å
4åè â â åå€16åè
âââââââââââââââââââââââââââââââ€
â æ»è®¡ 16åè â â
âââââââââââââââââââââââââââââââ
空对象å 16åèïŒ
è¿æ¯Java对象çæå°å€§å°ïŒ
æ¡äŸ2ïŒåªæäžäžªintåæ®µ ð¢
public class OneInt {
private int value;
}
OneInt obj = new OneInt();
计ç®è¿çšïŒ
âââââââââââââââââââââââââââââââ
â 对象倎 12åè â
â int value 4åè â
â å°è®¡ 16åè â
â 对éœå¡«å
0åè â â å奜16åèïŒ
âââââââââââââââââââââââââââââââ€
â æ»è®¡ 16åè â â
âââââââââââââââââââââââââââââââ
æ¡äŸ3ïŒå€æå¯¹è±¡ ð
public class User {
private int age; // 4åè
private long id; // 8åè
private String name; // 4åèïŒåŒçšïŒ
private boolean active; // 1åè
}
User user = new User();
计ç®è¿çšïŒ
ââââââââââââââââââââââââââââââââââââ
â 对象倎 12åè â
ââââââââââââââââââââââââââââââââââââ€
â å®äŸæ°æ®ïŒJVMäŒååç顺åºïŒ: â
â long id 8åè â â 8åèåæ®µæŸåé¢
â int age 4åè â â 4åèåæ®µ
â String name (åŒçš) 4åè â
â boolean active 1åè â â 1åèåæ®µ
â (å
éšå¯¹éœ) 3åè â â åå€8çåæ°
ââââââââââââââââââââââââââââââââââââ€
â å°è®¡ 32åè â
â 对éœå¡«å
0åè â â å奜32åèïŒ
ââââââââââââââââââââââââââââââââââââ€
â æ»è®¡ 32åè â â
ââââââââââââââââââââââââââââââââââââ
æ¡äŸ4ïŒæ°ç»å¯¹è±¡ ð
int[] array = new int[3];
计ç®è¿çšïŒ
ââââââââââââââââââââââââââââââââââââ
â 对象倎 (Mark Word) 8åè â
â ç±»åæé (å猩) 4åè â
â æ°ç»é¿åºŠ 4åè â â æ°ç»ç¹æïŒ
ââââââââââââââââââââââââââââââââââââ€
â æ°ç»æ°æ®: â
â int[0] 4åè â
â int[1] 4åè â
â int[2] 4åè â
ââââââââââââââââââââââââââââââââââââ€
â å°è®¡ 28åè â
â 对éœå¡«å
4åè â â åå€32åè
ââââââââââââââââââââââââââââââââââââ€
â æ»è®¡ 32åè â â
ââââââââââââââââââââââââââââââââââââ
å
¬åŒïŒ
æ°ç»å€§å° = 16 (对象倎) + å
çŽ å€§å° Ã æ°ç»é¿åºŠ + 对éœå¡«å
= 16 + 4 Ã 3 + 4
= 32åè
æ¡äŸ5ïŒå è£ ç±»å - æäººçåŒéïŒð±
Integer i = new Integer(123);
Integer对象å éšç»æïŒ
public final class Integer {
private final int value; // 4åè
// ...
}
计ç®è¿çšïŒ
ââââââââââââââââââââââââââââââââââââ
â 对象倎 12åè â
â int value 4åè â
â å°è®¡ 16åè â
â 对éœå¡«å
0åè â
ââââââââââââââââââââââââââââââââââââ€
â æ»è®¡ 16åè â â
ââââââââââââââââââââââââââââââââââââ
éæïŒ
- intïŒ 4åè
- IntegerïŒ 16åèïŒ4ååŒéïŒïŒ
1亿䞪int: 400MB
1亿䞪Integer: 1.6GB (4åå
åïŒ)
ð 第å ç« ïŒå åäŒåæå·§
æå·§1ïŒåçéæ©æ°æ®ç±»å ð¯
// â æµªè޹å
å
public class User {
private Long id; // 16åèïŒå¯¹è±¡ïŒ
private Integer age; // 16åèïŒå¯¹è±¡ïŒ
private Boolean active; // 16åèïŒå¯¹è±¡ïŒ
}
// æ¯äžªUser对象ïŒ12 + 16Ã3 = 60åèïŒå®äŸæ°æ®ïŒ
// â
èçå
å
public class User {
private long id; // 8åèïŒåºæ¬ç±»åïŒ
private int age; // 4åè
private boolean active; // 1åè
}
// æ¯äžªUser对象ïŒ12 + 13 = 25åè â 对éœå32åè
èçïŒ60 - 32 = 28åè (46%çèçïŒ)
æå·§2ïŒå段顺åºäŒå ð§©
// â æªäŒåïŒæµªèŽ¹ç©ºéŽïŒ
public class BadLayout {
private byte b1; // 1åè
private long l1; // 8åè
private byte b2; // 1åè
private long l2; // 8åè
}
// å
ååžå±ïŒ
ââââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ
â b1 âpad âpad âpad âpad âpad âpad âpad â
ââââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââ€
â l1 (8åè) â
ââââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ€
â b2 âpad âpad âpad âpad âpad âpad âpad â
ââââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââ€
â l2 (8åè) â
ââââââââââââââââââââââââââââââââââââââââââ
// 浪莹äº14åèpaddingïŒ
// â
äŒååïŒçާåïŒ
public class GoodLayout {
private long l1; // 8åè
private long l2; // 8åè
private byte b1; // 1åè
private byte b2; // 1åè
}
// å
ååžå±ïŒ
ââââââââââââââââââââââââââââââââââââââââââ
â l1 (8åè) â
ââââââââââââââââââââââââââââââââââââââââââ€
â l2 (8åè) â
ââââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ¬âââââ€
â b1 â b2 âpad âpad âpad âpad âpad âpad â
ââââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââŽâââââ
// åªæµªè޹6åèpaddingïŒ
èçïŒ14 - 6 = 8åè
ååïŒå€§å段åšåïŒå°å段åšåïŒ
æå·§3ïŒé¿å äžå¿ èŠç对象å建 â»ïž
// â å建倧é䞎æ¶å¯¹è±¡
public String process(List<Integer> numbers) {
String result = "";
for (Integer num : numbers) {
result += num.toString(); // æ¯æ¬¡åŸªç¯å建æ°StringïŒ
}
return result;
}
// 1000䞪æ°å â å建1000+䞪String对象ïŒ
// â
䜿çšStringBuilderå€çš
public String process(List<Integer> numbers) {
StringBuilder sb = new StringBuilder();
for (Integer num : numbers) {
sb.append(num);
}
return sb.toString();
}
// åªå建1䞪StringBuilderïŒ
æå·§4ïŒäœ¿çšæ°ç»ä»£æ¿éåïŒç¹å®åºæ¯ïŒ ð
// åºæ¯ïŒååš100äžäžªint
// â 䜿çšArrayList<Integer>
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1_000_000; i++) {
list.add(i);
}
// å
åå çšïŒ
// Integer对象ïŒ1,000,000 à 16åè = 16MB
// æ°ç»ïŒ 1,000,000 à 4åè = 4MB
// ArrayListæ¬èº«ïŒçºŠ40åè
// æ»è®¡ïŒçºŠ20MB
// â
䜿çšint[]
int[] array = new int[1_000_000];
for (int i = 0; i < 1_000_000; i++) {
array[i] = i;
}
// å
åå çšïŒ
// 对象倎ïŒ16åè
// æ°æ®ïŒ 1,000,000 à 4åè = 4MB
// æ»è®¡ïŒçºŠ4MB
èçïŒ20MB - 4MB = 16MB (80%çèçïŒ)
ð ïž ç¬¬äžç« ïŒå·¥å ·å®æ - 粟确计ç®å¯¹è±¡å€§å°
å·¥å ·1ïŒJOL (Java Object Layout) ð§
ææåšç对象åžå±åæå·¥å ·ïŒ
1. æ·»å äŸèµ
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.17</version>
</dependency>
2. 䜿çšç€ºäŸ
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;
public class ObjectSizeDemo {
public static void main(String[] args) {
// æ¥çVMä¿¡æ¯
System.out.println(VM.current().details());
// åæUser对象
User user = new User();
System.out.println(ClassLayout.parseInstance(user).toPrintable());
}
}
class User {
private int age;
private long id;
private String name;
private boolean active;
}
3. èŸåºç»æ
User object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) N/A
8 4 (object header: class) N/A
12 4 int User.age N/A
16 8 long User.id N/A
24 4 String User.name N/A
28 1 boolean User.active N/A
29 3 (object alignment gap)
Instance size: 32 bytes
Space losses: 0 bytes internal + 3 bytes external = 3 bytes total
å®çŸïŒåæä»¬æå·¥è®¡ç®çäžèŽïŒ â
å·¥å ·2ïŒInstrumentation API ð
JVMåçAPIïŒç²Ÿç¡®è®¡ç®ïŒ
import java.lang.instrument.Instrumentation;
public class ObjectSizeAgent {
private static Instrumentation inst;
// JVMå¯åšæ¶è°çš
public static void premain(String args, Instrumentation instP) {
inst = instP;
}
// 计ç®å¯¹è±¡å€§å°
public static long sizeOf(Object obj) {
return inst.getObjectSize(obj);
}
}
// 䜿çš
public class Test {
public static void main(String[] args) {
User user = new User();
long size = ObjectSizeAgent.sizeOf(user);
System.out.println("User对象倧å°ïŒ" + size + " åè");
}
}
// è¿è¡æ¶æ·»å åæ°ïŒ
// java -javaagent:agent.jar -jar app.jar
å·¥å ·3ïŒVisualVM + Memory Analyzer ð
å¯è§ååæå·¥å ·ïŒ
æ¥éª€ïŒ
1. å¯åšVisualVM
2. è¿æ¥å°Javaè¿çš
3. çæHeap Dump
4. æ¥çHistogramïŒçŽæ¹åŸïŒ
5. æ¥çæ¯äžªå¯¹è±¡çShallow SizeïŒæµ
å ïŒåRetained SizeïŒæ·±å ïŒ
ð ç¬¬å «ç« ïŒé¢è¯åžžèç¥è¯ç¹
é¢è¯é¢1ïŒå¯¹è±¡å€§å°è®¡ç® ð
é¢ç®ïŒä»¥äžå¯¹è±¡åå å€å°åèïŒïŒ64äœJVMïŒæéå猩åŒå¯ïŒ
1. Object obj = new Object();
çæ¡ïŒ16åè
è§£æïŒå¯¹è±¡å€Ž12åè + å®äŸæ°æ®0åè + 对éœ4åè = 16åè
2. int[] arr = new int[10];
çæ¡ïŒ56åè
è§£æïŒå¯¹è±¡å€Ž16åè + æ°æ®40åè + 对éœ0åè = 56åè
3. String str = new String("hello");
çæ¡ïŒString对象24åè + char[]对象40åè = 64åè
(JDK 8ïŒå笊æ°ç»åç¬ååš)
4. Integer i = 127;
çæ¡ïŒ0åèïŒäœ¿çšçŒåæ± ïŒïŒ
è§£æïŒ-128å°127äŒäœ¿çšIntegerCacheïŒäžäŒå建æ°å¯¹è±¡
é¢è¯é¢2ïŒæéå猩 ðïž
é¢ç®ïŒä»ä¹æ¯æéå猩ïŒäžºä»ä¹èœå猩ïŒ
çæ¡ïŒ
1. é»è®€åŒå¯ïŒ-XX:+UseCompressedOops
2. åçïŒå¯¹è±¡å°å8åè对éœïŒå3äœæ°žè¿æ¯0ïŒå¯ä»¥çç¥
3. å猩åïŒ4åèèœè¡šç€º32GBå°å空éŽ
4. å€±ææ¡ä»¶ïŒå > 32GB
5. ææïŒèç20-30%å
å
é¢è¯å å项ïŒ
- 诎åºå
·äœçåçŒ©ç®æ³ïŒå³ç§»3äœïŒ
- 诎åº32GBç计ç®è¿çšïŒ2^32 à 2^3 = 2^35 = 32GBïŒ
- ç¥éè¿æç±»æéå猩ïŒ-XX:+UseCompressedClassPointersïŒ
é¢è¯é¢3ïŒäžºä»ä¹èŠ8åè对éœïŒð€
çæ¡ïŒåå±åçïŒïŒ
åºç¡åçïŒ
- JVMè§å®å¯¹è±¡å€§å°å¿
é¡»æ¯8åèçåæ°
- æåCPU读åæç
è¿é¶åçïŒ
1. CPUçŒåè¡å¯¹éœïŒCache LineïŒ64åèïŒ
2. æéå猩çåæïŒå°åå3äœäžº0ïŒ
3. åå°å
åç¢ç
4. ç®åå
å管ç
é«çº§åçïŒ
- ç°ä»£CPU读åå
åéœæ¯æå读åïŒéåžž64åèïŒ
- åŠæå¯¹è±¡è·šè¶äž€äžªåïŒéèŠè¯»äž€æ¬¡ïŒæçäœ
- 8åèå¯¹éœæ¯64åèç纊æ°ïŒæ¹äŸ¿ç®¡ç
- TLABïŒThread Local Allocation BufferïŒä¹å©çšäºå¯¹éœ
ð¡ æ»ç»ïŒæ žå¿ç¥è¯ç¹
ð¯ äžå¥è¯æ»ç»
Java对象 = 对象倎(12-16åè) + å®äŸæ°æ®(åæ®µæ»å) + 对éœå¡«å (åå€8çåæ°)
ð å ³é®æ°å
对象倎倧å°ïŒ
- æ®é对象ïŒ12åè (64äœJVMïŒæéå猩)
- æ°ç»å¯¹è±¡ïŒ16åè (å€äº4åèæ°ç»é¿åºŠ)
æå°å¯¹è±¡ïŒ16åè (空对象)
åºæ¬ç±»åïŒ
- boolean/byte: 1åè
- char/short: 2åè
- int/float: 4åè
- long/double: 8åè
- åŒçš: 4åè (å猩) / 8åè (äžå猩)
对éœïŒ8åèçåæ°
ð äŒå建议
â
DOïŒ
- 䜿çšåºæ¬ç±»å代æ¿å
è£
ç±»
- 倧忮µåšåïŒå°å段åšå
- é¿å
äžå¿
èŠç对象å建
- åç䜿çšå¯¹è±¡æ±
â DON'TïŒ
- 滥çšå
è£
ç±»ïŒIntegerãLongçïŒ
- éæå®ä¹å段顺åº
- åšåŸªç¯äžé¢ç¹å建对象
- è¿åºŠå°è£
å°å¯¹è±¡
ð ç»è¯
æåäœ ïŒð äœ å·²ç»åœ»åºææ¡äºïŒ
- â 对象å åçäžå±ç»æïŒå¯¹è±¡å€Žãå®äŸæ°æ®ã对éœå¡«å ïŒ
- â Mark Wordçç§å¯åæéå猩åç
- â 粟确计ç®å¯¹è±¡å€§å°çæ¹æ³
- â å åäŒåç4倧æå·§
- â 䜿çšJOLçå·¥å ·åæå¯¹è±¡åžå±
äžæ¬¡é¢è¯è¢«é®å°"äžäžªå¯¹è±¡å å€å°åè"ïŒäœ äžä» èœç®åºæ¥ïŒè¿èœè®²æž æ¥äžºä»ä¹ïŒçè³èœç»åºäŒå建议ïŒð
è®°äœè¿äžªå ¬åŒïŒ
å¯¹è±¡å€§å° = 对象倎 + å®äŸæ°æ® + 对éœå¡«å
= 12/16 + ΣFields + Padding(8çåæ°)
ð æ©å±é 读
- ãæ·±å ¥çè§£Javaèææºã第2ç« - 对象å ååžå±
- JOLå·¥å ·å®æ¹ææ¡£
- OpenJDKæºç - markOop.hpp
ðª æ¿äœ ååºçæ¯äžªå¯¹è±¡éœçާåé«æïŒ ð
æåæŽæ°ïŒ 2025幎10æ
äœè ïŒ AI婿ïŒçšâ€ïžåâåäœïŒ
äžäžç¯é¢åïŒ ãåŠäœå®ç°äžäžªåç¡®çJava对象倧å°è®¡ç®å·¥å ·ïŒã