All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gridkit.jvmtool.gcflow.GcAdapter Maven / Gradle / Ivy

There is a newer version: 0.23
Show newest version
package org.gridkit.jvmtool.gcflow;

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.management.JMX;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.gridkit.jvmtool.gcflow.GarbageCollectionSampler.GcReport;
import org.gridkit.jvmtool.gcflow.GcKnowledgeBase.PoolType;

import com.sun.management.GarbageCollectorMXBean;
import com.sun.management.GcInfo;

@SuppressWarnings("restriction")
class GcAdapter {

	private final GarbageCollectionSampler sampler;
	private final GarbageCollectorMXBean gc;
	
	private final String name;
	private final long processStartMs;
	private final List collectedPools;
	private final List allCollectedPools;
	
	private final List edenPools;
	private final List survivourPools;
	private final List youngPools;
	private final List oldPools;
	private final List permPools;
	
	
	
	private final boolean isYoung;
	private final boolean isConcurent;
	
	private long gcCount = -1;
	private long prevCollectionEndTime = -1; 
	
	
	public GcAdapter(MBeanServerConnection mserver, ObjectName gcname, GarbageCollectionSampler sampler) throws IOException, MalformedObjectNameException {
		this.sampler = sampler;
		gc = JMX.newMXBeanProxy(mserver, gcname, GarbageCollectorMXBean.class);
		name = gc.getName();
		RuntimeMXBean runtime = JMX.newMXBeanProxy(mserver, new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME), RuntimeMXBean.class);

		processStartMs = runtime.getStartTime();
		collectedPools = Arrays.asList(gc.getMemoryPoolNames());
		
		allCollectedPools = new ArrayList(GcKnowledgeBase.allCollectedPools(mserver));
		Map> types = GcKnowledgeBase.classifyMemoryPools(mserver);
		
		edenPools = getMemPools(types, PoolType.EDEN);
		survivourPools = getMemPools(types, PoolType.SURVIVOR);
		oldPools = getMemPools(types, PoolType.TENURED);
		permPools = getMemPools(types, PoolType.PERMANENT);
		youngPools = new ArrayList();
		youngPools.addAll(edenPools);
		youngPools.addAll(survivourPools);
		
		isYoung = collectedPools.containsAll(oldPools);
		isConcurent = "ConcurrentMarkSweep".equals(name);
	}

	private List getMemPools(Map> types, PoolType type) {
		List pools;
		if (types.containsKey(type)) {
			pools = new ArrayList(types.get(type));
		}
		else {
			pools = Collections.emptyList();
		}
		return pools;
	}

	public void report() {
		try {
			GcInfo lastGc = gc.getLastGcInfo();
			if (lastGc == null || lastGc.getId() == gcCount) {
				return;
			}
			else {				
				int missed = (int)(lastGc.getId() - 1 - gcCount);
				if (gcCount < 0) {
					missed = 0;
				}
				long gcInterval = lastGc.getStartTime() - prevCollectionEndTime;
				prevCollectionEndTime = lastGc.getEndTime();
				if (gcCount < 0) {
					gcInterval = -1;
				}
				if (lastGc.getEndTime() == 0) {
					// no GC so far
					prevCollectionEndTime = 0;
					gcCount = lastGc.getId();
				}
				else {
					gcCount = lastGc.getId();
					sampler.report(name, missed, new Report(lastGc, gcInterval));
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


	private class Report implements GcReport {
		
		private GcInfo gcInfo;
		private long gcInterval;
		
		public Report(GcInfo gcInfo, long gcInterval) {
			this.gcInfo = gcInfo;
			this.gcInterval = gcInterval;
		}

		@Override
		public long getId() {
			return gcInfo.getId();
		}
		
		@Override
		public long getWallClockStartTime() {
			return processStartMs + gcInfo.getStartTime();
		}

		@Override
		public long getWallClockEndTime() {
			return processStartMs + gcInfo.getEndTime();
		}

		@Override
		public long getJvmClockStartTime() {
			return gcInfo.getStartTime();
		}

		@Override
		public long getJvmClockEndTime() {
			return gcInfo.getEndTime();
		}
		
		@Override
		public long getDuration() {
			return gcInfo.getDuration();
		}

		@Override
		public long getTimeSincePreviousGC() {
			return gcInterval;
		}

		@Override
		public boolean isYoungGC() {
			return isYoung;
		}

		@Override
		public boolean isConcurrentGC() {
			return isConcurent;
		}

		@Override
		public long getCollectedSize() {
			return getTotalSizeBefore() - getTotalSizeAfter();
		}

		@Override
		public long getPromotedSize() {
			return getSizeAfter(oldPools) - getSizeBefore(oldPools);
		}

		@Override
		public long getTotalSizeBefore() {
			return getSizeBefore(allCollectedPools);
		}

		@Override
		public long getTotalSizeAfter() {
			return getSizeAfter(allCollectedPools);
		}

		@Override
		public Collection getColletedPools() {
			return Collections.unmodifiableCollection(collectedPools);
		}
		
		@Override
		public Collection getAllCollectedPools() {
			return Collections.unmodifiableCollection(allCollectedPools);
		}

		@Override
		public Collection getAllMemoryPools() {
			return Collections.unmodifiableCollection(gcInfo.getMemoryUsageAfterGc().keySet());
		}

		@Override
		public long getSizeBefore(String pool) {
			return gcInfo.getMemoryUsageBeforeGc().get(pool).getUsed();
		}

		@Override
		public long getSizeAfter(String pool) {
			return gcInfo.getMemoryUsageAfterGc().get(pool).getUsed();
		}

		@Override
		public long getSizeBefore(Collection pools) {
			long total = 0;
			for(String pool: pools) {
				total += getSizeBefore(pool);
			}
			return total;
		}
		
		@Override
		public long getSizeAfter(Collection pools) {
			long total = 0;
			for(String pool: pools) {
				total += getSizeAfter(pool);
			}
			return total;
		}

		@Override
		public Collection getEdenPools() {
			List list = new ArrayList(edenPools);
			list.retainAll(gcInfo.getMemoryUsageAfterGc().keySet());
			return list;
		}

		@Override
		public Collection getSurvivourPools() {
			List list = new ArrayList(survivourPools);
			list.retainAll(gcInfo.getMemoryUsageAfterGc().keySet());
			return list;
		}

		@Override
		public Collection getOldSpacePools() {
			List list = new ArrayList(oldPools);
			list.retainAll(gcInfo.getMemoryUsageAfterGc().keySet());
			return list;
		}

		@Override
		public Collection getPermSpacePools() {
			List list = new ArrayList(permPools);
			list.retainAll(gcInfo.getMemoryUsageAfterGc().keySet());
			return list;
		}
	}		
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy