blob: 701ef4e22390de75855350fc291b0da032a5ab92 [file] [log] [blame]
package org.eclipse.osee.ote.core.log;
import java.lang.management.GarbageCollectorMXBean;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.NotificationListener;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.eclipse.osee.framework.logging.OseeLog;
public class GCHelper {
private static final String installGCMonitoring = System.getProperty("org.eclipse.osee.ote.gcmonitor", "true");
private static volatile boolean enableLog = false;
public static void enable(boolean enable){
enableLog = enable;
}
public static void installGCMonitoring(){
if(Boolean.parseBoolean(installGCMonitoring)){
List<GarbageCollectorMXBean> gcbeans = java.lang.management.ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean gcbean : gcbeans) {
NotificationEmitter emitter = (NotificationEmitter) gcbean;
NotificationListener listener = new GCListener();
emitter.addNotificationListener(listener, null, null);
}
}
}
private static class GCListener implements NotificationListener {
private GCNotification gcData;
public void printCompositeDataSupport(Object obj, int level){
if(obj instanceof CompositeDataSupport){
CompositeDataSupport dataSupport = (CompositeDataSupport)obj;
CompositeType type = dataSupport.getCompositeType();
for(String key : type.keySet()){
Object value = dataSupport.get(key);
if(value instanceof CompositeDataSupport || value instanceof TabularDataSupport){
printCompositeDataSupport(value, level + 1);
} else {
if(!populateCompositeData(key, type, value)){
for(int i = 0; i < level; i++){
System.out.print(" ");
}
System.out.printf("key[%s] desc[%s] value[%s] class[%s]\n", key , type.getDescription(key), value, value.getClass().getName());
}
}
}
} else if (obj instanceof TabularDataSupport){
TabularDataSupport dataSupport = (TabularDataSupport)obj;
TabularType type = dataSupport.getTabularType();
for(Object value : dataSupport.values()){
if(value instanceof CompositeDataSupport || value instanceof TabularDataSupport){
printCompositeDataSupport(value, level + 1);
} else {
System.out.println("nope");
}
}
}
else {
if(!populateGenericValue(obj)){
for(int i = 0; i < level; i++){
System.out.print(" ");
}
System.out.printf("valud[%s] class[%s]\n", obj, obj.getClass().getName());
}
}
}
private boolean populateCompositeData(String key, CompositeType type, Object value) {
if(key.equals("GcThreadCount")){
gcData.threadCount = (Integer)value;
return true;
} else if (key.equals("duration")){
gcData.duration = (Long)value;
return true;
} else if (key.equals("endTime")){
gcData.endtime = (Long)value;
return true;
} else if (key.equals("startTime")){
gcData.startTime = (Long)value;
return true;
} else if (key.equals("id")){
//ignore
return true;
} else if (key.equals("key")){
gcData.currentGcMemory = new GCMemory();
gcData.currentGcMemory.memType = GCMemory.getType(value);
if(gcData.currentGcMemory.memType == GCMemory.type.unknown){
System.out.printf("unknown mem type [%s]\n", value);
}
gcData.memory.add(gcData.currentGcMemory);
return true;
} else if (key.equals("committed")){
gcData.currentGcMemory.committed = (Long)value;
return true;
}else if (key.equals("init")){
gcData.currentGcMemory.init = (Long)value;
return true;
}else if (key.equals("max")){
gcData.currentGcMemory.max = (Long)value;
return true;
}else if (key.equals("used")){
gcData.currentGcMemory.used = (Long)value;
return true;
}
return false;
}
private boolean populateGenericValue(Object obj) {
if(obj.toString().equals("end of minor GC")){
gcData.isMinor = true;
return true;
} else if(obj.toString().equals("end of major GC")){
gcData.isMajor = true;
return true;
} else if (obj.toString().equals("System.gc()") || obj.toString().equals("Metadata GC Threshold") || obj.toString().equals("Allocation Failure") ||
obj.toString().equals("PS Scavenge") || obj.toString().equals("PS MarkSweep") || obj.toString().equals("ParNew") || obj.toString().equals("GCLocker Initiated GC")){
if(gcData.reason == null){
gcData.reason = obj.toString();
} else {
gcData.reason = gcData.reason +", " + obj.toString();
}
return true;
}
return false;
}
//implement the notifier callback handler
@Override
public void handleNotification(Notification notification, Object handback) {
if(enableLog){
gcData = new GCNotification();
Object userData = notification.getUserData();
if(userData instanceof CompositeDataSupport){
CompositeDataSupport dataSupport = (CompositeDataSupport)userData;
for(Object obj :dataSupport.values()){
printCompositeDataSupport(obj, 0);
}
} else {
System.out.printf("%s - %s\n", userData.getClass().getName(), userData);
}
OseeLog.log(GCHelper.class, Level.INFO, gcData.toString());
}
}
}
public static class GCNotification {
public String reason;
public Long startTime;
public GCMemory currentGcMemory;
enum gcType { psScavenge, psMarkSweep; }
private gcType type;
private boolean isMajor = false;
private boolean isMinor = false;
private int threadCount;
private long duration;
private long endtime;
private long id;
private List<GCMemory> memory;
public GCNotification(){
memory = new ArrayList<GCHelper.GCMemory>();
currentGcMemory = new GCMemory();
}
public String toString(){
return String.format("GC %s - %s - elapsedTime[%d]", (isMajor ? "major" : "minor"), reason, duration);
}
}
public static class GCMemory {
enum type { compressedClassSpace, psSurvivorSpace, parSurvivorSpace, psOldGen, parOldGen, psEdenSpace, parEdenSpace, Metaspace, CodeCache, unknown; }
private type memType;
private long committed;
private long init;
private long max;
private long used;
public static org.eclipse.osee.ote.core.log.GCHelper.GCMemory.type getType(Object value) {
if(value.equals("Compressed Class Space")){
return type.compressedClassSpace;
} else if (value.equals("PS Survivor Space")){
return type.psSurvivorSpace;
} else if (value.equals("PS Old Gen")){
return type.psOldGen;
} else if (value.equals("Metaspace")){
return type.Metaspace;
} else if (value.equals("PS Eden Space")){
return type.psEdenSpace;
} else if (value.equals("Code Cache")){
return type.CodeCache;
} else if (value.equals("Par Survivor Space")){
return type.parSurvivorSpace;
} else if (value.equals("CMS Old Gen")){
return type.parOldGen;
} else if (value.equals("Par Eden Space")){
return type.parEdenSpace;
}
return type.unknown;
}
}
}