Skip to content

Commit dc0d4a1

Browse files
feat(jdk14): Add demo for JEP 366 – Deprecate the ParallelScavenge + SerialOld GC Combination code changes (#346)
1 parent f382c99 commit dc0d4a1

3 files changed

Lines changed: 220 additions & 0 deletions

File tree

src/main/java/org/javademos/init/Java14DemoLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.javademos.java14.jep362.SolarisSparcRemovalDemo;
1414
import org.javademos.java14.jep364.ZGarbageCollectorOnMacOS;
1515
import org.javademos.java14.jep365.ZGarbageCollectorOnWindows;
16+
import org.javademos.java14.jep366.ParallelScavengeGCCombinationDemo;
1617
import org.javademos.java14.jep368.TextBlockSecondPreviewDemo;
1718
import org.javademos.java14.jep370.ForeignMemoryAccessDemo;
1819

@@ -31,6 +32,7 @@ public void loadDemos(Map<Integer, IDemo> demos) {
3132
demos.put(362, new SolarisSparcRemovalDemo());
3233
demos.put(364, new ZGarbageCollectorOnMacOS());
3334
demos.put(365, new ZGarbageCollectorOnWindows());
35+
demos.put(366, new ParallelScavengeGCCombinationDemo());
3436
demos.put(368, new TextBlockSecondPreviewDemo());
3537
demos.put(370, new ForeignMemoryAccessDemo());
3638
}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package org.javademos.java14.jep366;
2+
3+
import org.javademos.commons.IDemo;
4+
5+
import java.lang.management.*;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
/// Demo for JDK 14 feature <strong>JEP 366 - Deprecate the ParallelScavenge + SerialOld GC Combination</strong>.
10+
///
11+
///
12+
/// Summary:
13+
/// Deprecate the combination of the Parallel Scavenge and Serial Old garbage collection algorithms.
14+
///
15+
/// Further Reading -
16+
/// - [Official JEP 366](https://openjdk.org/jeps/366)
17+
///
18+
/// Additional References -
19+
/// - [DZone - Java 14](https://dzone.com/refcardz/java-14-1)
20+
/// - [New Features in Java 14](https://www.baeldung.com/java-14-new-features)
21+
///
22+
///
23+
/// @author SanjanaMahapatra
24+
25+
public class ParallelScavengeGCCombinationDemo implements IDemo {
26+
@Override
27+
public void demo() {
28+
info(366);
29+
30+
// In the oracle documentation, it states that very few people uses the pairing
31+
// combination of parallel young generation GC (called ParallelScavenge) and the
32+
// serial old GC (called SerialOld).
33+
34+
// To use this feature, this has to be explicitly specified and enabled by the
35+
// user with usage of following command - XX:+UseParallelGC -XX:-UseParallelOldGC
36+
// using the command line options.
37+
38+
// This combination is only useful, only when there is a need of deployment which
39+
// involves very large young generation and a very small old generation.
40+
41+
// This involves a very rare and risky deployment, since a slight shift in liveness for objects
42+
// in the young generation will result in an OutOfMemoryException, since the old generation is
43+
// significantly smaller than the young generation.
44+
45+
// Since, this is a rarely used combination of GC algorithms, and requires significant
46+
// maintenance effort, Java 14 have deprecated this feature.
47+
48+
// Lets demonstrates one example and check in the terminal
49+
50+
51+
System.out.println("=== JEP 366: Deprecate ParallelScavenge + SerialOld GC Combination ===");
52+
53+
// Example 1: Showing the deprecation warning
54+
System.out.println("""
55+
1. Running with deprecated GC combination:
56+
Command: java -XX:+UseParallelGC -XX:-UseParallelOldGC -version
57+
Expected: Deprecation warning in Java 14+
58+
"""
59+
);
60+
61+
// Show current GC information
62+
System.out.println("Demonstrating with example");
63+
64+
// allocate a memory to trigger the Garbage Collection (GC)
65+
66+
List<byte[]> largeMemory = new ArrayList<>(2000);
67+
try {
68+
for(int i =0; i < 100_000; i++) {
69+
largeMemory.add(new byte[500 * 1024 * 1024]);
70+
System.out.println(" === Allocated memory : " + ((i+1)*500) + " MB ===");
71+
Thread.sleep(50);
72+
}
73+
}catch (OutOfMemoryError err) {
74+
System.out.println(" === OutOfMemoryError occurred === ");
75+
}catch (InterruptedException err) {
76+
Thread.currentThread().interrupt();
77+
}
78+
79+
printGCInfo();
80+
}
81+
82+
private void printGCInfo() {
83+
Runtime runtime = Runtime.getRuntime();
84+
System.out.println("Max Memory: " + runtime.maxMemory() / (1024 * 1024) + "MB");
85+
System.out.println("Total Memory: " + runtime.totalMemory() / (1024 * 1024) + "MB");
86+
System.out.println("Free Memory: " + runtime.freeMemory() / (1024 * 1024) + "MB");
87+
System.out.println("Used Memory: " + (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024) + " MB");
88+
89+
// Get GC information
90+
try {
91+
92+
System.out.println("\n=== GARBAGE COLLECTORS ===");
93+
94+
List<GarbageCollectorMXBean> gcBeans =
95+
ManagementFactory.getGarbageCollectorMXBeans();
96+
97+
for(GarbageCollectorMXBean gcBean : gcBeans) {
98+
System.out.println("GC Name: " + gcBean.getName());
99+
System.out.println("Collection Count: " + gcBean.getCollectionCount());
100+
System.out.println("Collection Time: " + gcBean.getCollectionTime());
101+
}
102+
103+
System.out.println("\n === Memory Usage Distribution === ");
104+
105+
MemoryMXBean m = ManagementFactory.getMemoryMXBean();
106+
for(MemoryType type: MemoryType.values()) {
107+
usage(type, type == MemoryType.HEAP?
108+
m.getHeapMemoryUsage(): m.getNonHeapMemoryUsage());
109+
System.out.println();
110+
for(MemoryPoolMXBean mp: ManagementFactory.getMemoryPoolMXBeans())
111+
if(mp.getType() == type) usage(mp.getName(), mp.getUsage());
112+
System.out.println();
113+
}
114+
115+
System.out.println("\n === Memory Pools Used === ");
116+
117+
List<MemoryPoolMXBean> memoryPoolMXBeanList = ManagementFactory.getMemoryPoolMXBeans();
118+
119+
for(MemoryPoolMXBean poolMXBean : memoryPoolMXBeanList) {
120+
MemoryUsage memoryUsage = poolMXBean.getUsage();
121+
String name = poolMXBean.getName();
122+
123+
System.out.println("Pool Name: " + name);
124+
125+
System.out.printf(" - Init: %,dMB%n", memoryUsage.getInit() / (1024 * 1024));
126+
System.out.printf(" - Used: %,dMB%n", memoryUsage.getUsed() / (1024 * 1024));
127+
System.out.printf(" - Committed: %,dMB%n", memoryUsage.getCommitted() / (1024 * 1024));
128+
System.out.printf(" - Max: %,dMB%n", memoryUsage.getMax() / (1024 * 1024));
129+
130+
// Classify the pool
131+
if (name.contains("Eden") || name.contains("Young")) {
132+
System.out.println(" - Type: Young Generation (Eden)");
133+
} else if (name.contains("Survivor")) {
134+
System.out.println(" - Type: Young Generation (Survivor)");
135+
} else if (name.contains("Old") || name.contains("Tenured")) {
136+
System.out.println(" - Type: Old Generation");
137+
} else if (name.contains("Metaspace")) {
138+
System.out.println(" - Type: Metaspace");
139+
} else if (name.contains("Code")) {
140+
System.out.println(" - Type: Code Cache");
141+
}
142+
143+
}
144+
145+
calculateGenerationTotals(memoryPoolMXBeanList);
146+
147+
} catch (Exception e) {
148+
System.out.println("Unable to get GC details");
149+
}
150+
}
151+
152+
private static void usage(Object header, MemoryUsage mu) {
153+
long used = mu.getUsed(), max = mu.getMax();
154+
System.out.printf(
155+
max > 0? "%-30s %,d (%,d MiB) of %,d (%,d MiB)%n": "%-30s %,d (%,d MiB)%n",
156+
header, used, used >>> 20, max, max >>> 20);
157+
}
158+
159+
private void calculateGenerationTotals(List<MemoryPoolMXBean> memoryPools) {
160+
long youngGenUsed = 0;
161+
long youngGenCommitted = 0;
162+
long youngGenMax = 0;
163+
164+
long oldGenUsed = 0;
165+
long oldGenCommitted = 0;
166+
long oldGenMax = 0;
167+
168+
for (MemoryPoolMXBean pool : memoryPools) {
169+
MemoryUsage usage = pool.getUsage();
170+
String name = pool.getName();
171+
172+
if (name.contains("Eden") || name.contains("Survivor") ||
173+
name.contains("Young") || name.contains("PS Young")) {
174+
youngGenUsed += usage.getUsed();
175+
youngGenCommitted += usage.getCommitted();
176+
if (usage.getMax() != -1) {
177+
youngGenMax += usage.getMax();
178+
}
179+
} else if (name.contains("Old") || name.contains("Tenured") ||
180+
name.contains("PS Old")) {
181+
oldGenUsed += usage.getUsed();
182+
oldGenCommitted += usage.getCommitted();
183+
if (usage.getMax() != -1) {
184+
oldGenMax += usage.getMax();
185+
}
186+
}
187+
}
188+
189+
System.out.println("\n=== CALCULATED GENERATION TOTALS ===");
190+
System.out.printf("Young Generation:%n");
191+
System.out.printf(" - Used: %,dMB%n", youngGenUsed / (1024 * 1024));
192+
System.out.printf(" - Committed: %,dMB%n", youngGenCommitted / (1024 * 1024));
193+
if (youngGenMax > 0) {
194+
System.out.printf(" - Max: %,dMB%n", youngGenMax / (1024 * 1024));
195+
}
196+
197+
System.out.printf("Old Generation:%n");
198+
System.out.printf(" - Used: %,dMB%n", oldGenUsed / (1024 * 1024));
199+
System.out.printf(" - Committed: %,dMB%n", oldGenCommitted / (1024 * 1024));
200+
if (oldGenMax > 0) {
201+
System.out.printf(" - Max: %,dMB%n", oldGenMax / (1024 * 1024));
202+
}
203+
204+
if (youngGenCommitted > 0 && oldGenCommitted > 0) {
205+
double youngRatio = (double) youngGenCommitted / (youngGenCommitted + oldGenCommitted) * 100;
206+
double oldRatio = (double) oldGenCommitted / (youngGenCommitted + oldGenCommitted) * 100;
207+
System.out.printf("Generation Ratio: Young=%.1f%%, Old=%.1f%%%n", youngRatio, oldRatio);
208+
}
209+
}
210+
}

src/main/resources/JDK14Info.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@
6363
"link": true,
6464
"code": false
6565
},
66+
{
67+
"jep": 366,
68+
"jdk": 14,
69+
"name": "JEP 366 - Deprecate the ParallelScavenge + SerialOld GC Combination",
70+
"dscr": "Deprecate the combination of the Parallel Scavenge and Serial Old garbage collection algorithms.",
71+
"link": false,
72+
"code": true
73+
},
6674
{
6775
"jep": 368,
6876
"jdk": 14,

0 commit comments

Comments
 (0)