Oracle'ın Java 8'i Mart 2014'de duyurmasından tam 6 ay geçti. Şu an JDK'nın en güncel sürümü 8u20. Son sürümü bu bağlantıdan indirip deneyebilirsiniz. Artık platform olgunlaşmaya başladı. JDK 8u20 ile gelen birkaç ilginç yenilik de bulunuyor. Bu özelliklerden biriyle G1 çöp toplayıcısının kullanılması durumunda karşılaşıyoruz. Garbage First (G1), çöp toplama zamanı elvermesi halinde, karakter katarlarını sabit havuzuna alıyor (String Deduplication). Sabit havuzu eskiden PermGen olarak adlandırılan alanda yer alıyordu. Artık Java 8'de PermGen yok, yerine MetaSpace olarak adlandırılan bellek bölgesi geldi. MetaSpace alanının eski PermGen'e göre en önemli kazanımı, dinamik olarak genişleyebiliyor olmasıdır. Sabit havuzunu derleme aşamasında değeri belirli String, bir sekizliğe sığan ([-128..127])Integer gibi tamsayı sınıfları kullanır:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class TestConstantPool { public static void main(String[] args) { String s1= "Hello"; // CP String s2= "Hello"; // CP // String is immutable String s3= new String("Hello"); // Heap (Eden) String s4= new String("Hello"); // Heap (Eden) if (s1==s2){ System.out.println("s1 is equal to s2"); }else{ System.out.println("s1 is NOT equal to s2"); } if (s4==s3){ System.out.println("s1 is equal to s3"); }else{ System.out.println("s1 is NOT equal to s3"); } s3= s3.intern(); if (s1==s3){ System.out.println("s1 is equal to s3"); }else{ System.out.println("s1 is NOT equal to s3"); } } } |
Aşağıdaki kodda ise 108 bir sekizliğe sığdığı için a ve b sabit havuzunda, 549 ise sekizliğe sığmadığı için m ve n ise Heap'deki nesneleri gösterir:
public class TestInteger { public static void main(String[] args) { Integer a= 108; // CP Integer b= 108; // CP Integer m= 549; // Heap (Eden) Integer n= 549; // Heap (Eden) if (a==b){ System.out.println("a is equal to b"); } else { System.out.println("a is NoT equal to b"); } if (m==n)){ System.out.println("m is equal to n"); } else { System.out.println("m is NoT equal to n"); } } }
"String deduplication" özelliği normalde kapalı geliyor. Bu özelliği açmak için Hotspot'u -XX:+UseG1GC -XX:+UseStringDeduplication seçenekleri ile başlatmalısınız. Aradaki farkı izlemek için aşağıdaki program parçasını kullanalım.
public class LotsOfStrings { private static final LinkedList<String> LOTS_OF_STRINGS = new LinkedList<>(); public static void main(String[] args) throws Exception { int iteration = 0; while (true) { for (int i = 0; i < 100; i++) { for (int j = 0; j < 1000; j++) { LOTS_OF_STRINGS.add(new String("String " + j)); } } iteration++; System.out.println("Survived Iteration: " + iteration); Thread.sleep(100); } } }
Survived Iteration: 1 Survived Iteration: 2 Survived Iteration: 3 Survived Iteration: 4 Survived Iteration: 5 Survived Iteration: 6 Survived Iteration: 7 Survived Iteration: 8 Survived Iteration: 9 Survived Iteration: 10 Survived Iteration: 11 Survived Iteration: 12 Survived Iteration: 13 Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded at com.example.console.LotsOfStrings.main(LotsOfStrings.java:18)
-Xms128m -Xmx128m -XX:+UseG1GC -XX:+UseStringDeduplication
Survived Iteration: 1 Survived Iteration: 2 Survived Iteration: 3 Survived Iteration: 4 Survived Iteration: 5 Survived Iteration: 6 Survived Iteration: 7 Survived Iteration: 8 Survived Iteration: 9 Survived Iteration: 10 Survived Iteration: 11 Survived Iteration: 12 Survived Iteration: 13 Survived Iteration: 14 Survived Iteration: 15 Survived Iteration: 16 Survived Iteration: 17 Survived Iteration: 18 Survived Iteration: 19 Survived Iteration: 20 Survived Iteration: 21 Survived Iteration: 22 Survived Iteration: 23 Survived Iteration: 24 Survived Iteration: 25 Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main" Java Result: 1
- Heap'deki canlı nesnelerin ortalama dörtte biri String nesnesidir.
- Heap'de yinelenen String oranı ortalama %13.5'dir.
- Ortalama String uzunluğu 45'dir.
Survived Iteration: 1 Survived Iteration: 2 Survived Iteration: 3 Survived Iteration: 4 Survived Iteration: 5 Survived Iteration: 6 Survived Iteration: 7 Survived Iteration: 8 Survived Iteration: 9 Survived Iteration: 10 Survived Iteration: 11 Survived Iteration: 12 Survived Iteration: 13 Survived Iteration: 14 Survived Iteration: 15 Survived Iteration: 16 Survived Iteration: 17 Survived Iteration: 18 Survived Iteration: 19 Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main" Java Result: 1
Bu özelliği açmanın gerçekten işe yarayıp yaramadığına karar vermek için yapılan işlemin başarımını kayıtlardan izlemek gerekir. Bunun için -XX:+PrintStringDeduplicationStatistics seçeneğini vermek yeterli olur:
Survived Iteration: 1 [GC concurrent-string-deduplication, 2131.9K->39.3K(2092.6K), avg 98.2%, 0.0121525 secs] [Last Exec: 0.0121525 secs, Idle: 0.0000008 secs, Blocked: 0/0.0000000 secs] [Inspected: 54680] [Skipped: 0( 0.0%)] [Hashed: 54680(100.0%)] [Known: 0( 0.0%)] [New: 54680(100.0%) 2131.9K] [Deduplicated: 53678( 98.2%) 2092.6K( 98.2%)] [Young: 0( 0.0%) 0.0B( 0.0%)] [Old: 53678(100.0%) 2092.6K(100.0%)] [Total Exec: 1/0.0121525 secs, Idle: 1/0.0000008 secs, Blocked: 0/0.0000000 secs] [Inspected: 54680] [Skipped: 0( 0.0%)] [Hashed: 54680(100.0%)] [Known: 0( 0.0%)] [New: 54680(100.0%) 2131.9K] [Deduplicated: 53678( 98.2%) 2092.6K( 98.2%)] [Young: 0( 0.0%) 0.0B( 0.0%)] [Old: 53678(100.0%) 2092.6K(100.0%)] [Table] [Memory Usage: 49.5K] [Size: 1024, Min: 1024, Max: 16777216] [Entries: 1770, Load: 172.9%, Cached: 0, Added: 1770, Removed: 0] [Resize Count: 0, Shrink Threshold: 682(66.7%), Grow Threshold: 2048(200.0%)] [Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0] [Age Threshold: 3] [Queue] [Dropped: 0]
[GC concurrent-string-deduplication, 2131.9K->39.3K(2092.6K), avg 98.2%, 0.0121525 secs]
Bu satırdan, String deduplication için ne kadar süre harcandığı ve ortalama ne kadar yineleme yakalandığını okumak mümkündür. Karar sizin.
No comments:
Post a Comment