How can I tell whether the JVM performed a garbage collection? - java
Rewritten since everybody seems to be answering a different question:
How can I tell whether the JVM performed a garbage collection? Perhaps a System listener?
You can get the Garbage collection statistics via JMX. This is how jstat gets the information.
public static void main(String... args) throws IOException {
for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
System.out.println(toMap(bean).toString()
.replace("javax.management.openmbean.SimpleType", "ST")
.replace("java.lang.", ""));
}
}
public static Map<String, Object> toMap(Object o) {
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(o.getClass());
} catch (IntrospectionException e) {
throw new RuntimeException(e);
}
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
if (propertyDescriptor.getName().equals("class")) continue;
Object value = null;
try {
value = propertyDescriptor.getReadMethod().invoke(o);
} catch (Exception e) {
value = e.toString();
}
map.put(propertyDescriptor.getName(), value);
}
return map;
}
prints a lot of descriptive information, but hidden in there is all the stats of how many collections have been performed, how long they took and the size of the regions before and after collections.
In particular, you can look at the collectionCount. When this increases, a collection occurred.
{collectionCount=2, collectionTime=1, lastGcInfo=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=sun.management.PS Scavenge.GcInfoCompositeType,items=((itemName=GcThreadCount,itemType=ST(name=Integer)),(itemName=duration,itemType=ST(name=Long)),(itemName=endTime,itemType=ST(name=Long)),(itemName=id,itemType=ST(name=Long)),(itemName=memoryUsageAfterGc,itemType=javax.management.openmbean.TabularType(name=Map,rowType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),indexNames=(key))),(itemName=memoryUsageBeforeGc,itemType=javax.management.openmbean.TabularType(name=Map,rowType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),indexNames=(key))),(itemName=startTime,itemType=ST(name=Long)))),contents={GcThreadCount=10, duration=1, endTime=40, id=2, memoryUsageAfterGc=javax.management.openmbean.TabularDataSupport(tabularType=javax.management.openmbean.TabularType(name=Map,rowType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),indexNames=(key)),contents={[Compressed Class Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Compressed Class Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=524288, init=0, max=1073741824, used=424552})}), [PS Survivor Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Survivor Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=524288, init=524288, max=524288, used=507920})}), [PS Old Gen]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Old Gen, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=22544384, init=22544384, max=22544384, used=151568})}), [Metaspace]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Metaspace, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=4980736, init=0, max=-1, used=3648080})}), [PS Eden Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Eden Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=1048576, init=524288, max=9961472, used=0})}), [Code Cache]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Code Cache, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=2555904, init=2555904, max=251658240, used=1242560})})}), memoryUsageBeforeGc=javax.management.openmbean.TabularDataSupport(tabularType=javax.management.openmbean.TabularType(name=Map,rowType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),indexNames=(key)),contents={[Compressed Class Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Compressed Class Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=524288, init=0, max=1073741824, used=424552})}), [PS Survivor Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Survivor Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=524288, init=524288, max=524288, used=524288})}), [PS Old Gen]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Old Gen, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=22544384, init=22544384, max=22544384, used=8192})}), [Metaspace]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Metaspace, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=4980736, init=0, max=-1, used=3648080})}), [PS Eden Space]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=PS Eden Space, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=524288, init=524288, max=9961472, used=524288})}), [Code Cache]=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=Map,items=((itemName=key,itemType=ST(name=String)),(itemName=value,itemType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long))))))),contents={key=Code Cache, value=javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=management.MemoryUsage,items=((itemName=committed,itemType=ST(name=Long)),(itemName=init,itemType=ST(name=Long)),(itemName=max,itemType=ST(name=Long)),(itemName=used,itemType=ST(name=Long)))),contents={committed=2555904, init=2555904, max=251658240, used=1242560})})}), startTime=39}), memoryPoolNames=[LString;#6d03e736, name=PS Scavenge, notificationInfo=[Ljavax.management.MBeanNotificationInfo;#568db2f2, objectName=java.lang:type=GarbageCollector,name=PS Scavenge, valid=true}
{collectionCount=0, collectionTime=0, lastGcInfo=null, memoryPoolNames=[LString;#378bf509, name=PS MarkSweep, notificationInfo=[Ljavax.management.MBeanNotificationInfo;#5fd0d5ae, objectName=java.lang:type=GarbageCollector,name=PS MarkSweep, valid=true}
GC is hardly going to affect your game performance, because it's ongoing, it keeps collecting everything that isn't used anymore and it does it while the code is running. You can force the GC to work and then put up a loading screen, but that's not recommended.
PS.: If the GC affected the game performance that much, Minecraft would be a disaster and Android apps and games wouldn't be built in Java! Think about that ;)
System.gc();
Java uses managed memory although I would not recommend you to use the above method.
From the Java Docs
Calling the gc method suggests that the Java Virtual Machine expend
effort toward recycling unused objects in order to make the memory
they currently occupy available for quick reuse. When control returns
from the method call, the Java Virtual Machine has made a best effort
to reclaim space from all discarded objects.
Related
Is there any equivalent of Java Runtime Class in C#? [duplicate]
How can I get the available RAM or memory used by the application?
You can use: Process proc = Process.GetCurrentProcess(); To get the current process and use: proc.PrivateMemorySize64; To get the private memory usage. For more information look at this link.
You might want to check the GC.GetTotalMemory method. It retrieves the number of bytes currently thought to be allocated by the garbage collector.
System.Environment has WorkingSet- a 64-bit signed integer containing the number of bytes of physical memory mapped to the process context. In .NET Core 3.0 and later (aka .NET 5 and later), you can use GC.GetGCMemoryInfo to get information about memory used by the GC heap and how much memory the GC thinks is available. .NET internally uses this data to calculate memory pressure. The memory pressure is used to decide when to trim the System.Buffers.ArrayPool.
In addition to #JesperFyhrKnudsen's answer and #MathiasLykkegaardLorenzen's comment, you'd better dispose the returned Process after using it. So, In order to dispose the Process, you could wrap it in a using scope or calling Dispose on the returned process (proc variable). using scope: var memory = 0.0; using (Process proc = Process.GetCurrentProcess()) { // The proc.PrivateMemorySize64 will returns the private memory usage in byte. // Would like to Convert it to Megabyte? divide it by 2^20 memory = proc.PrivateMemorySize64 / (1024*1024); } Or Dispose method: var memory = 0.0; Process proc = Process.GetCurrentProcess(); memory = Math.Round(proc.PrivateMemorySize64 / (1024*1024), 2); proc.Dispose(); Now you could use the memory variable which is converted to Megabyte.
Look here for details. private PerformanceCounter cpuCounter; private PerformanceCounter ramCounter; public Form1() { InitializeComponent(); InitialiseCPUCounter(); InitializeRAMCounter(); updateTimer.Start(); } private void updateTimer_Tick(object sender, EventArgs e) { this.textBox1.Text = "CPU Usage: " + Convert.ToInt32(cpuCounter.NextValue()).ToString() + "%"; this.textBox2.Text = Convert.ToInt32(ramCounter.NextValue()).ToString()+"Mb"; } private void Form1_Load(object sender, EventArgs e) { } private void InitialiseCPUCounter() { cpuCounter = new PerformanceCounter( "Processor", "% Processor Time", "_Total", true ); } private void InitializeRAMCounter() { ramCounter = new PerformanceCounter("Memory", "Available MBytes", true); } If you get value as 0 it need to call NextValue() twice. Then it gives the actual value of CPU usage. See more details here.
For the complete system you can add the Microsoft.VisualBasic Framework as a reference; Console.WriteLine("You have {0} bytes of RAM", new Microsoft.VisualBasic.Devices.ComputerInfo().TotalPhysicalMemory); Console.ReadLine();
Why is heap memory going up together with metaspace in Java 8?
I'm doing a little test to understand how metaspace memory (Java 8 onwards) works. When I create 100,000 classes dynamically the metaspace memory is growing (obviously) but heap memory is going up too. Can someone explain to me why this occurs? PS: I'm running the test with 128 MB of heap and 128 MB of metaspace. #Test public void metaspaceTest() throws CannotCompileException, InterruptedException { ClassPool cp = ClassPool.getDefault(); System.out.println("started"); for (int i = 0; i <= 100000; i++) { Class c = cp.makeClass("br.com.test.GeneratedClass" + i).toClass(); Thread.sleep(1); if (i % 10000 == 0) { System.out.println(i); } } System.out.println("finished"); } See the images below:
Your class pool uses heap memory. It's got hashtables and lists and other things. It also uses java reflection code which uses heap memory. Heap memory that is not gc'ed is probably all those data structures in class pool, a couple hashtables, linked lists, array lists, pools, etc... For instance, every single class you create is stored in a hashtable by the class pool. That is a 100,000 element hash table. Secondly, if there are any static initializers in the classes you are creating, that will use heap memory. Static initializers include the static field initializations and the static block code.
I did a study of your code especially ClassPool#makeClass. There are few points I noticed which are causing heap space to increase as metaspace increases. It cache the classes created by method makeClass inside a hashtable protected Hashtable classes; So, for a 10th of million of classes, it has the entry for each of these. Hence, Heap Space increases too and it's not GC as hashtable reference is still used by your for loop and continuously updated hence not eligible for gc. CtNewClass creates the new instance of the class and it has the constructor definition as below: CtNewClass(String name, ClassPool cp, boolean isInterface, CtClass superclass) { super(name, cp); this.wasChanged = true; String superName; if (!isInterface && superclass != null) { superName = superclass.getName(); } else { superName = null; } this.classfile = new ClassFile(isInterface, name, superName); if (isInterface && superclass != null) { this.classfile.setInterfaces(new String[]{superclass.getName()}); } this.setModifiers(Modifier.setPublic(this.getModifiers())); this.hasConstructor = isInterface; } In code above line this.classfile = new ClassFile(isInterface, name, superName); actually creates new ConstPool instance for each class i.e. new HashMap instances for each instance and these reserve memory on heap space. HashMap classes; //from ConstPool class HashMap strings; //from ConstPool class Also, this creates two new ArrayLists. Observe this.fields = new ArrayList(); and this.methods = new ArrayList(); statement in above constructor. Also, a new linked list this.attributes = new LinkedList();. Hence, the conclusion is the ClassPool has its cache management which takes the good amount of heap space. Then each class has its own set of collections to manage properties, constants etc. Hope it helps!
Java G1: Monitoring for memory leaks in production
For years, we've been running Java services with modest heap sizes using +UseParallelOldGC. Now, we're starting to roll out a new service using a larger heap and the G1 collector. This is going pretty well. For our services that use +UseParallelOldGC, we monitor for memory leaks by looking at the old generation size after collection and alerting on a threshold. This works quite well, and in fact saved our bacon just two weeks ago. Specifically, for +UseParallelOldGC, we do the following: ManagementFactory.getMemoryPoolMXBeans() Search for the MemoryPoolMXBean result with the name ending in "Old Gen" Compare getCollectionUsage().getUsed() (if available) with getMax() Unfortunately, it seems like G1 no longer has a concept of getCollectionUsage(). Fundamentally, though, we'd like to monitor the G1 heap size following the last mixed collection it chooses to do in a mixed cycle, or something similar. For example, outside the VM I would be happy with an awk script that merely found the last '(mixed)' was that's followed by a '(young)' and look what the final heap size was (e.g., '1540.0M' 'Heap: 3694.5M(9216.0M)->1540.0M(9216.0M)') Is there any way to do this inside the Java VM?
Yes, JVM gives you enough tools to retrieve such information for G1. For instance, you could use something like this class that prints all the details about garbage collections (just call MemoryUtil.startGCMonitor()): public class MemoryUtil { private static final Set<String> heapRegions; static { heapRegions = ManagementFactory.getMemoryPoolMXBeans().stream() .filter(b -> b.getType() == MemoryType.HEAP) .map(MemoryPoolMXBean::getName) .collect(Collectors.toSet()); } private static NotificationListener gcHandler = (notification, handback) -> { if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData()); Map<String, MemoryUsage> memBefore = gcInfo.getGcInfo().getMemoryUsageBeforeGc(); Map<String, MemoryUsage> memAfter = gcInfo.getGcInfo().getMemoryUsageAfterGc(); StringBuilder sb = new StringBuilder(250); sb.append("[").append(gcInfo.getGcAction()).append(" / ").append(gcInfo.getGcCause()) .append(" / ").append(gcInfo.getGcName()).append(" / ("); appendMemUsage(sb, memBefore); sb.append(") -> ("); appendMemUsage(sb, memAfter); sb.append("), ").append(gcInfo.getGcInfo().getDuration()).append(" ms]"); System.out.println(sb.toString()); } }; public static void startGCMonitor() { for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) { ((NotificationEmitter) mBean).addNotificationListener(gcHandler, null, null); } } public static void stopGCMonitor() { for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) { try { ((NotificationEmitter) mBean).removeNotificationListener(gcHandler); } catch(ListenerNotFoundException e) { // Do nothing } } } private static void appendMemUsage(StringBuilder sb, Map<String, MemoryUsage> memUsage) { memUsage.entrySet().forEach((entry) -> { if (heapRegions.contains(entry.getKey())) { sb.append(entry.getKey()).append(" used=").append(entry.getValue().getUsed() >> 10).append("K; "); } }); } } In this code, gcInfo.getGcAction() gives you enough information to separate minor collections from major/mixed ones. But there's an important caveat to using your approach (with a threshold) to G1. A single mixed collection in G1 usually affects only several old gen regions - many enough to free sufficient amount of memory but not too many in order to keep the GC pause low. So, after a mixed collection in G1 you cannot be sure that all your garbage has gone. As a result, you need to find more sophisticated strategy to detect memory leaks (maybe based on collections frequency, gathering statistics from several collections, etc.)
Java memory leak and garbage collection,
This question has baffled myself and my cohorts. In the program I had written I was experiencing a memory leak. The var Platform, was being reassigned each iterations to a new object. But for some reason the old platform objects where not being cleaned by the gc and after many iterations the heap overflows: Some of you may realise this is a PSO algorithm. But for those who don't this function has to be evaluated 1000's of times, and basicplatform is an extremely data extensive object, so multiple instances would eventually give a memory overflow, just to give a little context. Buggy code: public class Fitness implements FitnessFunction{ protected Platform platform; public Fitness(){ } public Fitness(Platform platform) { this.platform = platform; } #Override public double fitness(Particle p) { try { platform = new BasicPlatform("testData.csv"); } catch (Exception e) { e.printStackTrace(); } platform.startSimulation(); double prof = platform.getFitness(); v.clear(); if(prof != 0) return -prof; return 0; } } After being confused as to why there is leak, as surely there shoudln't be, my friend showed me this solution, which he used before in a similar situation: public class TradingRuleFitness implements FitnessFunction{ protected Platform platform; public Fitness(){ } public Fitness(Platform platform) { this.platform = platform; } #Override public double fitness(Particle p) { Vector<Platform> v = new Vector<Platform>(); try { //platform = new BasicPlatform("testData.csv"); v.add(new BasicPlatform("testData.csv")); } catch (Exception e) { e.printStackTrace(); } double prof = v.get(0).getFitness; v.clear(); if(prof != 0) return -prof; return 0; } } Nearly exactly the same but this time instead of re-assigning the var platform we create a new object inside a vector and delete it after I have finished with it.This method seems to force the gc into cleaning up. The question is why does this vector method work but not the original which technically should and are there any cleaner solutions? p.s I have cleaned up unnesscary bits of code, as the question is about the object creation and removal
In the first case, if your Fitness object si retained, so will your Platform object be retained as it a field. In the second case, your Platform is held in a local variable and is discard when fitness returns. It doesn't have to be a Vector, it could be a plain local variable. Try removing the field in both examples and it should work either way.
Seems in the first example you also cleared the "unnesscary bits of code" for the vector itself :) It'll be hard to give a correct answer like this...
How to detect PermGen free memory
What is the best way to work out the current PermGen usage in a Grails app? I'm trying to do some graphing of Runtime.getRuntime().freeMemory(); Runtime.getRuntime().totalMemory(); And I'd like to also measure the free PermGen space. Most of the search engine + Stack Overflow results on this matter are on handling the PermGenOutOfMemory-like errors, I'd just like to access the stats on these.
Just connect to it using JConsole or VisualVM. Theres no way for you to programmatically determine the PermGen size in your application. You can use the MemoryMXBean to do simple memory reporting, but stick to using the tools I mentioned to get a more detailed picture.
I guess you should try this public class Main { public static void main(final String[] args) { final RuntimeMXBean memMXBean = ManagementFactory.getRuntimeMXBean(); final String prefix = "-XX:MaxPermSize="; final List<String> jvmArgs = memMXBean.getInputArguments(); String maxPermSize = null; for (final String jvmArg : jvmArgs) { if (jvmArg.startsWith(prefix)) { maxPermSize = jvmArg.substring(prefix.length()); break; } } System.out.println("MaxPermSize is " + maxPermSize); } }
I think ManagementFactory could be the source, one of the pools returned from List getMemoryPoolMXBeans() should be PermGen.