Have you considered that what you are telling your students is not generally true if you cannot reproduce it? If your toy definition of realtime is "pauses less than 1s" then many JVM applications can be considered realtime.
And that's without resorting to pauseless collectors.
But of course one can also trivially construct cases where a GC takes more than 1 second, e.g. by allocating a sufficiently large heap so that the system starts swapping. But in that case non-GCed languages would also experience latency spikes - maybe not quite as bad - and thus it would be a quite poor demonstration of GC issues.
System.gc()
also is a bad demonstration since it currently invokes a single-threaded collection while the normal operation of the default collectors make use of multiple cores. Fixes are underway
To construct a somewhat realistic scenario under which modern collectors will experience >1s pauses, you will need
- a large heap - multiple cores can generally chew through small heaps quite fast
- a large live set size - dead objects are cheap
- lots of small objects - large arrays of primitives are generally collected quickly
- lots of reference between objects - null fields don't need updating. random object graphs also make life a lot harder for G1GC
And since you're using OpenJDK you would merely be testing collectors of a JVM targeting desktop and server-class workloads. There are other JVMs and 3rd-party garbage collector implementations which aim for realtime goals so one could simply dismiss your demonstration as calling a downhill bike a horrible bicycle because you can't win a velodrome race with it.