สตริงมีหน่วยความจำจำนวนมากในแอปพลิเคชันใด ๆ โดยเฉพาะอย่างยิ่งอาร์เรย์ถ่าน [] ที่มีตัวละคร UTF-16 อิสระมีส่วนช่วยในการบริโภคหน่วยความจำ JVM เนื่องจากตัวละครแต่ละตัวมีหลัก 2 หลัก
30%ของหน่วยความจำเป็นเรื่องธรรมดามากไม่เพียงเพราะสตริงเป็นรูปแบบที่ดีที่สุดสำหรับเรา แต่ยังเป็นเพราะ HTTP API ยอดนิยมใช้สตริงจำนวนมาก การใช้ Java 8 Update 20 ตอนนี้เราสามารถติดต่อคุณลักษณะใหม่ที่เรียกว่า String to Go Heavy
สตริงถูกนำมาใช้ใหม่เพื่อใช้การใช้ภายในของสตริงเป็นอาร์เรย์ถ่านและคุณลักษณะของสุดท้ายดังนั้น JVM จึงสามารถจัดการกับพวกเขาได้โดยพลการ
นักพัฒนาพิจารณากลยุทธ์จำนวนมากสำหรับสตริงสตริง แต่การใช้งานขั้นสุดท้ายใช้ในการดำเนินการขั้นสุดท้าย:
เมื่อใดก็ตามที่อุปกรณ์การกู้คืนขยะเข้าถึงวัตถุสตริงมันจะทำเครื่องหมายอาร์เรย์ถ่าน มันได้รับค่าแฮชของอาร์เรย์ถ่านและที่มีอยู่โดยมีการอ้างอิงที่อ่อนแอไปยังอาร์เรย์ ตราบใดที่เครื่องร่อนของการกลับมาพบสตริงอื่นและสตริงนี้และอาร์เรย์ถ่านมีรหัสแฮชเดียวกันจากนั้นทั้งสองจะถูกเปรียบเทียบกับตัวละครหนึ่งตัวและตัวละครหนึ่งตัว
หากพวกเขาจับคู่สตริงจะถูกแก้ไขโดยชี้ไปที่อาร์เรย์ถ่านของสตริงที่สอง อาร์เรย์ถ่านแรกไม่ได้อ้างถึงอีกต่อไปดังนั้นจึงสามารถรีไซเคิลได้
แน่นอนกระบวนการทั้งหมดนี้นำมาซึ่งค่าใช้จ่ายบางอย่าง แต่ถูกควบคุมโดยขีด จำกัด สูงสุดที่แน่นมาก ตัวอย่างเช่นหากไม่พบตัวละครซ้ำ ๆ มันจะไม่ถูกตรวจสอบอีกต่อไปเป็นระยะเวลาหนึ่ง
คุณสมบัตินี้ทำงานอย่างไร? ก่อนอื่นคุณต้องเปิดตัว Java 8 Update 20 จากนั้นติดตามการกำหนดค่านี้: -xmx256m -xx:+useg1gc เพื่อเรียกใช้รหัสต่อไปนี้:
Public Class LoteOfStrings {Private Static Final LinkedList <String> LOTE_OF_STRINGS = ใหม่ LinkedList <() (); j = 0; );}}}
รหัสนี้จะถูกรายงานไปยัง OutofMemoryError หลังจากการทำซ้ำ 30 ครั้ง
ตอนนี้เปิดสตริงเพื่อให้หนักใช้การกำหนดค่าต่อไปนี้เพื่อเรียกใช้รหัสด้านบน:
-xmx256m -xx:+useg1gc -xx:+usestringdeduplication -xx:+printstringuplicationStator
ในเวลานี้มันสามารถทำงานได้นานขึ้นและมันจะสิ้นสุดหลังจากการวนซ้ำ 50 ครั้งเท่านั้น
JVM ยังพิมพ์สิ่งที่ได้ทำมาดูกันเถอะ:
[GC พร้อมกัน-สตริงการเติมเงิน, 4658.2K-> 0.0B (4658.2K), AVG 99.6%, 0.0165023 วินาที] [EXEC ครั้งสุดท้าย: 0.0165023 วินาที, ไม่ได้ใช้งาน: 0.0953764 วินาที: บล็อก: 0/0.00000 [SKIPPD: 0 (0.0%)] [Hashed: 119538 (100.0%)] [รู้จัก: 0 (0.0%)] [ใหม่: 119538 (100.0%) 4658.2K] [deduplicated: 119538 (100.0%) 4658.2K .0.0] [Young: 372 (0.3%) 14.5K (0.3%)] [เก่า: 119166 (99.7%) 4643.8K (99.7%)] [รวมทั้งหมด: 4/0.0802259 วินาที : 0/0.0000000 วินาที] [ตรวจสอบ: 557503] [ข้าม: 0 (0.0%)] [แฮชเด็ด: 556191 (99.8%)] [รู้จัก: 903 (0.2%)] [ใหม่: 556600 (99.8%) 21.2m] [ deduplicated: 554727 (99.7%) 21.1m (99.6%)] [Young: 1101 (0.2%) 43.0k (0.2%)] [เก่า: 553626 (99.8%) 21.1m (99.8%)] [ตาราง] : 81.1K] [ขนาด: 2048, ขั้นต่ำ: 1024, สูงสุด: 16777216] [รายการ: 2776, โหลด: 135.5%, แคช: 0, เพิ่ม: 2776, ลบ: 0] (65 (66.7%), Grow Threshold: 4096 (200.0%)] [การกลับมาใหม่: 0, ธรณีประตูใหม่: 120, เมล็ดแฮช: 0x0] [เกณฑ์อายุ: 3] [คิว] [ลดลง: 0]
เพื่อความสะดวกเราไม่จำเป็นต้องคำนวณการเพิ่มข้อมูลทั้งหมดด้วยตัวเองและก็เพียงพอที่จะใช้งานได้อย่างสะดวก
เซ็กเมนต์รหัสข้างต้นกำหนดว่าสตริงนั้นหนักหน่วง
คุณสมบัติข้างต้นเพิ่งเปิดตัวซึ่งหมายความว่าอาจไม่ได้รับการตรวจสอบอย่างละเอียด具体的数据在实际的应用中可能看起来有差别, 尤其是那些应用中字符串被多次使用和传递, 因此一些字符串可能被跳过或者早就有了 hashcode (正如你可能知道的那样, รหัสแฮชสตริงถูกโหลดอย่างเกียจคร้าน)
ในกรณีข้างต้นสตริงทั้งหมดนั้นหนักและข้อมูล 4.5MB จะถูกลบออกในหน่วยความจำ
[ตาราง] ส่วนหนึ่งของข้อมูลทางสถิติเกี่ยวกับตารางการติดตามภายในได้รับ
ดังนั้นความแตกต่างระหว่างการถ่วงน้ำหนักสตริงและที่อยู่อาศัยของสตริงคืออะไร? ในความเป็นจริงสตริงขึ้นอยู่กับมันคล้ายกับที่อยู่อาศัย
การโต้เถียงของผู้สร้างข้อเสนอการปรับปรุง JDK 192 คือนักพัฒนามักจะไม่ทราบว่าจะวางสตริงที่อยู่อาศัยที่เหมาะสมหรือถูกซ่อนไว้โดยเฟรมเวิร์ก ของประเทศ) คุณต้องการสามัญสำนึก
เมื่อสตริงอยู่ในเธรดแอปพลิเคชันเมื่อการกู้คืนขยะเป็นแบบอะซิงโครนัสและส่งผ่านสตริงจะไม่เพิ่มการบริโภคในระหว่างการรันไทม์ มันจะเพิ่มแรงกดดันให้กับ GC มากเกินไปดังนั้นสตริงจะไม่เกิดขึ้นเลย