ExerciseWarm-up
Warm-up
Ask the JVM where its metadata lives
5 minintermediate2–10 yrs
One concept, guided. Near-impossible to fail.
What this teaches
- Metaspace is a non-heap pool, outside -Xmx
- It is unbounded by default, which is the whole change from PermGen
- There is no PermGen pool on any JDK 8 or later
- Loading a class costs metadata, and nothing unloads it in a normal run
Starter
Starter.javaOpen in playground
import java.lang.management.*;
import java.util.*;
/**
* WARM-UP — 5 minutes. One concept. Hard to fail.
*
* The JVM will tell you where its class metadata lives. Ask it.
*
* TASKS
* 1. Predict the three booleans before running.
* 2. Run it.
* 3. Run it again with a ceiling and watch one of them flip:
* java -XX:MaxMetaspaceSize=64m -cp . Starter
* 4. Try the flag PermGen used to take. The JVM will not start:
* java -XX:MaxPermSize=256m -cp . Starter
* 5. In a comment: which of the numbers printed here would appear in a
* heap dump?
*/
public class Starter {
public static void main(String[] args) {
boolean permGen = false;
MemoryPoolMXBean metaspace = null;
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
if (pool.getName().contains("Perm")) permGen = true;
if (pool.getName().equals("Metaspace")) metaspace = pool;
}
System.out.println("a PermGen pool exists : " + permGen);
System.out.println("Metaspace is non-heap memory : "
+ (metaspace.getType() == MemoryType.NON_HEAP));
System.out.println("Metaspace has a ceiling : "
+ (metaspace.getUsage().getMax() >= 0));
System.out.println();
System.out.println("metaspace used : " + metaspace.getUsage().getUsed() / 1024 + " KB");
ClassLoadingMXBean loading = ManagementFactory.getClassLoadingMXBean();
System.out.println("classes loaded : " + loading.getLoadedClassCount());
System.out.println("ever unloaded : " + loading.getUnloadedClassCount());
System.out.println();
System.out.println("every non-heap pool in this JVM:");
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
if (pool.getType() == MemoryType.NON_HEAP) {
long max = pool.getUsage().getMax();
System.out.println(" " + pool.getName()
+ " max=" + (max < 0 ? "unbounded" : (max / (1024 * 1024)) + " MB"));
}
}
// Question to answer in a comment before you move on:
// "ever unloaded" is 0 in a program that ran to completion. Is that
// a bug, and what would have to be true for it to be non-zero?
}
}Run it locally:
cd exercises/java/jvm/metaspace-vs-permgen/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out StarterDone when
- You predicted each of the three booleans before running
- You re-ran it with -XX:MaxMetaspaceSize=64m and saw one flip
- A comment says which of these numbers a heap dump would show