diff --git a/src/java.base/share/classes/sun/evtracing/EventTracing.java b/src/java.base/share/classes/sun/evtracing/EventTracing.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/EventTracing.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class EventTracing {
+
+	private static final EventTracing instance;
+
+	public static EventTracing getEventTracing() {
+		// TODO: check permissions
+		return instance;
+	}
+
+	public static boolean isEnabled() {
+		return instance != null;
+	}
+
+	private StatisticsProvider statisticsProvider;
+
+	private EventTracing() {
+	}
+
+	public native long queueCount(long queueHandle);
+
+	public native TraceBuffer dequeueBuffer(long queueHandle, boolean shouldBlock);
+
+	public native void enqueueBuffer(long queueHandle, long bufferHandle);
+
+	public native void resetAndEnqueueBuffer(long queueHandle, long bufferHandle);
+
+	public native void freeBuffer(long bufferHandle);
+
+	public native void writeGroupEvent(long parkGlobalSeqBeginRef, Object source);
+
+	public native String getConfiguration();
+
+	public Map<String, Double> getStatistics() {
+		Map<String, Double> map = new HashMap<String, Double>() {
+			private static final long serialVersionUID = 1L;
+
+			@Override
+			public Double put(String key, Double value) {
+				Double old = super.put(key, value);
+				assert old == null : "overwriting not permitted";
+				return old;
+			}
+		};
+
+		putNativeStatistics(map);
+		if (statisticsProvider != null) {
+			statisticsProvider.putStatistics(map);
+		}
+		return map;
+	}
+
+	public void resetStatistics() {
+		resetNativeStatistics();
+		if (statisticsProvider != null) {
+			statisticsProvider.resetStatistics();
+		}
+	}
+
+	public void setStatisticsProvider(StatisticsProvider provider) {
+		assert statisticsProvider == null : "already set";
+		this.statisticsProvider = provider;
+	}
+
+	private native void putNativeStatistics(Map<String, Double> map);
+
+	private native void resetNativeStatistics();
+
+	public native void reclaimBuffers(boolean waitUntilProcessed);
+
+	public void resetMetadata() {
+		resetNativeMetadata();
+	}
+
+	private native void resetNativeMetadata();
+
+
+	private static native boolean registerNatives();
+
+	static {
+		if (registerNatives()) {
+			instance = new EventTracing();
+		} else {
+			instance = null;
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/StatisticsProvider.java b/src/java.base/share/classes/sun/evtracing/StatisticsProvider.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/StatisticsProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing;
+
+import java.util.Map;
+
+public interface StatisticsProvider {
+
+	void putStatistics(Map<String, Double> map);
+
+	void resetStatistics();
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/TraceBuffer.java b/src/java.base/share/classes/sun/evtracing/TraceBuffer.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/TraceBuffer.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class TraceBuffer {
+
+	private final long handle;
+	private final ByteBuffer bytes;
+	private final long thread;
+
+	public TraceBuffer(ByteBuffer bytes, long thread) {
+		this.handle = 0xBADBADBADBADBADL;
+		this.bytes = bytes;
+		this.thread = thread;
+	}
+
+	@SuppressWarnings("unused")
+	private TraceBuffer(long handle, ByteBuffer bytes, long thread) {
+		// called only from native
+		assert bytes.isDirect();
+		bytes.order(ByteOrder.nativeOrder());
+
+		this.handle = handle;
+		this.bytes = bytes;
+		this.thread = thread;
+	}
+
+	long handle() {
+		return handle;
+	}
+
+	public ByteBuffer bytes() {
+		return bytes;
+	}
+
+	public long thread() {
+		return thread;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/TraceBufferQueue.java b/src/java.base/share/classes/sun/evtracing/TraceBufferQueue.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/TraceBufferQueue.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing;
+
+public class TraceBufferQueue {
+
+	private static final EventTracing tracing = EventTracing.getEventTracing();
+
+	private final long handle;
+
+	public static TraceBufferQueue fromHandle(long h) {
+		return new TraceBufferQueue(h);
+	}
+
+	private TraceBufferQueue(long handle) {
+		this.handle = handle;
+	}
+
+	public long size() {
+		return tracing.queueCount(handle);
+	}
+
+	public boolean isEmpty() {
+		return (size() == 0);
+	}
+
+	public TraceBuffer dequeue() {
+		return tracing.dequeueBuffer(handle, true);
+	}
+
+	public TraceBuffer tryDequeue() {
+		return tracing.dequeueBuffer(handle, false);
+	}
+
+	public void enqueue(TraceBuffer buffer) {
+		tracing.enqueueBuffer(handle, buffer.handle());
+	}
+
+	public void resetBufferAndEnqueue(TraceBuffer buffer) {
+		tracing.resetAndEnqueueBuffer(handle, buffer.handle());
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/TraceReaderThread.java b/src/java.base/share/classes/sun/evtracing/TraceReaderThread.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/TraceReaderThread.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing;
+
+import static java.lang.System.err;
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import sun.evtracing.parser.TraceParser;
+import sun.evtracing.processing.TraceEventDiagnosticsHandler;
+import sun.evtracing.processing.TraceEventHandler;
+import sun.evtracing.processing.TraceEventJsonWriter;
+import sun.evtracing.processing.TraceEventMetadataResolveHandler;
+import sun.evtracing.processing.TraceEventNopProcessor;
+import sun.evtracing.processing.TraceEventPrintHandler;
+import sun.evtracing.processing.TraceEventReorderHandler;
+import sun.evtracing.processing.TraceEventValidateHandler;
+import sun.evtracing.processing.TraceProcessor;
+import sun.evtracing.processing.io.Compression;
+import sun.evtracing.processing.io.TraceDataChannelWriter;
+import sun.evtracing.processing.statistics.StatisticsPrinter;
+import sun.evtracing.processing.statistics.TraceEventStatisticsHandler;
+
+public class TraceReaderThread implements Runnable {
+
+	private static final EventTracing tracing = EventTracing.getEventTracing();
+
+	private final TraceBufferQueue flushQueue;
+	private final TraceBufferQueue freeQueue;
+
+	private volatile boolean shuttingDown = false;
+	private Runnable onCompletion = () -> {};
+
+	public TraceReaderThread(TraceBufferQueue flushQueue, TraceBufferQueue freeQueue) throws IOException {
+		assert flushQueue != null;
+		this.flushQueue = flushQueue;
+		this.freeQueue = freeQueue;
+	}
+
+	private TraceProcessor initializeProcessor() throws IOException {
+		String config = EventTracing.getEventTracing().getConfiguration();
+		if (config == null || config.isEmpty()) {
+			config = "Statistics";
+		}
+
+		if (config.equals("Nop")) {
+			return new TraceEventNopProcessor();
+		}
+
+		boolean compressedOutput = config.startsWith("CompressedOutput");
+		if (compressedOutput || config.startsWith("Output")) {
+			String path;
+			if (config.startsWith("Output=") || config.startsWith("CompressedOutput=")) {
+				path = config.substring(1 + config.indexOf('='));
+			} else if (config.equals("Output") || config.equals("CompressedOutput")) {
+				path = "output.trc";
+				if (compressedOutput) {
+					path += ".lz4";
+				}
+			} else {
+				throw new RuntimeException("Invalid tracing configuration: '" + config + "'");
+			}
+
+			if (compressedOutput && !Compression.isSupported()) {
+				throw new RuntimeException("Compression not supported in this build");
+			}
+
+			SeekableByteChannel channel = Files.newByteChannel(Paths.get(path), WRITE, CREATE, TRUNCATE_EXISTING);
+			TraceDataChannelWriter writer = new TraceDataChannelWriter(channel, compressedOutput);
+			EventTracing.getEventTracing().setStatisticsProvider(writer);
+			return writer;
+		}
+
+		String[] handlerConfigs = config.split("\\+");
+		String primary = handlerConfigs[0];
+
+		TraceEventHandler handler;
+
+		if (primary.startsWith("Statistics")) {
+			final String path;
+			if (primary.equals("Statistics")) {
+				path = "trace-statistics.txt";
+			} else if (primary.startsWith("Statistics=")) {
+				path = primary.substring(1 + primary.indexOf('='));
+			} else {
+				throw new RuntimeException("Invalid primary handler: '" + primary + "'");
+			}
+			final TraceEventStatisticsHandler statisticsHandler = new TraceEventStatisticsHandler();
+			handler = statisticsHandler;
+
+			onCompletion = (() -> {
+				try (OutputStream out = new FileOutputStream(path)) {
+					new StatisticsPrinter(statisticsHandler.result(), out).print();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			});
+		} else if (primary.startsWith("JsonOutput")) {
+			final String path;
+			if (primary.equals("JsonOutput")) {
+				path = "trace-output.json";
+			} else if (primary.startsWith("JsonOutput=")) {
+				path = primary.substring(1 + primary.indexOf('='));
+			} else {
+				throw new RuntimeException("Invalid primary handler: '" + primary + "'");
+			}
+			handler = new TraceEventJsonWriter(new File(path));
+		} else if (primary.equals("Validate")) {
+			handler = new TraceEventValidateHandler();
+		} else {
+			throw new RuntimeException("Invalid primary handler: '" + primary + "'");
+		}
+
+		for (int i = 1; i < handlerConfigs.length; i++) {
+			String secondary = handlerConfigs[i];
+			if (secondary.equals("Print")) {
+				handler = new TraceEventPrintHandler(handler);
+			} else if (secondary.equals("Diagnostics")) {
+				handler = new TraceEventDiagnosticsHandler(handler);
+			} else {
+				throw new RuntimeException("Invalid secondary handler: '" + secondary + "'");
+			}
+		}
+
+		handler = new TraceEventReorderHandler(handler);
+		handler = new TraceEventMetadataResolveHandler(handler);
+
+		TraceParser parser = new TraceParser(handler, null);
+		EventTracing.getEventTracing().setStatisticsProvider(parser);
+		return parser;
+	}
+
+	void shutdown() {
+		shuttingDown = true;
+	}
+
+	@Override
+	public void run() {
+		try {
+			loop();
+		} catch (Exception e) {
+			e.printStackTrace(err);
+		}
+	}
+
+	@SuppressWarnings("try")
+	private void loop() throws Exception {
+		try (TraceProcessor processor = initializeProcessor()) {
+			while (true) {
+				TraceBuffer tb = flushQueue.dequeue();
+				if (tb == null) {
+					if (!shuttingDown) {
+						throw new RuntimeException("dequeue");
+					}
+					break;
+				}
+
+				processor.process(tb);
+
+				release(tb);
+				tb = null; // do not use after here
+			}
+
+			while (!flushQueue.isEmpty()) {
+				TraceBuffer tb = flushQueue.tryDequeue();
+				assert tb != null;
+
+				processor.process(tb);
+
+				release(tb);
+				tb = null; // do not use after here
+			}
+
+			onCompletion.run();
+		}
+	}
+
+	private void release(TraceBuffer tb) {
+		if (freeQueue != null) {
+			freeQueue.resetBufferAndEnqueue(tb);
+		} else {
+			tracing.freeBuffer(tb.handle());
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ClassLoaderUnloadEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ClassLoaderUnloadEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ClassLoaderUnloadEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ClassLoaderUnloadEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ClassLoaderUnload;
+
+	public static ClassLoaderUnloadEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long classLoader = reader.readClassLoader();
+		return new ClassLoaderUnloadEvent(thread, classLoader);
+	}
+
+	private final long classLoader;
+
+	protected ClassLoaderUnloadEvent(long thread, long classLoader) {
+		super(thread);
+		this.classLoader = classLoader;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long classLoader() {
+		return classLoader;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.classLoaderUnload(this);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ClassMetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ClassMetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ClassMetadataEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ClassMetadataEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ClassMetadata;
+
+	public static ClassMetadataEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long clazz = reader.readClassId();
+		long classLoader = reader.readClassLoader();
+		String name = reader.readString();
+		return new ClassMetadataEvent(thread, clazz, classLoader, name);
+	}
+
+	private final long clazz;
+	private final long classLoader;
+	private final String name;
+
+	private ClassMetadataEvent(long thread, long clazz, long classLoader, String name) {
+		super(thread);
+		this.classLoader = classLoader;
+		this.clazz = clazz;
+		this.name = name;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long clazz() {
+		return clazz;
+	}
+
+	public long classLoader() {
+		return classLoader;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.classMetadata(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/GlobalSequenceOrderedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/GlobalSequenceOrderedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/GlobalSequenceOrderedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+
+public abstract class GlobalSequenceOrderedEvent extends SequenceOrderedEvent {
+
+	protected GlobalSequenceOrderedEvent(long thread, long timestamp, long sequenceNumber) {
+		super(thread, timestamp, sequenceNumber);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/GroupEvent.java b/src/java.base/share/classes/sun/evtracing/parser/GroupEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/GroupEvent.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class GroupEvent extends GlobalSequenceOrderedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.Group;
+
+	public static GroupEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long sequenceBeginReference = reader.readSequenceNumber();
+		int obj = reader.readObject();
+		MetadataRef<JavaClass> clazz = reader.readClass();
+		return new GroupEvent(thread, timestamp, sequenceNumber, sequenceBeginReference, obj, clazz);
+	}
+
+	private final long sequenceBeginReference;
+	private final int obj;
+	private final MetadataRef<JavaClass> clazz;
+
+	protected GroupEvent(long thread, long timestamp, long sequenceNumber, long sequenceBeginReference, int obj, MetadataRef<JavaClass> clazz) {
+		super(thread, timestamp, sequenceNumber);
+		this.sequenceBeginReference = sequenceBeginReference;
+		this.obj = obj;
+		this.clazz = clazz;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long sequenceBeginReference() {
+		return sequenceBeginReference;
+	}
+
+	public int obj() {
+		return obj;
+	}
+
+	public MetadataRef<JavaClass> clazz() {
+		return clazz;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.group(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/IdenticalStacksMetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/IdenticalStacksMetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/IdenticalStacksMetadataEvent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class IdenticalStacksMetadataEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.IdenticalStacksMetadata;
+
+	public static IdenticalStacksMetadataEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long stack = reader.readStackId();
+		long known = reader.readStackId();
+		return new IdenticalStacksMetadataEvent(thread, stack, known);
+	}
+
+	private final long stack;
+	private final long knownStack;
+
+	protected IdenticalStacksMetadataEvent(long thread, long stack, long knownStack) {
+		super(thread);
+		this.stack = stack;
+		this.knownStack = knownStack;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long stack() {
+		return stack;
+	}
+
+	public long knownStack() {
+		return knownStack;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.identicalStacksMetadata(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MarkerEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MarkerEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MarkerEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MarkerEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.Marker;
+
+	public static MarkerEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long time = reader.readTimestamp();
+		String label = reader.readString();
+		return new MarkerEvent(thread, time, label);
+	}
+
+	private final String label;
+
+	protected MarkerEvent(long thread, long timestamp, String label) {
+		super(thread, timestamp);
+		this.label = label;
+	}
+
+	public String label() {
+		return label;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.marker(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MetadataEvent.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+public abstract class MetadataEvent extends TraceEvent {
+
+	protected MetadataEvent(long thread) {
+		super(thread);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MetadataResetEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MetadataResetEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MetadataResetEvent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MetadataResetEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MetadataReset;
+
+	public static MetadataResetEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		return new MetadataResetEvent(thread);
+	}
+
+	public MetadataResetEvent(long thread) {
+		super(thread);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.metadataReset(this);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MethodMetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MethodMetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MethodMetadataEvent.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MethodMetadataEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MethodMetadata;
+
+	public static MethodMetadataEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long method = reader.readMethodId();
+		MetadataRef<JavaClass> clazz = reader.readClass();
+		String name = reader.readString();
+		String signature = reader.readString();
+		return new MethodMetadataEvent(thread, method, clazz, name, signature);
+	}
+
+	private final long method;
+	private final MetadataRef<JavaClass> clazz;
+	private final String name;
+	private final String signature;
+
+	private MethodMetadataEvent(long thread, long method, MetadataRef<JavaClass> clazz, String name, String signature) {
+		super(thread);
+		this.method = method;
+		this.clazz = clazz;
+		this.name = name;
+		this.signature = signature;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long method() {
+		return method;
+	}
+
+	public MetadataRef<JavaClass> clazz() {
+		return clazz;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	public String signature() {
+		return signature;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.methodMetadata(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnterEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnterEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnterEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorContendedEnterEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorContendedEnter;
+
+	public static MonitorContendedEnterEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		MonitorEnterWait wait = reader.readMonitorEnterWait();
+		return new MonitorContendedEnterEvent(thread, timestamp, sequenceNumber, monitor, stack, wait);
+	}
+
+	private final MetadataRef<JavaStack> stack;
+	private final MonitorEnterWait afterWait;
+
+	protected MonitorContendedEnterEvent(long thread, long timestamp, long sequenceNumber, long monitor, MetadataRef<JavaStack> stack, MonitorEnterWait wait) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.stack = stack;
+		this.afterWait = wait;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	public MonitorEnterWait afterWait() {
+		return afterWait;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorContendedEnter(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnteredEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnteredEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedEnteredEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.util.EnumSet;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorContendedEnteredEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorContendedEntered;
+
+	private final EnumSet<MonitorEnteredFlags> flags;
+
+	public static MonitorContendedEnteredEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		EnumSet<MonitorEnteredFlags> flags = reader.readMonitorEnteredFlags();
+		return new MonitorContendedEnteredEvent(thread, timestamp, sequenceNumber, monitor, flags);
+	}
+
+	protected MonitorContendedEnteredEvent(long thread, long timestamp, long sequenceNumber, long monitor, EnumSet<MonitorEnteredFlags> flags) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.flags = flags;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public EnumSet<MonitorEnteredFlags> flags() {
+		return flags;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorContendedEntered(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedExitedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedExitedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorContendedExitedEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorContendedExitedEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorContendedExited;
+
+	public static MonitorContendedExitedEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		return new MonitorContendedExitedEvent(thread, timestamp, sequenceNumber, monitor, stack);
+	}
+
+	private final MetadataRef<JavaStack> stack;
+
+	protected MonitorContendedExitedEvent(long thread, long timestamp, long sequenceNumber, long monitor, MetadataRef<JavaStack> stack) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.stack = stack;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorContendedExited(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorDeflateEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorDeflateEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorDeflateEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorDeflateEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorDeflate;
+
+	public static MonitorDeflateEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		return new MonitorDeflateEvent(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	protected MonitorDeflateEvent(long thread, long timestamp, long sequenceNumber, long monitor) {
+		super(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorDeflate(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorDummyEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorDummyEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorDummyEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorDummyEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorDummy;
+
+	public static MonitorDummyEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		return new MonitorDummyEvent(thread, sequenceNumber, monitor);
+	}
+
+	protected MonitorDummyEvent(long thread, long sequenceNumber, long monitor) {
+		super(thread, -1, sequenceNumber, monitor);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorDummy(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorEnterWait.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorEnterWait.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorEnterWait.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+public enum MonitorEnterWait {
+	NoWait,
+	WaitNotify,
+	WaitTimeout,
+	WaitOther; /* interrupt or spurious wakeup */
+
+	private static final MonitorEnterWait[] VALUES = values();
+
+	public static MonitorEnterWait fromOrdinal(int index) {
+		return VALUES[index];
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorEnteredFlags.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorEnteredFlags.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorEnteredFlags.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.util.EnumSet;
+
+public enum MonitorEnteredFlags {
+	Queued(1 << 0),
+	Parked(1 << 1);
+
+	private final int bit;
+
+	private MonitorEnteredFlags(int bit) {
+		this.bit = bit;
+	}
+
+	private static final MonitorEnteredFlags[] VALUES = values();
+
+	@SuppressWarnings({"unchecked", "rawtypes"})
+	private static final EnumSet<MonitorEnteredFlags>[] cache = new EnumSet[1 << VALUES.length];
+
+	public static EnumSet<MonitorEnteredFlags> fromBits(int value) {
+		if (cache[value] == null) {
+			EnumSet<MonitorEnteredFlags> flags = EnumSet.noneOf(MonitorEnteredFlags.class);
+			for (MonitorEnteredFlags flag : VALUES) {
+				if ((value & flag.bit) == flag.bit) {
+					flags.add(flag);
+				}
+			}
+			cache[value] = flags;
+		}
+		return cache[value];
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+public abstract class MonitorEvent extends SequenceOrderedEvent {
+
+	private final long monitor;
+
+	protected MonitorEvent(long thread, long timestamp, long sequenceNumber, long monitor) {
+		super(thread, timestamp, sequenceNumber);
+		this.monitor = monitor;
+	}
+
+	public long monitor() {
+		return monitor;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/MonitorInflateEvent.java b/src/java.base/share/classes/sun/evtracing/parser/MonitorInflateEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/MonitorInflateEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class MonitorInflateEvent extends MonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.MonitorInflate;
+
+	public static MonitorInflateEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readMonitor();
+		int object = reader.readObject();
+		MetadataRef<JavaClass> clazz = reader.readClass();
+		return new MonitorInflateEvent(thread, timestamp, sequenceNumber, monitor, object, clazz);
+	}
+
+	private final int object;
+	private final MetadataRef<JavaClass> clazz;
+
+	protected MonitorInflateEvent(long thread, long timestamp, long sequenceNumber, long monitor, int object, MetadataRef<JavaClass> klass) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.object = object;
+		this.clazz = klass;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public int object() {
+		return object;
+	}
+
+	public MetadataRef<JavaClass> clazz() {
+		return clazz;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.monitorInflate(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockEvent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorContendedLockEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorContendedLock;
+
+	public static NativeMonitorContendedLockEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		MonitorEnterWait wait = reader.readMonitorEnterWait();
+		return new NativeMonitorContendedLockEvent(thread, timestamp, sequenceNumber, monitor, stack, wait);
+	}
+
+	private final MetadataRef<JavaStack> stack;
+	private final MonitorEnterWait afterWait;
+
+	protected NativeMonitorContendedLockEvent(long thread, long timestamp, long sequenceNumber, long monitor, MetadataRef<JavaStack> stack, MonitorEnterWait wait) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.afterWait = wait;
+		this.stack = stack;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	public MonitorEnterWait afterWait() {
+		return afterWait;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorContendedLock(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedLockedEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorContendedLockedEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorContendedLocked;
+
+	public static NativeMonitorContendedLockedEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		return new NativeMonitorContendedLockedEvent(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	protected NativeMonitorContendedLockedEvent(long thread, long timestamp, long sequenceNumber, long monitor) {
+		super(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorContendedLocked(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedUnlockedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedUnlockedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorContendedUnlockedEvent.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorContendedUnlockedEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorContendedUnlocked;
+
+	public static NativeMonitorContendedUnlockedEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		return new NativeMonitorContendedUnlockedEvent(thread, timestamp, sequenceNumber, monitor, stack);
+	}
+
+	private final MetadataRef<JavaStack> stack;
+
+	protected NativeMonitorContendedUnlockedEvent(long thread, long timestamp, long sequenceNumber, long monitor, MetadataRef<JavaStack> stack) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.stack = stack;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorContendedUnlocked(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDestroyEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDestroyEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDestroyEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorDestroyEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorDestroy;
+
+	public static NativeMonitorDestroyEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		return new NativeMonitorDestroyEvent(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	protected NativeMonitorDestroyEvent(long thread, long timestamp, long sequenceNumber, long monitor) {
+		super(thread, timestamp, sequenceNumber, monitor);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorDestroy(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDummyEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDummyEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorDummyEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorDummyEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorDummy;
+
+	public static NativeMonitorDummyEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		return new NativeMonitorDummyEvent(thread, sequenceNumber, monitor);
+	}
+
+	protected NativeMonitorDummyEvent(long thread, long sequenceNumber, long monitor) {
+		super(thread, -1, sequenceNumber, monitor);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorDummy(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+public abstract class NativeMonitorEvent extends SequenceOrderedEvent {
+
+	private final long monitor;
+
+	protected NativeMonitorEvent(long thread, long timestamp, long sequenceNumber, long monitor) {
+		super(thread, timestamp, sequenceNumber);
+		this.monitor = monitor;
+	}
+
+	public long monitor() {
+		return monitor;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorInfoEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorInfoEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeMonitorInfoEvent.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeMonitorInfoEvent extends NativeMonitorEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeMonitorInfo;
+
+	public static NativeMonitorInfoEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long monitor = reader.readNativeMonitor();
+		String name = reader.readString();
+		return new NativeMonitorInfoEvent(thread, timestamp, sequenceNumber, monitor, name);
+	}
+
+	private final String name;
+
+	protected NativeMonitorInfoEvent(long thread, long timestamp, long sequenceNumber, long monitor, String name) {
+		super(thread, timestamp, sequenceNumber, monitor);
+		this.name = name;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeMonitorInfo(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/NativeSymbolMetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/NativeSymbolMetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/NativeSymbolMetadataEvent.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class NativeSymbolMetadataEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.NativeSymbolMetadata;
+
+	public static NativeSymbolMetadataEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long address = reader.readNativeAddress();
+		String description = reader.readString();
+		return new NativeSymbolMetadataEvent(thread, address, description);
+	}
+
+	private final long address;
+	private final String description;
+
+	private NativeSymbolMetadataEvent(long thread, long address, String description) {
+		super(thread);
+		this.address = address;
+		this.description = description;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long address() {
+		return address;
+	}
+
+	public String description() {
+		return description;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.nativeSymbolMetadata(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ParkReturnCode.java b/src/java.base/share/classes/sun/evtracing/parser/ParkReturnCode.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ParkReturnCode.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+public enum ParkReturnCode {
+	Normal,
+	TimedOut,
+	ImmediateFast,
+	InterruptedFast,
+	NoWaitTime,
+	InterruptedSlow,
+	Locked,
+	ImmediateSlow,
+	Unknown;
+
+	private static final ParkReturnCode[] VALUES = values();
+
+	public static ParkReturnCode fromOrdinal(int index) {
+		return VALUES[index];
+	}
+
+	public boolean hasUnpark() {
+		switch (this) {
+		case InterruptedFast:
+		case InterruptedSlow:
+		case NoWaitTime:
+		case Locked:
+		case TimedOut:
+			return false;
+		case Normal:
+		case ImmediateFast:
+		case ImmediateSlow:
+			return true;
+		case Unknown:
+		default:
+			throw new RuntimeException("Unknown park return code " + this);
+		}
+	}
+
+	public boolean causedContention() {
+		switch (this) {
+		case ImmediateFast:
+		case ImmediateSlow:
+		case InterruptedFast:
+		case InterruptedSlow:
+		case NoWaitTime:
+		case Locked:
+			return false;
+		case TimedOut:
+		case Normal:
+			return true;
+		case Unknown:
+		default:
+			throw new RuntimeException("Unknown park return code " + this);
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/SafepointBeginEvent.java b/src/java.base/share/classes/sun/evtracing/parser/SafepointBeginEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/SafepointBeginEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class SafepointBeginEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.SafepointBegin;
+
+	public static SafepointBeginEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		SafepointReason reason = reader.readSafepointReason();
+		return new SafepointBeginEvent(thread, timestamp, reason);
+	}
+
+	private final SafepointReason reason;
+
+	protected SafepointBeginEvent(long thread, long timestamp, SafepointReason reason) {
+		super(thread, timestamp);
+		this.reason = reason;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public SafepointReason reason() {
+		return reason;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.safepointBegin(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/SafepointEndEvent.java b/src/java.base/share/classes/sun/evtracing/parser/SafepointEndEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/SafepointEndEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class SafepointEndEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.SafepointEnd;
+
+	public static SafepointEndEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		int processedOps = reader.readUnsignedByte();
+		return new SafepointEndEvent(thread, timestamp, processedOps);
+	}
+
+	private final int processedOps;
+
+	protected SafepointEndEvent(long thread, long timestamp, int processedOps) {
+		super(thread, timestamp);
+		this.processedOps = processedOps;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public int processedOps() {
+		return processedOps;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.safepointEnd(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/SafepointReason.java b/src/java.base/share/classes/sun/evtracing/parser/SafepointReason.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/SafepointReason.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+public enum SafepointReason {
+	Periodic,
+	ForVMOperation;
+
+	private static final SafepointReason[] VALUES = values();
+
+	public static SafepointReason fromOrdinal(int index) {
+		return VALUES[index];
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/SequenceOrderedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/SequenceOrderedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/SequenceOrderedEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+public abstract class SequenceOrderedEvent extends TimestampedEvent {
+
+	private final long sequenceNumber;
+
+	protected SequenceOrderedEvent(long thread, long timestamp, long sequenceNumber) {
+		super(thread, timestamp);
+		this.sequenceNumber = sequenceNumber;
+	}
+
+	public long sequenceNumber() {
+		return sequenceNumber;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/StackFrameKind.java b/src/java.base/share/classes/sun/evtracing/parser/StackFrameKind.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/StackFrameKind.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+public enum StackFrameKind {
+	Java,
+	Native;
+
+	private static final StackFrameKind[] VALUES = values();
+
+	public static StackFrameKind fromOrdinal(int index) {
+		return VALUES[index];
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/StackMetadataEvent.java b/src/java.base/share/classes/sun/evtracing/parser/StackMetadataEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/StackMetadataEvent.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class StackMetadataEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.StackMetadata;
+
+	public static StackMetadataEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long stack = reader.readStackId();
+		boolean truncated = reader.readBoolean();
+		int count = reader.readUnsignedShort();
+		long[] methods = new long[count];
+		int[] bcis = new int[count];
+		for (int i = 0; i < count; i++) {
+			methods[i] = reader.readMethodId();
+			bcis[i] = reader.readBytecodeIndex();
+			assert bcis[i] >= -1;
+		}
+		return new StackMetadataEvent(thread, stack, truncated, methods, bcis);
+	}
+
+	private final long stack;
+	private final boolean truncated;
+	private final long[] methods;
+	private final int[] bcis;
+
+	protected StackMetadataEvent(long thread, long stack, boolean truncated, long[] methods, int[] bcis) {
+		super(thread);
+		this.stack = stack;
+		this.truncated = truncated;
+		this.methods = methods;
+		this.bcis = bcis;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long stack() {
+		return stack;
+	}
+
+	public boolean isTruncated() {
+		return truncated;
+	}
+
+	public long[] methods() {
+		return methods;
+	}
+
+	public int[] bcis() {
+		return bcis;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.stackMetadata(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/StackMetadataExtendedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/StackMetadataExtendedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/StackMetadataExtendedEvent.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class StackMetadataExtendedEvent extends MetadataEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.StackMetadataExtended;
+
+	public static StackMetadataExtendedEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long stack = reader.readStackId();
+		boolean truncated = reader.readBoolean();
+		int count = reader.readUnsignedShort();
+		StackFrameKind[] kinds = new StackFrameKind[count];
+		long[] methods = new long[count];
+		int[] bcis = new int[count];
+		for (int i = 0; i < count; i++) {
+			kinds[i] = reader.readStackFrameKind();
+			if (kinds[i] == StackFrameKind.Java) {
+				methods[i] = reader.readMethodId();
+				bcis[i] = reader.readBytecodeIndex();
+				assert bcis[i] >= -1;
+			} else {
+				methods[i] = reader.readNativeAddress();
+			}
+		}
+		return new StackMetadataExtendedEvent(thread, stack, truncated, kinds, methods, bcis);
+	}
+
+	private final long stack;
+	private final boolean truncated;
+	private final StackFrameKind[] kinds;
+	private final long[] methods;
+	private final int[] bcis;
+
+	protected StackMetadataExtendedEvent(long thread, long stack, boolean truncated, StackFrameKind[] kinds, long[] methods, int[] bcis) {
+		super(thread);
+		this.stack = stack;
+		this.truncated = truncated;
+		this.kinds = kinds;
+		this.methods = methods;
+		this.bcis = bcis;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long stack() {
+		return stack;
+	}
+
+	public boolean isTruncated() {
+		return truncated;
+	}
+
+	public StackFrameKind[] kinds() {
+		return kinds;
+	}
+
+	public long[] methods() {
+		return methods;
+	}
+
+	public int[] bcis() {
+		return bcis;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.stackMetadataExtended(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadExitEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadExitEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadExitEvent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadExitEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadExit;
+
+	public static ThreadExitEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		return new ThreadExitEvent(thread, timestamp);
+	}
+
+	protected ThreadExitEvent(long thread, long timestamp) {
+		super(thread, timestamp);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadExit(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadInterruptEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadInterruptEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadInterruptEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadInterruptEvent extends GlobalSequenceOrderedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadInterrupt;
+
+	public static ThreadInterruptEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		MetadataRef<JavaThread> affectedThread = reader.readThread();
+		return new ThreadInterruptEvent(thread, timestamp, sequenceNumber, affectedThread);
+	}
+
+	private final MetadataRef<JavaThread> affectedThread;
+
+	protected ThreadInterruptEvent(long thread, long timestamp, long sequenceNumber, MetadataRef<JavaThread> affectedThread) {
+		super(thread, timestamp, sequenceNumber);
+		this.affectedThread = affectedThread;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaThread> affectedThread() {
+		return affectedThread;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadInterrupt(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadNameChangeEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadNameChangeEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadNameChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadNameChangeEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadNameChange;
+
+	public static ThreadNameChangeEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		MetadataRef<JavaThread> affectedThread = reader.readThread();
+		String name = reader.readString();
+		return new ThreadNameChangeEvent(thread, timestamp, affectedThread, name);
+	}
+
+	private final MetadataRef<JavaThread> affectedThread;
+	private final String newName;
+
+	protected ThreadNameChangeEvent(long actingThread, long timestamp, MetadataRef<JavaThread> affectedThread, String newName) {
+		super(actingThread, timestamp);
+		this.affectedThread = affectedThread;
+		this.newName = newName;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public String newName() {
+		return newName;
+	}
+
+	public MetadataRef<JavaThread> affectedThread() {
+		return affectedThread;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadNameChange(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadParkBeginEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadParkBeginEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadParkBeginEvent.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadParkBeginEvent extends GlobalSequenceOrderedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadParkBegin;
+
+	public static ThreadParkBeginEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		int blockerObject = reader.readObject();
+		MetadataRef<JavaClass> clazz = reader.readClass();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		int nestingLevel = reader.readUnsignedByte();
+		boolean isAbsolute = reader.readBoolean();
+		long parkTime = reader.readDuration();
+		return new ThreadParkBeginEvent(thread, timestamp, sequenceNumber, blockerObject, clazz, stack, nestingLevel, isAbsolute, parkTime);
+	}
+
+	private final int blockerObject;
+	private final MetadataRef<JavaClass> clazz;
+	private final MetadataRef<JavaStack> stack;
+	private final int nestingLevel;
+	private final boolean isAbsolute;
+	private final long parkTime;
+
+	protected ThreadParkBeginEvent(long thread, long timestamp, long sequenceNumber, int blockerObject, MetadataRef<JavaClass> clazz, MetadataRef<JavaStack> stack, int nestingLevel, boolean isAbsolute, long parkTime) {
+		super(thread, timestamp, sequenceNumber);
+		this.blockerObject = blockerObject;
+		this.clazz = clazz;
+		this.stack = stack;
+		this.nestingLevel = nestingLevel;
+		this.isAbsolute = isAbsolute;
+		this.parkTime = parkTime;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public int blockerObject() {
+		return blockerObject;
+	}
+
+	public MetadataRef<JavaClass> clazz() {
+		return clazz;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	public int nestingLevel() {
+		return nestingLevel;
+	}
+
+	public boolean isAbsolute() {
+		return isAbsolute;
+	}
+
+	public long parkTime() {
+		return parkTime;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadParkBegin(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadParkEndEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadParkEndEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadParkEndEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadParkEndEvent extends GlobalSequenceOrderedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadParkEnd;
+
+	public static ThreadParkEndEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long unparkSequenceNumber = reader.readSequenceNumber();
+		ParkReturnCode parkReturnCode = reader.readParkReturnCode();
+		return new ThreadParkEndEvent(thread, timestamp, sequenceNumber, unparkSequenceNumber, parkReturnCode);
+	}
+
+	private final long unparkSequenceNumber;
+	private final ParkReturnCode parkReturnCode;
+
+	protected ThreadParkEndEvent(long thread, long timestamp, long sequenceNumber, long unparkSequenceNumber, ParkReturnCode parkReturnCode) {
+		super(thread, timestamp, sequenceNumber);
+		this.unparkSequenceNumber = unparkSequenceNumber;
+		this.parkReturnCode = parkReturnCode;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long unparkSequenceNumber() {
+		return unparkSequenceNumber;
+	}
+
+	public ParkReturnCode parkReturnCode() {
+		return parkReturnCode;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadParkEnd(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadStartEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadStartEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadStartEvent.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadStartEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadStart;
+
+	public static ThreadStartEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		String name = reader.readString();
+		return new ThreadStartEvent(thread, timestamp, name);
+	}
+
+	private final String name;
+
+	protected ThreadStartEvent(long thread, long timestamp, String name) {
+		super(thread, timestamp);
+		this.name = name;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadStart(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadState.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadState.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadState.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.lang.Thread.State;
+
+public class ThreadState {
+
+	static final int JVMTI_THREAD_STATE_ALIVE = 0x0001,
+			JVMTI_THREAD_STATE_TERMINATED = 0x0002,
+			JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
+			JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
+			JVMTI_THREAD_STATE_WAITING = 0x0080,
+			JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
+			JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
+			JVMTI_THREAD_STATE_SLEEPING = 0x0040,
+			JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
+			JVMTI_THREAD_STATE_PARKED = 0x0200,
+			JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
+			JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
+			JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
+			JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
+			JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
+			JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000;
+
+	static final int
+			JVMTI_JAVA_LANG_THREAD_STATE_MASK =
+					  JVMTI_THREAD_STATE_TERMINATED
+					| JVMTI_THREAD_STATE_ALIVE
+					| JVMTI_THREAD_STATE_RUNNABLE
+					| JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
+					| JVMTI_THREAD_STATE_WAITING
+					| JVMTI_THREAD_STATE_WAITING_INDEFINITELY
+					| JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
+			JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
+			JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
+			JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE
+					| JVMTI_THREAD_STATE_RUNNABLE,
+			JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE
+					| JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
+			JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE
+					| JVMTI_THREAD_STATE_WAITING
+					| JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
+			JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE
+					| JVMTI_THREAD_STATE_WAITING
+					| JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT;
+
+	public static ThreadState fromFlags(int mask) {
+		return new ThreadState(mask);
+	}
+
+	private int flags;
+
+	private ThreadState(int flags) {
+		// TODO: validate somehow?
+		this.flags = flags;
+	}
+
+	public boolean isInNative() {
+		return (flags & JVMTI_THREAD_STATE_IN_NATIVE) != 0;
+	}
+
+	public boolean isSuspended() {
+		return (flags & JVMTI_THREAD_STATE_SUSPENDED) != 0;
+	}
+
+	public boolean isInterrupted() {
+		return (flags & JVMTI_THREAD_STATE_INTERRUPTED) != 0;
+	}
+
+	public Thread.State toThreadState() {
+		switch (flags & JVMTI_JAVA_LANG_THREAD_STATE_MASK) {
+		case JVMTI_JAVA_LANG_THREAD_STATE_NEW:
+			return State.NEW;
+		case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED:
+			return State.TERMINATED;
+		case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE:
+			return State.RUNNABLE;
+		case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED:
+			return State.BLOCKED;
+		case JVMTI_JAVA_LANG_THREAD_STATE_WAITING:
+			return State.WAITING;
+		case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING:
+			return State.TIMED_WAITING;
+		default:
+			throw new RuntimeException("illegal state");
+		}
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(toThreadState().toString().toLowerCase());
+		if (isInNative()) {
+			sb.append("+native");
+		}
+		if (isSuspended()) {
+			sb.append("+suspended");
+		}
+		if (isInterrupted()) {
+			sb.append("+interrupted");
+		}
+		return sb.toString();
+	}
+
+	@Override
+	public int hashCode() {
+		return flags;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj != null && obj instanceof ThreadState) {
+			return (flags == ((ThreadState) obj).flags);
+		}
+		return false;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadStateChangeEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadStateChangeEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadStateChangeEvent.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadStateChangeEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadStateChange;
+
+	public static ThreadStateChangeEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		MetadataRef<JavaThread> affectedThread = reader.readThread();
+		ThreadState newState = reader.readThreadState();
+		return new ThreadStateChangeEvent(thread, timestamp, affectedThread, newState);
+	}
+
+	private final MetadataRef<JavaThread> affectedThread;
+	private final ThreadState newState;
+
+	protected ThreadStateChangeEvent(long thread, long timestamp, MetadataRef<JavaThread> affectedThread, ThreadState newState) {
+		super(thread, timestamp);
+		this.affectedThread = affectedThread;
+		this.newState = newState;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public MetadataRef<JavaThread> affectedThread() {
+		return affectedThread;
+	}
+
+	public ThreadState newState() {
+		return newState;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadStateChange(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/ThreadUnparkEvent.java b/src/java.base/share/classes/sun/evtracing/parser/ThreadUnparkEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/ThreadUnparkEvent.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class ThreadUnparkEvent extends GlobalSequenceOrderedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.ThreadUnpark;
+
+	public static ThreadUnparkEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		long sequenceNumber = reader.readSequenceNumber();
+		long chainedSequenceNumber = reader.readSequenceNumber();
+		MetadataRef<JavaThread> unparkedThread = reader.readThread();
+		MetadataRef<JavaStack> stack = reader.readStack();
+		return new ThreadUnparkEvent(thread, timestamp, sequenceNumber, chainedSequenceNumber, unparkedThread, stack);
+	}
+
+	private final long chainedSequenceNumber;
+	private final MetadataRef<JavaThread> unparkedThread;
+	private final MetadataRef<JavaStack> stack;
+
+	protected ThreadUnparkEvent(long thread, long timestamp, long sequenceNumber, long chainedSequenceNumber, MetadataRef<JavaThread> unparkedThread, MetadataRef<JavaStack> stack) {
+		super(thread, timestamp, sequenceNumber);
+		this.chainedSequenceNumber = chainedSequenceNumber;
+		this.unparkedThread = unparkedThread;
+		this.stack = stack;
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	public long chainedSequenceNumber() {
+		return chainedSequenceNumber;
+	}
+
+	public MetadataRef<JavaThread> unparkedThread() {
+		return unparkedThread;
+	}
+
+	public MetadataRef<JavaStack> stack() {
+		return stack;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.threadUnpark(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TimestampedEvent.java b/src/java.base/share/classes/sun/evtracing/parser/TimestampedEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TimestampedEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+
+public abstract class TimestampedEvent extends TraceEvent {
+
+	private final long timestamp;
+
+	protected TimestampedEvent(long thread, long timestamp) {
+		super(thread);
+		this.timestamp = timestamp;
+	}
+
+	public long timestamp() {
+		return timestamp;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TraceEvent.java b/src/java.base/share/classes/sun/evtracing/parser/TraceEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TraceEvent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.processing.TraceEventHandler;
+
+public abstract class TraceEvent {
+
+	private final MetadataRef<JavaThread> thread;
+
+	protected TraceEvent(long thread) {
+		this.thread = new MetadataRef<>(thread);
+	}
+
+	public MetadataRef<JavaThread> thread() {
+		return thread;
+	}
+
+	public abstract TraceEventType type();
+
+	public abstract void accept(TraceEventHandler handler);
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TraceEventType.java b/src/java.base/share/classes/sun/evtracing/parser/TraceEventType.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TraceEventType.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+public enum TraceEventType {
+	ThreadStart,
+	ThreadNameChange,
+	ThreadStateChange,
+	ThreadInterrupt,
+	ThreadExit,
+	ThreadParkBegin,
+	ThreadParkEnd,
+	ThreadUnpark,
+	MonitorInflate,
+	MonitorDeflate,
+	MonitorContendedEnter,
+	MonitorContendedEntered,
+	MonitorContendedExited,
+	MonitorDummy,
+	ClassMetadata,
+	MethodMetadata,
+	StackMetadata,
+	IdenticalStacksMetadata,
+	ClassLoaderUnload,
+	SafepointBegin,
+	SafepointEnd,
+	VMEnd,
+	MetadataReset,
+	Group,
+	NativeMonitorInfo,
+	NativeMonitorContendedLock,
+	NativeMonitorContendedLocked,
+	NativeMonitorContendedUnlocked,
+	NativeMonitorDestroy,
+	NativeMonitorDummy,
+	StackMetadataExtended,
+	NativeSymbolMetadata,
+	Marker,
+	;
+
+	private static final TraceEventType[] VALUES = values();
+
+	public static TraceEventType fromOrdinal(int value) {
+		return VALUES[value];
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TraceParser.java b/src/java.base/share/classes/sun/evtracing/parser/TraceParser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TraceParser.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.util.Map;
+
+import sun.evtracing.StatisticsProvider;
+import sun.evtracing.TraceBuffer;
+import sun.evtracing.processing.ProgressCallback;
+import sun.evtracing.processing.TraceEventHandler;
+import sun.evtracing.processing.TraceProcessor;
+
+public class TraceParser implements TraceProcessor, StatisticsProvider {
+
+	private final TraceEventHandler handler;
+	private final ProgressCallback progressCallback;
+	private long bytesProcessed;
+
+	public TraceParser(TraceEventHandler handler, ProgressCallback callback) {
+		this.handler = handler;
+		this.progressCallback = callback;
+	}
+
+	@Override
+	public void process(TraceBuffer buffer) {
+		TraceReader reader = new TraceReader(buffer.bytes());
+		final long thread = buffer.thread();
+		while (reader.hasMore()) {
+			byte t = reader.peekByte();
+			switch (TraceEventType.fromOrdinal(t)) {
+			case ThreadStart:
+				handler.threadStart(ThreadStartEvent.parse(reader, thread));
+				break;
+
+			case ThreadNameChange:
+				handler.threadNameChange(ThreadNameChangeEvent.parse(reader, thread));
+				break;
+
+			case ThreadStateChange:
+				handler.threadStateChange(ThreadStateChangeEvent.parse(reader, thread));
+				break;
+
+			case ThreadInterrupt:
+				handler.threadInterrupt(ThreadInterruptEvent.parse(reader, thread));
+				break;
+
+			case ThreadExit:
+				handler.threadExit(ThreadExitEvent.parse(reader, thread));
+				break;
+
+			case ThreadParkBegin:
+				handler.threadParkBegin(ThreadParkBeginEvent.parse(reader, thread));
+				break;
+
+			case ThreadParkEnd:
+				handler.threadParkEnd(ThreadParkEndEvent.parse(reader, thread));
+				break;
+
+			case ThreadUnpark:
+				handler.threadUnpark(ThreadUnparkEvent.parse(reader, thread));
+				break;
+
+			case MonitorInflate:
+				handler.monitorInflate(MonitorInflateEvent.parse(reader, thread));
+				break;
+
+			case MonitorDeflate:
+				handler.monitorDeflate(MonitorDeflateEvent.parse(reader, thread));
+				break;
+
+			case MonitorContendedEnter:
+				handler.monitorContendedEnter(MonitorContendedEnterEvent.parse(reader, thread));
+				break;
+
+			case MonitorContendedEntered:
+				handler.monitorContendedEntered(MonitorContendedEnteredEvent.parse(reader, thread));
+				break;
+
+			case MonitorContendedExited:
+				handler.monitorContendedExited(MonitorContendedExitedEvent.parse(reader, thread));
+				break;
+
+			case MonitorDummy:
+				handler.monitorDummy(MonitorDummyEvent.parse(reader, thread));
+				break;
+
+			case ClassMetadata:
+				handler.classMetadata(ClassMetadataEvent.parse(reader, thread));
+				break;
+
+			case MethodMetadata:
+				handler.methodMetadata(MethodMetadataEvent.parse(reader, thread));
+				break;
+
+			case StackMetadata:
+				handler.stackMetadata(StackMetadataEvent.parse(reader, thread));
+				break;
+
+			case IdenticalStacksMetadata:
+				handler.identicalStacksMetadata(IdenticalStacksMetadataEvent.parse(reader, thread));
+				break;
+
+			case ClassLoaderUnload:
+				handler.classLoaderUnload(ClassLoaderUnloadEvent.parse(reader, thread));
+				break;
+
+			case SafepointBegin:
+				handler.safepointBegin(SafepointBeginEvent.parse(reader, thread));
+				break;
+
+			case SafepointEnd:
+				handler.safepointEnd(SafepointEndEvent.parse(reader, thread));
+				break;
+
+			case VMEnd:
+				handler.endVM(VMEndEvent.parse(reader, thread));
+				break;
+
+			case MetadataReset:
+				handler.metadataReset(MetadataResetEvent.parse(reader, thread));
+				break;
+
+			case Group:
+				handler.group(GroupEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorInfo:
+				handler.nativeMonitorInfo(NativeMonitorInfoEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorDestroy:
+				handler.nativeMonitorDestroy(NativeMonitorDestroyEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorContendedLock:
+				handler.nativeMonitorContendedLock(NativeMonitorContendedLockEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorContendedLocked:
+				handler.nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorContendedUnlocked:
+				handler.nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent.parse(reader, thread));
+				break;
+
+			case NativeMonitorDummy:
+				handler.nativeMonitorDummy(NativeMonitorDummyEvent.parse(reader, thread));
+				break;
+
+			case StackMetadataExtended:
+				handler.stackMetadataExtended(StackMetadataExtendedEvent.parse(reader, thread));
+				break;
+
+			case NativeSymbolMetadata:
+				handler.nativeSymbolMetadata(NativeSymbolMetadataEvent.parse(reader, thread));
+				break;
+
+			case Marker:
+				handler.marker(MarkerEvent.parse(reader, thread));
+				break;
+
+			default:
+				throw new RuntimeException("unknown");
+			}
+			if (progressCallback != null) {
+				progressCallback.eventRead();
+			}
+		}
+		bytesProcessed += reader.bytesRead();
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		map.put("processed_trace_bytes", (double) bytesProcessed);
+		handler.putStatistics(map);
+	}
+
+	@Override
+	public void resetStatistics() {
+		bytesProcessed = 0;
+		handler.resetStatistics();
+	}
+
+	@Override
+	public void close() {
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TraceReader.java b/src/java.base/share/classes/sun/evtracing/parser/TraceReader.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TraceReader.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.nio.ByteBuffer;
+import java.util.EnumSet;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+
+public class TraceReader extends TraceReaderBase {
+	static {
+		assert TraceEventType.values().length <= TraceReader.UNSIGNED_BYTE_MAX_VALUE;
+		assert ParkReturnCode.values().length <= UNSIGNED_BYTE_MAX_VALUE;
+		assert SafepointReason.values().length <= UNSIGNED_BYTE_MAX_VALUE;
+	}
+
+	public TraceReader(ByteBuffer buffer) {
+		super(buffer);
+	}
+
+	// A lot less useful without typedefs, but we don't want to wrap all those
+	// values in heap objects
+
+	public TraceEventType readEventType() {
+		return TraceEventType.fromOrdinal(readByte());
+	}
+
+	public long readTimestamp() {
+		return readLong();
+	}
+
+	public long readDuration() {
+		return readLong();
+	}
+
+	public long readThreadId() {
+		return readLong();
+	}
+
+	public MetadataRef<JavaThread> readThread() {
+		return new MetadataRef<>(readThreadId());
+	}
+
+	public ThreadState readThreadState() {
+		return ThreadState.fromFlags(readInt());
+	}
+
+	public int readObject() {
+		return readInt();
+	}
+
+	public long readSequenceNumber() {
+		return readLong();
+	}
+
+	public long readMetadataVersion() {
+		return readLong();
+	}
+
+	public long readClassId() {
+		return readLong();
+	}
+
+	public MetadataRef<JavaClass> readClass() {
+		return new MetadataRef<>(readClassId());
+	}
+
+	public long readClassLoader() {
+		return readLong();
+	}
+
+	public long readMethodId() {
+		return readLong();
+	}
+
+	public MetadataRef<JavaMethod> readMethod() {
+		return new MetadataRef<>(readMethodId());
+	}
+
+	public int readBytecodeIndex() {
+		return readInt();
+	}
+
+	public long readStackId() {
+		return readLong();
+	}
+
+	public MetadataRef<JavaStack> readStack() {
+		return new MetadataRef<>(readStackId());
+	}
+
+	public ParkReturnCode readParkReturnCode() {
+		return ParkReturnCode.fromOrdinal(readUnsignedByte());
+	}
+
+	public SafepointReason readSafepointReason() {
+		return SafepointReason.fromOrdinal(readUnsignedByte());
+	}
+
+	public long readMonitor() {
+		return readLong();
+	}
+
+	public MonitorEnterWait readMonitorEnterWait() {
+		return MonitorEnterWait.fromOrdinal(readUnsignedByte());
+	}
+
+	public EnumSet<MonitorEnteredFlags> readMonitorEnteredFlags() {
+		return MonitorEnteredFlags.fromBits(readUnsignedByte());
+	}
+
+	public long readNativeMonitor() {
+		return readLong();
+	}
+
+	public StackFrameKind readStackFrameKind() {
+		return StackFrameKind.fromOrdinal(readUnsignedByte());
+	}
+
+	public long readNativeAddress() {
+		return readLong();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/TraceReaderBase.java b/src/java.base/share/classes/sun/evtracing/parser/TraceReaderBase.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/TraceReaderBase.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+public class TraceReaderBase {
+	public static final int UNSIGNED_BYTE_MAX_VALUE = 0xff;
+
+	private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+	private final ByteBuffer buffer;
+	private final long initialPosition;
+
+	public TraceReaderBase(ByteBuffer buffer) {
+		this.buffer = buffer.asReadOnlyBuffer();
+		this.buffer.order(buffer.order()); // preserve byte order
+		this.initialPosition = this.buffer.position();
+	}
+
+	public byte peekByte() {
+		int p = buffer.position();
+		byte v = buffer.get();
+		buffer.position(p);
+		return v;
+	}
+
+	public byte readByte() {
+		return buffer.get();
+	}
+
+	public int readUnsignedByte() {
+		return Byte.toUnsignedInt(readByte());
+	}
+
+	public short readShort() {
+		return buffer.getShort();
+	}
+
+	public int readUnsignedShort() {
+		return Short.toUnsignedInt(readShort());
+	}
+
+	public int readInt() {
+		return buffer.getInt();
+	}
+
+	public long readUnsignedInt() {
+		return Integer.toUnsignedLong(readInt());
+	}
+
+	public long readLong() {
+		return buffer.getLong();
+	}
+
+	public boolean readBoolean() {
+		return (readUnsignedByte() != 0);
+	}
+
+	public boolean hasMore() {
+		return buffer.hasRemaining();
+	}
+
+	public String readString() {
+		int length = buffer.getShort();
+		assert length >= 0;
+		int oldLimit = buffer.limit();
+		buffer.limit(buffer.position() + length);
+		String s = UTF_8.decode(buffer).toString();
+		buffer.limit(oldLimit);
+		return s;
+	}
+
+	public long bytesRead() {
+		return buffer.position() - initialPosition;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/VMEndEvent.java b/src/java.base/share/classes/sun/evtracing/parser/VMEndEvent.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/VMEndEvent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser;
+
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.processing.TraceEventHandler;
+
+public class VMEndEvent extends TimestampedEvent {
+
+	public static final TraceEventType EVENT_TYPE = TraceEventType.VMEnd;
+
+	public static VMEndEvent parse(TraceReader reader, long thread) {
+		TraceEventType eventType = reader.readEventType();
+		assert eventType == EVENT_TYPE;
+		long timestamp = reader.readTimestamp();
+		return new VMEndEvent(thread, timestamp);
+	}
+
+	protected VMEndEvent(long thread, long timestamp) {
+		super(thread, timestamp);
+	}
+
+	@Override
+	public TraceEventType type() {
+		return EVENT_TYPE;
+	}
+
+	@Override
+	public void accept(TraceEventHandler handler) {
+		handler.endVM(this);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClass.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClass.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClass.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class JavaClass {
+
+	public static final long SPECIAL_ID = 0;
+	private static class SpecialJavaClass extends JavaClass {
+		public SpecialJavaClass(String name) {
+			super(SPECIAL_ID, 0, name);
+		}
+		@Override
+		public boolean isSet() {
+			return true;
+		}
+		@Override
+		public void set(long classLoader, String name) {
+			throw new UnsupportedOperationException();
+		}
+		@Override
+		public boolean isSpecial() {
+			return true;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	}
+	public static final JavaClass UNKNOWN = new SpecialJavaClass("(class unknown)");
+	public static final JavaClass UNCONTENDED = new SpecialJavaClass("(uncontended)");
+	public static final JavaClass NATIVE = new SpecialJavaClass("(native)");
+
+	private final long id;
+	private long classLoader;
+	private String name;
+
+	public JavaClass(long id) {
+		this(id, 0, "(name unknown)");
+	}
+
+	private JavaClass(long id, long classLoader, String name) {
+		this.id = id;
+		this.classLoader = classLoader;
+		this.name = name;
+	}
+	
+	public boolean isSpecial() {
+		return false;
+	}
+
+	public long classLoader() {
+		assert isSet();
+		return classLoader;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	public String prettyName(boolean compact) {
+		return JvmNamePrettyPrinter.prettyClassName(name, compact);
+	}
+
+	public boolean isSet() {
+		return (this.classLoader != 0);
+	}
+
+	public void set(long classLoader, String name) {
+		assert (classLoader != 0 && name != null);
+		assert !isSet() : "set allowed only once";
+
+		this.classLoader = classLoader;
+		this.name = name;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj instanceof JavaClass) {
+			JavaClass other = (JavaClass) obj;
+			if (id == other.id) {
+				assert (!isSet() || !other.isSet() || (classLoader == other.classLoader && name.equals(other.name)));
+				return true;
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public int hashCode() {
+		return Long.hashCode(id);
+	}
+
+	@Override
+	public String toString() {
+		return prettyName(false);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClassDeepComparator.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClassDeepComparator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaClassDeepComparator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package sun.evtracing.parser.metadata;
+
+import java.util.Comparator;
+import sun.evtracing.parser.metadata.JavaClass;
+
+public class JavaClassDeepComparator implements Comparator<JavaClass> {
+
+	public static final JavaClassDeepComparator INSTANCE = new JavaClassDeepComparator();
+
+	@Override
+	public int compare(JavaClass o1, JavaClass o2) {
+		if (o1 == o2) {
+			return 0;
+		}
+		if (o1.isSpecial() && o2.isSpecial()) {
+			if (o1.equals(o2)) {
+				return 0;
+			}
+		}
+		if (o1.isSet() && !o2.isSet()) {
+			return 1;
+		}
+		if (!o1.isSet() && o2.isSet()) {
+			return -1;
+		}
+		if (!o1.isSet() && !o2.isSet()) {
+			return System.identityHashCode(o1) - System.identityHashCode(o2);
+		}
+		return o1.name().compareTo(o2.name());
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethod.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethod.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethod.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class JavaMethod {
+
+	public static final long SPECIAL_ID = 0;
+	private static class SpecialJavaMethod extends JavaMethod {
+		SpecialJavaMethod(JavaClass clazz, String name) {
+			super(SPECIAL_ID, clazz, name, name);
+		}
+		@Override
+		public void set(JavaClass clazz, String name, String signature) {
+			throw new UnsupportedOperationException();
+		}
+		@Override
+		public boolean isSpecial() {
+			return true;
+		}
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	}
+	public static final JavaMethod UNKNOWN = new SpecialJavaMethod(JavaClass.UNKNOWN, "(unknown)");
+	public static final JavaMethod UNCONTENDED = new SpecialJavaMethod(JavaClass.UNCONTENDED, "(uncontended)");
+	public static final JavaMethod READERS = new SpecialJavaMethod(JavaClass.UNKNOWN, "(readers)");
+	public static final JavaMethod MISSING = new SpecialJavaMethod(JavaClass.UNKNOWN, "(missing)");
+	public static final JavaMethod HIDDEN = new SpecialJavaMethod(JavaClass.UNKNOWN, "(hidden)");
+
+	private final long id;
+	private JavaClass clazz;
+	private String name;
+	private String signature;
+
+	public JavaMethod(long id) {
+		this(id, JavaClass.UNKNOWN, "(name unknown)", "(signature unknown)");
+	}
+
+	private JavaMethod(long id, JavaClass clazz, String name, String signature) {
+		this.id = id;
+		this.clazz = clazz;
+		this.name = name;
+		this.signature = signature;
+	}
+	
+	public boolean isSpecial() {
+		return false;
+	}
+
+	public long id() {
+		return id;
+	}
+
+	public JavaClass clazz() {
+		return clazz;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	public String signature() {
+		return signature;
+	}
+
+	public String prettyName(boolean compact) {
+		return JvmNamePrettyPrinter.prettyMethodName(clazz.name(), name, compact);
+	}
+
+	public String prettyDescriptor(boolean compact) {
+		return JvmNamePrettyPrinter.prettyMethodDescriptor(clazz.name(), name, signature, compact);
+	}
+
+	public String prettySignature(boolean compact) {
+		return JvmNamePrettyPrinter.prettyMethodSignature(signature, compact);
+	}
+
+	public boolean isSet() {
+		return (this.clazz != JavaClass.UNKNOWN);
+	}
+
+	public void set(JavaClass clazz, String name, String signature) {
+		assert (clazz != null && clazz != JavaClass.UNKNOWN && name != null && signature != null);
+		assert !isSet() : "set allowed only once";
+
+		this.clazz = clazz;
+		this.name = name;
+		this.signature = signature;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj instanceof JavaMethod) {
+			JavaMethod other = (JavaMethod) obj;
+			if (id == other.id) {
+				assert (!isSet() || !other.isSet() || (clazz.equals(other.clazz) && name.equals(other.name) && signature.equals(other.signature)));
+				return true;
+			}
+		}
+		return false;
+	}
+
+	@Override
+	public int hashCode() {
+		return Long.hashCode(id);
+	}
+
+	@Override
+	public String toString() {
+		if (isSet()) {
+			return prettyDescriptor(true);
+		}
+		return "(unknown)";
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethodDeepComparator.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethodDeepComparator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaMethodDeepComparator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package sun.evtracing.parser.metadata;
+
+import java.util.Comparator;
+import sun.evtracing.parser.metadata.JavaMethod;
+
+public class JavaMethodDeepComparator implements Comparator<JavaMethod> {
+
+	public static final JavaMethodDeepComparator INSTANCE = new JavaMethodDeepComparator();
+
+	@Override
+	public int compare(JavaMethod o1, JavaMethod o2) {
+		if (o1 == o2) {
+			return 0;
+		}
+		if (o1.isSpecial() && o2.isSpecial()) {
+			if (o1.equals(o2)) {
+				return 0;
+			}
+		}
+		if (o1.isSet() && !o2.isSet()) {
+			return 1;
+		}
+		if (!o1.isSet() && o2.isSet()) {
+			return -1;
+		}
+		if (!o1.isSet() && !o2.isSet()) {
+			return System.identityHashCode(o1) - System.identityHashCode(o2);
+		}
+		int result = JavaClassDeepComparator.INSTANCE.compare(o1.clazz(), o2.clazz());
+		if (result == 0) {
+			result = o1.name().compareTo(o2.name());
+			if (result == 0) {
+				result = o1.signature().compareTo(o2.signature());
+			}
+		}
+		return result;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStack.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStack.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStack.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+import java.util.ListIterator;
+import sun.evtracing.parser.StackFrameKind;
+
+import sun.evtracing.processing.MetadataStore;
+
+public class JavaStack implements Iterable<JavaStackFrame> {
+
+	public static final JavaStack UNKNOWN = new JavaStack(JavaStackData.UNKNOWN);
+	public static final JavaStack READERS = new JavaStack(JavaStackData.UNKNOWN);
+	public static final JavaStack UNCONTENDED = new JavaStack(JavaStackData.UNKNOWN);
+	public static final JavaStack HIDDEN = new JavaStack(JavaStackData.UNKNOWN);
+
+	private JavaStack assigned;
+	private JavaStackData data;
+
+	public JavaStack() {
+	}
+
+	private JavaStack(JavaStackData data) {
+		this.data = data;
+	}
+
+	private JavaStackData data() {
+		if (data == null && assigned != null && assigned.isSet()) {
+			// transfer reference
+			data = assigned.data();
+			assigned = null;
+		}
+		return data;
+	}
+
+	public boolean isSet() {
+		return (data() != null);
+	}
+
+	public boolean isUnknown() {
+		assert isSet();
+		return (data() == JavaStackData.UNKNOWN);
+	}
+
+	public void fill(StackFrameKind[] kinds, long[] methods, int[] bcis, MetadataStore metadataStore) {
+		assert (data == null && assigned == null) : "only one set/assign allowed";
+		data = new JavaStackData(kinds, methods, bcis, metadataStore);
+	}
+
+	public void assign(JavaStack other) {
+		assert (data == null && assigned == null) : "only one set/assign allowed";
+		assigned = other;
+	}
+
+	public int frameCount() {
+		return data().frameCount();
+	}
+
+	public boolean hasMethodFromClassLoader(long classLoader) {
+		return data().hasMethodFromClassLoader(classLoader);
+	}
+
+	@Override
+	public ListIterator<JavaStackFrame> iterator() {
+		return data().iterator();
+	}
+
+	public ListIterator<JavaStackFrame> lastIterator() {
+		return data().lastIterator();
+	}
+
+	@Override
+	public String toString() {
+		return data().toString();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackData.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackData.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackData.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+import java.util.Arrays;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import sun.evtracing.parser.StackFrameKind;
+
+import sun.evtracing.processing.MetadataStore;
+
+class JavaStackData implements Iterable<JavaStackFrame> {
+	public static final JavaStackData UNKNOWN = new JavaStackData(null, new long[0], new int[0], null);
+
+	private final JavaMethod[] methods;
+	private final int[] bcis;
+
+	public JavaStackData(StackFrameKind[] kinds, long[] methods, int[] bcis, MetadataStore metadataStore) {
+		assert (methods.length == bcis.length && (kinds == null || kinds.length == methods.length));
+
+		this.methods = new JavaMethod[methods.length];
+		for (int i = 0; i < methods.length; i++) {
+			if (kinds == null || kinds[i] == StackFrameKind.Java) {
+				this.methods[i] = metadataStore.getOrAddMethod(methods[i]);
+			} else {
+				this.methods[i] = metadataStore.getOrAddNativeSymbol(methods[i]);
+			}
+		}
+		this.bcis = Arrays.copyOf(bcis, bcis.length);
+	}
+
+	public int frameCount() {
+		return methods.length;
+	}
+
+	public boolean hasMethodFromClassLoader(long classLoader) {
+		return Arrays.stream(methods).anyMatch(m -> m.clazz().classLoader() == classLoader);
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		for (JavaStackFrame frame : this) {
+			sb.append(frame.toString());
+			sb.append(System.lineSeparator());
+		}
+		return sb.toString();
+	}
+
+	@Override
+	public ListIterator<JavaStackFrame> iterator() {
+		return new ListItr(0);
+	}
+
+	public ListIterator<JavaStackFrame> lastIterator() {
+		return new ListItr(methods.length);
+	}
+
+	private class ListItr implements ListIterator<JavaStackFrame> {
+
+		private int index;
+
+		public ListItr(int index) {
+			this.index = index;
+		}
+
+		@Override
+		public boolean hasNext() {
+			return (index < methods.length);
+		}
+
+		@Override
+		public JavaStackFrame next() {
+			if (!hasNext()) {
+				throw new NoSuchElementException();
+			}
+			JavaStackFrame jsf = new JavaStackFrame(methods[index], bcis[index]);
+			index++;
+			return jsf;
+		}
+
+		@Override
+		public boolean hasPrevious() {
+			return (index > 0);
+		}
+
+		@Override
+		public JavaStackFrame previous() {
+			if (!hasPrevious()) {
+				throw new NoSuchElementException();
+			}
+			index--;
+			return new JavaStackFrame(methods[index], bcis[index]);
+		}
+
+		@Override
+		public int nextIndex() {
+			return index + 1;
+		}
+
+		@Override
+		public int previousIndex() {
+			return index - 1;
+		}
+
+		@Override
+		public void remove() {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public void set(JavaStackFrame e) {
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public void add(JavaStackFrame e) {
+			throw new UnsupportedOperationException();
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackDeepComparator.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackDeepComparator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackDeepComparator.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaStackFrame;
+import sun.evtracing.parser.metadata.MethodFilter;
+
+/**
+ * Compares stack traces using only method and class names, disregarding class
+ * loaders and identifiers.
+ */
+public class JavaStackDeepComparator implements Comparator<JavaStack> {
+
+	public static final JavaStackDeepComparator INSTANCE = new JavaStackDeepComparator();
+
+	public static JavaStackDeepComparator forTopMethodOnly(MethodFilter filter) {
+		return new JavaStackDeepComparator(filter);
+	}
+
+	private final boolean topMethodOnly;
+	private final MethodFilter filter;
+
+	private JavaStackDeepComparator() {
+		this.topMethodOnly = false;
+		this.filter = null;
+	}
+	
+	private JavaStackDeepComparator(MethodFilter filter) {
+		assert (filter != null);
+		this.topMethodOnly = true;
+		this.filter = filter;
+	}
+
+	@Override
+	public int compare(JavaStack o1, JavaStack o2) {
+		if (o1 == o2) {
+			return 0;
+		}
+		if (o1.isSet() && !o2.isSet()) {
+			return 1;
+		}
+		if (!o1.isSet() && o2.isSet()) {
+			return -1;
+		}
+		if (!o1.isSet() && !o2.isSet()) {
+			return 0;
+		}
+		if (o1.isUnknown() && o2.isUnknown()) {
+			return System.identityHashCode(o1) - System.identityHashCode(o2);
+		}
+		if (o1.isUnknown() && !o2.isUnknown()) {
+			return -1;
+		}
+		if (!o1.isUnknown() && o2.isUnknown()) {
+			return 1;
+		}
+		if (o1.frameCount() == 0 || o2.frameCount() == 0 || (!topMethodOnly && o1.frameCount() != o2.frameCount())) {
+			return (o1.frameCount() - o2.frameCount());
+		}
+		if (topMethodOnly) {
+			JavaMethod m1 = filter.getFirstUnmatched(o1);
+			JavaMethod m2 = filter.getFirstUnmatched(o2);
+			return JavaMethodDeepComparator.INSTANCE.compare(m1, m2);
+		}
+		int result;
+		Iterator<JavaStackFrame> i1 = o1.iterator();
+		Iterator<JavaStackFrame> i2 = o2.iterator();
+		do {
+			JavaStackFrame f1 = i1.next();
+			JavaStackFrame f2 = i2.next();
+			result = JavaMethodDeepComparator.INSTANCE.compare(f1.method(), f2.method());
+			/*if (result == 0) {
+			 result = f1.bci() - f2.bci();
+			 }*/
+		} while (result == 0 && i1.hasNext());
+		return result;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackFrame.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackFrame.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaStackFrame.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class JavaStackFrame {
+
+	private final JavaMethod method;
+	private final int bci;
+
+	public JavaStackFrame(JavaMethod method, int bci) {
+		this.method = method;
+		this.bci = bci;
+	}
+
+	public JavaMethod method() {
+		return method;
+	}
+
+	public int bci() {
+		return bci;
+	}
+
+	@Override
+	public String toString() {
+		return method.toString() + " @" + bci;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaThread.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaThread.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JavaThread.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class JavaThread {
+	public static final long SPECIAL_ID = 0;
+	private static class SpecialJavaThread extends JavaThread {
+		public SpecialJavaThread() {
+			super(SPECIAL_ID);
+		}
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	}
+	public static final JavaThread UNKNOWN = new SpecialJavaThread();
+	public static final JavaThread READERS = new SpecialJavaThread();
+	public static final JavaThread UNCONTENDED = new SpecialJavaThread();
+	public static final JavaThread HIDDEN = new SpecialJavaThread();
+
+	private final long tid;
+	private String name;
+
+	private long startTime;
+	private long endTime;
+
+	public JavaThread(long tid) {
+		this.tid = tid;
+	}
+
+	public long threadId() {
+		return tid;
+	}
+
+	public String name() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public void setStart(long time) {
+		startTime = time;
+	}
+
+	public void setEnd(long time) {
+		endTime = time;
+	}
+
+	public boolean hasEnded() {
+		return endTime > 0;
+	}
+
+	public long totalRuntime() {
+		assert startTime != 0;
+		assert endTime != 0;
+		return endTime - startTime;
+	}
+
+	@Override
+	public String toString() {
+		return "Thread " + tid + ": " + ((name != null) ? name : "(unknown name)");
+	}
+
+	@Override
+	public int hashCode() {
+		return Long.hashCode(tid);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		JavaThread other = (JavaThread) obj;
+		if (tid == SPECIAL_ID || other.tid == SPECIAL_ID)
+			return false;
+		if (tid != other.tid)
+			return false;
+		return true;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/JvmNamePrettyPrinter.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/JvmNamePrettyPrinter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/JvmNamePrettyPrinter.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+public class JvmNamePrettyPrinter {
+
+	public static String prettyClassName(String className, boolean compact) {
+		try {
+			Reader reader = new StringReader(className);
+			StringBuilder sb = new StringBuilder();
+			int c = peek(reader);
+			if (c == '[') {
+				prettyPrintNextType(reader, sb, compact);
+			} else {
+				int startLength = sb.length();
+				c = reader.read();
+				while (c != -1) {
+					if (c == '/') {
+						if (compact) {
+							sb.setLength(startLength);
+						} else {
+							sb.append('.');
+						}
+					} else {
+						sb.append((char) c);
+					}
+					c = reader.read();
+				}
+			}
+			return sb.toString();
+		} catch (Exception ex) {
+			throw new RuntimeException(ex);
+		}
+	}
+
+	public static String prettyMethodName(String className, String methodName, boolean compact) {
+		return prettyClassName(className, compact) + "." + methodName;
+	}
+
+	public static String prettyMethodDescriptor(String className, String methodName, String signature, boolean compact) {
+		return prettyMethodName(className, methodName, compact) + prettyMethodSignature(signature, compact);
+	}
+
+	public static String prettyMethodSignature(String signature, boolean compact) {
+		StringBuilder sb = new StringBuilder();
+		StringReader reader = new StringReader(signature);
+		try {
+			int c = reader.read();
+			assert c == '(';
+			sb.append('(');
+
+			c = peek(reader);
+			if (c == -1)
+				throw new EOFException("closing parenthesis");
+
+			// arguments
+			while (c != ')') {
+				prettyPrintNextType(reader, sb, compact);
+
+				c = peek(reader);
+				if (c == -1)
+					throw new EOFException("closing parenthesis");
+
+				if (c != ')')
+					sb.append(", ");
+			}
+
+			c = reader.read(); // consume ')'
+
+			sb.append(')');
+
+			// return type
+			sb.append(" : ");
+			prettyPrintNextType(reader, sb, compact);
+		} catch (Exception e) {
+			throw new RuntimeException("unparsable signature '" + signature + "'", e);
+		}
+		return sb.toString();
+	}
+
+	private static int peek(Reader reader) throws IOException {
+		int c;
+		reader.mark(1);
+		c = reader.read();
+		reader.reset();
+		return c;
+	}
+
+	private static void prettyPrintNextType(Reader reader, StringBuilder sb, boolean compact) throws Exception {
+		int arrayDimensions = 0;
+		boolean atEnd;
+		do {
+			int c = reader.read();
+			if (c == -1)
+				throw new EOFException();
+
+			atEnd = true;
+			switch (c) {
+			case '[':
+				arrayDimensions++;
+				atEnd = false;
+				break;
+			case 'B': sb.append("byte");    break;
+			case 'C': sb.append("char");    break;
+			case 'D': sb.append("double");  break;
+			case 'F': sb.append("float");   break;
+			case 'I': sb.append("int");     break;
+			case 'J': sb.append("long");    break;
+			case 'S': sb.append("short");   break;
+			case 'Z': sb.append("boolean"); break;
+			case 'V': sb.append("void");    break;
+			case 'L':
+				int startLength = sb.length();
+				do {
+					c = reader.read();
+					if (c == -1)
+						throw new EOFException("in class name");
+					if (c != ';') {
+						if (c == '/') {
+							if (compact) {
+								sb.setLength(startLength);
+							} else {
+								sb.append('.');
+							}
+						} else {
+							sb.append((char) c);
+						}
+					}
+				} while (c != ';');
+				break;
+			default:
+				throw new Exception("invalid type '" + (char) c + "'");
+			}
+		} while (!atEnd);
+
+		for (int i = 0; i < arrayDimensions; i++) {
+			sb.append("[]");
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/MetadataRef.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/MetadataRef.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/MetadataRef.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class MetadataRef<T> {
+
+	private final long identifier;
+	private T metadata;
+
+	public MetadataRef(long identifier) {
+		this(identifier, null);
+	}
+
+	public MetadataRef(long identifier, T metadata) {
+		this.identifier = identifier;
+		this.metadata = metadata;
+	}
+
+	public long identifier() {
+		return identifier;
+	}
+
+	public T metadata() {
+		return metadata;
+	}
+
+	public void setMetadata(T metadata) {
+		assert (this.metadata == null) : "set only allowed once";
+		this.metadata = metadata;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/MethodFilter.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/MethodFilter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/MethodFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+public class MethodFilter {
+
+	public static final MethodFilter NO_FILTER = new MethodFilter(new Pattern[0]);
+
+	private final Pattern[] patterns;
+
+	public MethodFilter(Pattern[] patterns) {
+		this.patterns = patterns;
+	}
+
+	public boolean matches(JavaMethod method) {
+		String name = method.prettyName(false);
+		for (Pattern p : patterns) {
+			if (p.matcher(name).matches()) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	public JavaMethod getFirstUnmatched(JavaStack stack) {
+		if (!stack.isSet() || stack.frameCount() == 0) {
+			return null;
+		}
+		Iterator<JavaStackFrame> it = stack.iterator();
+		JavaMethod method = it.next().method();
+		int skipped = 1;
+		while (it.hasNext() && matches(method)) {
+			method = it.next().method();
+			skipped++;
+		}
+		// if everything was skipped, return the first one
+		return skipped == stack.frameCount() ? stack.iterator().next().method() : method;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/parser/metadata/NativeSymbol.java b/src/java.base/share/classes/sun/evtracing/parser/metadata/NativeSymbol.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/parser/metadata/NativeSymbol.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.parser.metadata;
+
+public class NativeSymbol extends JavaMethod {
+	/* FIXME: this is really just an ugly hack to accommodate native symbols in
+	 * our class hierarchy without major refactoring. At the very least, we
+	 * should introduce a class that JavaMethod and NativeSymbol independently
+	 * extend.
+	 */
+
+	public NativeSymbol(long id) {
+		super(id);
+	}
+
+	public void set(String name) {
+		set(JavaClass.NATIVE, name, "");
+	}
+
+	@Override
+	public void set(JavaClass clazz, String name, String signature) {
+		assert clazz == JavaClass.NATIVE;
+		assert signature.isEmpty();
+
+		super.set(clazz, name, signature);
+	}
+
+	@Override
+	public String prettyDescriptor(boolean compact) {
+		return name();
+	}
+
+	@Override
+	public String prettyName(boolean compact) {
+		return name();
+	}
+
+	@Override
+	public String prettySignature(boolean compact) {
+		return "";
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (obj instanceof NativeSymbol) {
+			return super.equals(obj);
+		}
+		return false;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/AbstractTraceEventHandler.java b/src/java.base/share/classes/sun/evtracing/processing/AbstractTraceEventHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/AbstractTraceEventHandler.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Map;
+
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.IdenticalStacksMetadataEvent;
+import sun.evtracing.parser.MarkerEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorDummyEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.NativeSymbolMetadataEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.NativeMonitorDummyEvent;
+import sun.evtracing.parser.SafepointBeginEvent;
+import sun.evtracing.parser.SafepointEndEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.StackMetadataExtendedEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+
+public class AbstractTraceEventHandler implements TraceEventHandler {
+
+	@Override
+	public void threadStart(ThreadStartEvent event) {
+	}
+
+	@Override
+	public void threadNameChange(ThreadNameChangeEvent event) {
+	}
+
+	@Override
+	public void threadStateChange(ThreadStateChangeEvent event) {
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+	}
+
+	@Override
+	public void threadExit(ThreadExitEvent event) {
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+	}
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+	}
+
+	@Override
+	public void monitorDummy(MonitorDummyEvent event) {
+	}
+
+	@Override
+	public void classMetadata(ClassMetadataEvent event) {
+	}
+
+	@Override
+	public void safepointBegin(SafepointBeginEvent event) {
+	}
+
+	@Override
+	public void safepointEnd(SafepointEndEvent event) {
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+	}
+
+	@Override
+	public void methodMetadata(MethodMetadataEvent event) {
+	}
+
+	@Override
+	public void classLoaderUnload(ClassLoaderUnloadEvent event) {
+	}
+
+	@Override
+	public void stackMetadata(StackMetadataEvent event) {
+	}
+
+	@Override
+	public void identicalStacksMetadata(IdenticalStacksMetadataEvent event) {
+	}
+
+	@Override
+	public void metadataReset(MetadataResetEvent event) {
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+	}
+
+	@Override
+	public void resetStatistics() {
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorInfo(NativeMonitorInfoEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorDestroy(NativeMonitorDestroyEvent event) {
+	}
+
+	@Override
+	public void nativeMonitorDummy(NativeMonitorDummyEvent event) {
+	}
+
+	@Override
+	public void stackMetadataExtended(StackMetadataExtendedEvent event) {
+	}
+
+	@Override
+	public void nativeSymbolMetadata(NativeSymbolMetadataEvent event) {
+	}
+
+	@Override
+	public void marker(MarkerEvent event) {
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/DelegateTraceEventHandler.java b/src/java.base/share/classes/sun/evtracing/processing/DelegateTraceEventHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/DelegateTraceEventHandler.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Map;
+
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.IdenticalStacksMetadataEvent;
+import sun.evtracing.parser.MarkerEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorDummyEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.NativeSymbolMetadataEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.NativeMonitorDummyEvent;
+import sun.evtracing.parser.SafepointBeginEvent;
+import sun.evtracing.parser.SafepointEndEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.StackMetadataExtendedEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+
+public class DelegateTraceEventHandler implements TraceEventHandler {
+	private final TraceEventHandler delegateHandler;
+
+	public DelegateTraceEventHandler(TraceEventHandler delegateHandler) {
+		this.delegateHandler = delegateHandler;
+	}
+
+	protected TraceEventHandler delegateHandler() {
+		return delegateHandler;
+	}
+
+	@Override
+	public void threadStart(ThreadStartEvent event) {
+		delegateHandler.threadStart(event);
+	}
+
+	@Override
+	public void threadNameChange(ThreadNameChangeEvent event) {
+		delegateHandler.threadNameChange(event);
+	}
+
+	@Override
+	public void threadStateChange(ThreadStateChangeEvent event) {
+		delegateHandler.threadStateChange(event);
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+		delegateHandler.threadInterrupt(event);
+	}
+
+	@Override
+	public void threadExit(ThreadExitEvent event) {
+		delegateHandler.threadExit(event);
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		delegateHandler.threadParkBegin(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		delegateHandler.threadParkEnd(event);
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+		delegateHandler.threadUnpark(event);
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+		delegateHandler.monitorContendedEnter(event);
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+		delegateHandler.monitorContendedEntered(event);
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+		delegateHandler.monitorContendedExited(event);
+	}
+
+	@Override
+	public void monitorDummy(MonitorDummyEvent event) {
+		delegateHandler.monitorDummy(event);
+	}
+
+	@Override
+	public void safepointBegin(SafepointBeginEvent event) {
+		delegateHandler.safepointBegin(event);
+	}
+
+	@Override
+	public void safepointEnd(SafepointEndEvent event) {
+		delegateHandler.safepointEnd(event);
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+		delegateHandler.endVM(event);
+	}
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+		delegateHandler.monitorInflate(event);
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+		delegateHandler.monitorDeflate(event);
+	}
+
+	@Override
+	public void classMetadata(ClassMetadataEvent event) {
+		delegateHandler.classMetadata(event);
+	}
+
+	@Override
+	public void methodMetadata(MethodMetadataEvent event) {
+		delegateHandler.methodMetadata(event);
+	}
+
+	@Override
+	public void classLoaderUnload(ClassLoaderUnloadEvent event) {
+		delegateHandler.classLoaderUnload(event);
+	}
+
+	@Override
+	public void stackMetadata(StackMetadataEvent event) {
+		delegateHandler.stackMetadata(event);
+	}
+
+	@Override
+	public void identicalStacksMetadata(IdenticalStacksMetadataEvent event) {
+		delegateHandler.identicalStacksMetadata(event);
+	}
+
+	@Override
+	public void metadataReset(MetadataResetEvent event) {
+		delegateHandler.metadataReset(event);
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		delegateHandler.putStatistics(map);
+	}
+
+	@Override
+	public void resetStatistics() {
+		delegateHandler.resetStatistics();
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		delegateHandler.group(event);
+	}
+
+	@Override
+	public void nativeMonitorInfo(NativeMonitorInfoEvent event) {
+		delegateHandler.nativeMonitorInfo(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event) {
+		delegateHandler.nativeMonitorContendedLock(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent event) {
+		delegateHandler.nativeMonitorContendedLocked(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event) {
+		delegateHandler.nativeMonitorContendedUnlocked(event);
+	}
+
+	@Override
+	public void nativeMonitorDestroy(NativeMonitorDestroyEvent event) {
+		delegateHandler.nativeMonitorDestroy(event);
+	}
+
+	@Override
+	public void nativeMonitorDummy(NativeMonitorDummyEvent event) {
+		delegateHandler.nativeMonitorDummy(event);
+	}
+
+	@Override
+	public void stackMetadataExtended(StackMetadataExtendedEvent event) {
+		delegateHandler.stackMetadataExtended(event);
+	}
+
+	@Override
+	public void nativeSymbolMetadata(NativeSymbolMetadataEvent event) {
+		delegateHandler.nativeSymbolMetadata(event);
+	}
+
+	@Override
+	public void marker(MarkerEvent event) {
+		delegateHandler.marker(event);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/MetadataStore.java b/src/java.base/share/classes/sun/evtracing/processing/MetadataStore.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/MetadataStore.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.NativeSymbol;
+
+public class MetadataStore {
+
+	private static final long UNKNOWN_STACK_ID = 0;
+
+	private Map<Long, JavaClass> classes = new HashMap<>();
+	private Map<Long, JavaMethod> methods = new HashMap<>();
+	private Map<Long, JavaStack> stacks = new HashMap<>();
+	private Map<Long, NativeSymbol> nativeSymbols = new HashMap<>();
+
+	public JavaClass getOrAddClass(long classId) {
+		if (classId == JavaClass.SPECIAL_ID) {
+			return JavaClass.UNKNOWN;
+		}
+		return classes.computeIfAbsent(classId, k -> new JavaClass(k));
+	}
+
+	public JavaMethod getOrAddMethod(long methodId) {
+		if (methodId == JavaMethod.SPECIAL_ID) {
+			return JavaMethod.UNKNOWN;
+		}
+		return methods.computeIfAbsent(methodId, m -> new JavaMethod(m));
+	}
+
+	public JavaStack getOrAddStack(long stackId) {
+		if (stackId == UNKNOWN_STACK_ID) {
+			return JavaStack.UNKNOWN;
+		}
+		return stacks.computeIfAbsent(stackId, s -> new JavaStack());
+	}
+
+	public NativeSymbol getOrAddNativeSymbol(long nativeAddress) {
+		return nativeSymbols.computeIfAbsent(nativeAddress, a -> new NativeSymbol(a));
+	}
+
+	public void purgeUnloadedClassesFrom(long classLoader) {
+		classes.values().removeIf(c -> c.classLoader() == classLoader);
+		methods.values().removeIf(m -> m.clazz().classLoader() == classLoader);
+
+		// Some stacks are not resolved immediately and thus remain unset for
+		// considerable time. One example is when a monitor is exited temporarily
+		// for Object.wait(), but the event refers to the actual lock site which can
+		// only be determined later when the monitor is actually exited. Obviously,
+		// such stacks can never be affected by class unloads.
+		// If a stack was resolved immediately, but we missed it because of a broken
+		// event order, this is a bug and we can't detect it.
+		stacks.values().removeIf(st -> st.isSet() && st.hasMethodFromClassLoader(classLoader));
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/PersistentMetadataStore.java b/src/java.base/share/classes/sun/evtracing/processing/PersistentMetadataStore.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/PersistentMetadataStore.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import sun.evtracing.parser.metadata.JavaThread;
+
+public class PersistentMetadataStore {
+
+	private final Map<Long, JavaThread> threads = new HashMap<>();
+
+	public JavaThread getOrAddJavaThread(long threadId) {
+		return threads.computeIfAbsent(threadId, k -> new JavaThread(k));
+	}
+
+	public void endAllJavaThreads(long timestamp) {
+		for (JavaThread t : threads.values()) {
+			if (!t.hasEnded()) {
+				t.setEnd(timestamp);
+			}
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/ProgressCallback.java b/src/java.base/share/classes/sun/evtracing/processing/ProgressCallback.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/ProgressCallback.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+public interface ProgressCallback {
+
+	void bufferRead();
+
+	void eventRead();
+
+	void totalInputBytesRead(long bytesRead);
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/Sanity.java b/src/java.base/share/classes/sun/evtracing/processing/Sanity.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/Sanity.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import static java.lang.System.err;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+public class Sanity {
+
+	private static final boolean PRINT_INDIVIDUAL_WARNINGS = Boolean.parseBoolean(System.getProperty("sun.evtracing.printIndividualWarnings"));
+
+	private static class Counter {
+		private int value = 0;
+		public void inc() { value++; }
+		public int get() { return value; }
+	}
+	private static HashMap<String, Counter> WARNINGS;
+
+	public static boolean isEnabled() {
+		boolean ea = false;
+		assert (ea = true);
+		return ea;
+	}
+
+	/**
+	 * Non-failing assert for conditions that we expect to be true, but might be
+	 * violated in rare cases, especially because of magic happening during VM
+	 * startup.
+	 */
+	public static void warnIf(boolean condition, String format, Object... args) {
+		if (condition) {
+			warn(format, args);
+		}
+	}
+
+	/**
+	 * Print a warning if assertions are enabled.
+	 */
+	public static void warn(String format, Object... args) {
+		if (isEnabled()) {
+			if (PRINT_INDIVIDUAL_WARNINGS) {
+				err.printf(format, args);
+				err.println();
+			} else {
+				if (WARNINGS == null) {
+					WARNINGS = new HashMap<>();
+				}
+				Counter ctr = WARNINGS.computeIfAbsent(format, f -> new Counter());
+				ctr.inc();
+			}
+		}
+	}
+
+	public static void printCollectedWarnings() {
+		if (WARNINGS != null) {
+			WARNINGS.entrySet().stream()
+				.sorted((x, y) -> y.getValue().get() - x.getValue().get())
+				.forEach(e -> err.printf("%6d  %s%n", e.getValue().get(), e.getKey()));
+		}
+	}
+
+	public static void assertNoInheritedAbstractMethods(Class<?> clazz) {
+		for (Method m : clazz.getMethods()) {
+			if (Modifier.isAbstract(m.getModifiers()) && !clazz.equals(m.getDeclaringClass())) {
+				throw new AssertionError("class must implement all abstract methods from superclasses", null);
+			}
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/SequenceOrderedEventQueue.java b/src/java.base/share/classes/sun/evtracing/processing/SequenceOrderedEventQueue.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/SequenceOrderedEventQueue.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Comparator;
+import java.util.PriorityQueue;
+import java.util.Queue;
+
+import sun.evtracing.parser.SequenceOrderedEvent;
+
+public class SequenceOrderedEventQueue {
+	private static class SequenceOrderedEventComparator implements Comparator<SequenceOrderedEvent> {
+		@Override
+		public int compare(SequenceOrderedEvent e1, SequenceOrderedEvent e2) {
+			return (int) (e1.sequenceNumber() - e2.sequenceNumber());
+		}
+	}
+
+	private final TraceEventHandler delegateHandler;
+
+	public SequenceOrderedEventQueue(TraceEventHandler delegate) {
+		this.delegateHandler = delegate;
+	}
+
+	private long nextSeqNumber = 1;
+	private final Queue<SequenceOrderedEvent> queue = new PriorityQueue<>(new SequenceOrderedEventComparator());
+
+	public int size() {
+		return queue.size();
+	}
+
+	public void addEvent(SequenceOrderedEvent event) {
+		if (tryNotify(event)) {
+			tryFlushQueue();
+		} else {
+			queue.add(event);
+		}
+	}
+
+	private boolean tryNotify(SequenceOrderedEvent event) {
+		if (nextSeqNumber == event.sequenceNumber()) {
+			event.accept(delegateHandler);
+			nextSeqNumber++;
+			return true;
+		}
+		return false;
+	}
+
+	private void tryFlushQueue() {
+		while (!queue.isEmpty() && tryNotify(queue.peek())) {
+			queue.remove();
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventDiagnosticsHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventDiagnosticsHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventDiagnosticsHandler.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import sun.evtracing.parser.TraceEvent;
+import sun.evtracing.parser.TraceEventType;
+
+public class TraceEventDiagnosticsHandler extends TraceEventUniversalHandler {
+
+	private final TraceEventHandler delegate;
+
+	private final long[] counters = new long[TraceEventType.values().length];
+
+	public TraceEventDiagnosticsHandler(TraceEventHandler delegate) {
+		this.delegate = delegate;
+	}
+
+	@Override
+	public void handle(TraceEvent event) {
+		int index = event.type().ordinal();
+		counters[index]++;
+		event.accept(delegate);
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		for (int i = 0; i < counters.length; i++) {
+			map.put("event_count_" + TraceEventType.fromOrdinal(i).name(), (double) counters[i]);
+		}
+		delegate.putStatistics(map);
+	}
+
+	@Override
+	public void resetStatistics() {
+		Arrays.fill(counters, 0);
+		delegate.resetStatistics();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventHandler.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import sun.evtracing.StatisticsProvider;
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.IdenticalStacksMetadataEvent;
+import sun.evtracing.parser.MarkerEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorDummyEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.NativeSymbolMetadataEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.NativeMonitorDummyEvent;
+import sun.evtracing.parser.SafepointBeginEvent;
+import sun.evtracing.parser.SafepointEndEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.StackMetadataExtendedEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+
+public interface TraceEventHandler extends StatisticsProvider {
+
+	void threadStart(ThreadStartEvent event);
+
+	void threadNameChange(ThreadNameChangeEvent event);
+
+	void threadStateChange(ThreadStateChangeEvent event);
+
+	void threadInterrupt(ThreadInterruptEvent event);
+
+	void threadExit(ThreadExitEvent event);
+
+	void threadParkBegin(ThreadParkBeginEvent event);
+
+	void threadParkEnd(ThreadParkEndEvent event);
+
+	void threadUnpark(ThreadUnparkEvent event);
+
+	void monitorContendedEnter(MonitorContendedEnterEvent event);
+
+	void monitorDeflate(MonitorDeflateEvent event);
+
+	void monitorContendedEntered(MonitorContendedEnteredEvent event);
+
+	void monitorContendedExited(MonitorContendedExitedEvent event);
+
+	void monitorDummy(MonitorDummyEvent event);
+
+	void safepointBegin(SafepointBeginEvent event);
+
+	void safepointEnd(SafepointEndEvent event);
+
+	void endVM(VMEndEvent event);
+
+	void monitorInflate(MonitorInflateEvent event);
+
+	void classMetadata(ClassMetadataEvent event);
+
+	void methodMetadata(MethodMetadataEvent event);
+
+	void classLoaderUnload(ClassLoaderUnloadEvent event);
+
+	void stackMetadata(StackMetadataEvent event);
+	
+	void identicalStacksMetadata(IdenticalStacksMetadataEvent event);
+
+	void metadataReset(MetadataResetEvent event);
+
+	void group(GroupEvent event);
+
+	void nativeMonitorInfo(NativeMonitorInfoEvent event);
+
+	void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event);
+
+	void nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent event);
+
+	void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event);
+
+	void nativeMonitorDestroy(NativeMonitorDestroyEvent event);
+
+	void nativeMonitorDummy(NativeMonitorDummyEvent event);
+
+	void stackMetadataExtended(StackMetadataExtendedEvent event);
+
+	void nativeSymbolMetadata(NativeSymbolMetadataEvent event);
+
+	void marker(MarkerEvent event);
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventJsonWriter.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventJsonWriter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventJsonWriter.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import sun.evtracing.parser.GlobalSequenceOrderedEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadState;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.VMEndEvent;
+import sun.evtracing.parser.metadata.JavaStack;
+
+public class TraceEventJsonWriter extends AbstractTraceEventHandler {
+	private class ThreadData {
+		private long stateChangeTime = -1;
+		private ThreadState state;
+		private final Deque<List<GlobalSequenceOrderedEvent>> nestingStack = new ArrayDeque<>();
+
+		public long stateChangeTime() {
+			assert stateChangeTime > 0;
+			return stateChangeTime;
+		}
+
+		public ThreadState state() {
+			return state;
+		}
+
+		public void setThreadState(long time, ThreadState ts) {
+			this.stateChangeTime = time;
+			this.state = ts;
+		}
+
+		public void resetThreadState() {
+			setThreadState(-1, null);
+		}
+
+		public int nestingLevel() {
+			return nestingStack.size();
+		}
+
+		public void addParkBeginEvent(ThreadParkBeginEvent event) {
+			int currentLevel = nestingStack.size();
+			assert event.nestingLevel() >= currentLevel;
+			if (event.nestingLevel() > currentLevel) {
+				for (int i = currentLevel; i < event.nestingLevel() - 1; i++) {
+					nestingStack.push(new ArrayList<>());
+				}
+				List<GlobalSequenceOrderedEvent> events = new ArrayList<>();
+				events.add(event);
+				nestingStack.push(events);
+			} else if (event.nestingLevel() == currentLevel) {
+				addParkEvent(event);
+			}
+		}
+
+		public void addParkEndEvent(ThreadParkEndEvent event) {
+			addParkEvent(event);
+		}
+
+		public void addParkEvent(GlobalSequenceOrderedEvent event) {
+			if (nestingLevel() > 0) {
+				nestingStack.peek().add(event);
+			} else {
+				event.accept(parkHandler);
+			}
+		}
+
+		public long nestingFirstSeen() {
+			return nestingStack.peek().get(0).timestamp();
+		}
+
+		public void popNestingLevel() {
+			List<GlobalSequenceOrderedEvent> events = nestingStack.pop();
+			if (nestingLevel() > 0) {
+				nestingStack.peek().addAll(events);
+			} else {
+				events.forEach(e -> e.accept(parkHandler));
+			}
+		}
+	}
+
+	private PrintStream ps;
+	private final Map<Long, ThreadData> threadData = new HashMap<>();
+	private final TraceEventHandler parkHandler = new AbstractTraceEventHandler() {
+		@Override
+		public void threadParkBegin(ThreadParkBeginEvent event) {
+			String name = event.clazz().metadata().prettyName(true);
+			JavaStack jstack = event.stack().metadata();
+			String stack;
+			if (jstack.isSet()) {
+				stack = StreamSupport.stream(jstack.spliterator(), false)
+							.map(frame -> "\"" + (frame.method().isSet() ? frame.method().prettyDescriptor(true) : "(unknown)") + "\"")
+							.collect(Collectors.joining(","));
+			} else {
+				stack = "";
+			}
+			ps.printf(",\n{\"name\":\"%s\",\"cat\":\"park\",\"ph\":\"B\",\"ts\":%d,\"pid\":1,\"tid\":%d,\"args\":{\"Arg isAbsolute\":%s,\"Arg time\":%d,\"Identity Hash Code\":\"%s\",\"Stack\":[%s],\"Nesting Level\":%d,\"Seq Begin\":%d}}", name, event.timestamp() / 1000, event.thread().identifier(), event.isAbsolute(), event.parkTime(), Integer.toHexString(event.blockerObject()), stack, event.nestingLevel(), event.sequenceNumber());
+		}
+
+		@Override
+		public void threadParkEnd(ThreadParkEndEvent event) {
+			ps.printf(",\n{\"ph\":\"E\",\"ts\":%d,\"pid\":1,\"tid\":%d,\"args\":{\"Seq Unpark\":%d,\"Seq End\":%d,\"Return Code\":\"%s\"}}", event.timestamp() / 1000, event.thread().identifier(), event.unparkSequenceNumber(), event.sequenceNumber(), event.parkReturnCode().name());
+		}
+	};
+
+	public TraceEventJsonWriter(File file) throws FileNotFoundException {
+		ps = new PrintStream(file);
+		ps.println("[");
+		ps.print("{\"name\":\"process_name\",\"ph\":\"M\",\"pid\":1,\"args\":{\"name\":\"java\"}}");
+	}
+
+	private ThreadData getOrCreateThreadData(long thread) {
+		return threadData.computeIfAbsent(thread, t -> new ThreadData());
+	}
+
+	@Override
+	public void threadStart(ThreadStartEvent event) {
+		ps.printf(",\n{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":1,\"tid\":%d,\"args\":{\"name\":\"%s\"}}", event.thread().identifier(), event.name());
+	}
+
+	@Override
+	public void threadNameChange(ThreadNameChangeEvent event) {
+		ps.printf(",\n{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":1,\"tid\":%d,\"args\":{\"name\":\"%s\"}}", event.affectedThread().identifier(), event.newName());
+	}
+
+	@Override
+	public void threadStateChange(ThreadStateChangeEvent event) {
+		ThreadData td = getOrCreateThreadData(event.affectedThread().identifier());
+		if (td.state() != null) {
+			printThreadState(event.timestamp(), event.affectedThread().identifier(), td);
+		}
+		if (!event.newState().toThreadState().equals(Thread.State.TERMINATED)) {
+			td.setThreadState(event.timestamp(), event.newState());
+		}
+	}
+
+	private void printThreadState(long time, long thread, ThreadData threadData) {
+		long startTime = threadData.stateChangeTime() / 1000;
+		long endTime = time / 1000;
+		if (endTime - startTime > 0) {
+			ps.printf(",\n{\"name\":\"%s\",\"cat\":\"state\",\"ph\":\"B\",\"ts\":%d,\"pid\":1,\"tid\":%d}", threadData.state().toString(), startTime, thread);
+			ps.printf(",\n{\"cat\":\"state\",\"ph\":\"E\",\"ts\":%d,\"pid\":1,\"tid\":%d}", endTime, thread);
+		}
+	}
+
+	@Override
+	public void threadExit(ThreadExitEvent event) {
+		ThreadData td = getOrCreateThreadData(event.thread().identifier());
+		if (td.state() != null) {
+			printThreadState(event.timestamp(), event.thread().identifier(), td);
+			td.resetThreadState();
+		}
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+		ps.println("\n]");
+		ps.close();
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		ThreadData td = getOrCreateThreadData(event.thread().identifier());
+		td.addParkBeginEvent(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		ThreadData td = getOrCreateThreadData(event.thread().identifier());
+		td.addParkEndEvent(event);
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		ThreadData td = getOrCreateThreadData(event.thread().identifier());
+		int nestingLevel = td.nestingLevel();
+		if (nestingLevel > 0) {
+			String name = event.clazz().metadata().prettyName(true);
+			long startTime = td.nestingFirstSeen();
+			ps.printf(",\n{\"name\":\"%s\",\"cat\":\"group\",\"ph\":\"X\",\"ts\":%d,\"dur\":%d,\"pid\":1,\"tid\":%d,\"args\":{\"Identity Hash Code\":\"%s\",\"Nesting Level\":%d,\"Seq Begin Reference\":%d,\"Seq End\":%d}}", name, startTime / 1000, (event.timestamp() - startTime) / 1000, event.thread().identifier(), Integer.toHexString(event.obj()), nestingLevel, event.sequenceBeginReference(), event.sequenceNumber());
+			td.popNestingLevel();
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventMetadataResolveHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventMetadataResolveHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventMetadataResolveHandler.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Map;
+
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.IdenticalStacksMetadataEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeSymbolMetadataEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.StackMetadataExtendedEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.TraceEvent;
+import sun.evtracing.parser.VMEndEvent;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MetadataRef;
+import sun.evtracing.parser.metadata.NativeSymbol;
+
+public class TraceEventMetadataResolveHandler extends TraceEventUniversalHandler {
+
+	private class ResolveHandler extends DelegateTraceEventHandler {
+		public ResolveHandler(TraceEventHandler delegate) {
+			super(delegate);
+		}
+
+		//
+		// Metadata events
+		//
+
+		@Override
+		public void threadStart(ThreadStartEvent event) {
+			JavaThread t = event.thread().metadata();
+			t.setName(event.name());
+			t.setStart(event.timestamp());
+			super.threadStart(event);
+		}
+
+		@Override
+		public void threadNameChange(ThreadNameChangeEvent event) {
+			resolveThread(event.affectedThread()).setName(event.newName());
+			super.threadNameChange(event);
+		}
+
+		@Override
+		public void threadExit(ThreadExitEvent event) {
+			event.thread().metadata().setEnd(event.timestamp());
+			super.threadExit(event);
+		}
+
+		@Override
+		public void endVM(VMEndEvent event) {
+			persistentMetadata.endAllJavaThreads(event.timestamp());
+			super.endVM(event);
+		}
+
+		@Override
+		public void classMetadata(ClassMetadataEvent event) {
+			metadata.getOrAddClass(event.clazz()).set(event.classLoader(), event.name());
+			super.classMetadata(event);
+		}
+
+		@Override
+		public void stackMetadata(StackMetadataEvent event) {
+			metadata.getOrAddStack(event.stack()).fill(null, event.methods(), event.bcis(), metadata);
+			super.stackMetadata(event);
+		}
+
+		@Override
+		public void stackMetadataExtended(StackMetadataExtendedEvent event) {
+			metadata.getOrAddStack(event.stack()).fill(event.kinds(), event.methods(), event.bcis(), metadata);
+		}
+
+		@Override
+		public void identicalStacksMetadata(IdenticalStacksMetadataEvent event) {
+			JavaStack known = metadata.getOrAddStack(event.knownStack());
+			metadata.getOrAddStack(event.stack()).assign(known);
+			super.identicalStacksMetadata(event);
+		}
+
+		@Override
+		public void methodMetadata(MethodMetadataEvent event) {
+			metadata.getOrAddMethod(event.method()).set(resolveClass(event.clazz()), event.name(), event.signature());
+			super.methodMetadata(event);
+		}
+
+		@Override
+		public void nativeSymbolMetadata(NativeSymbolMetadataEvent event) {
+			NativeSymbol symbol = metadata.getOrAddNativeSymbol(event.address());
+			if (!symbol.isSet()) {
+				symbol.set(event.description());
+			} else {
+				assert symbol.name().equals(event.description());
+			}
+			super.nativeSymbolMetadata(event);
+		}
+
+		@Override
+		public void classLoaderUnload(ClassLoaderUnloadEvent event) {
+			metadata.purgeUnloadedClassesFrom(event.classLoader());
+			super.classLoaderUnload(event);
+		}
+
+		@Override
+		public void metadataReset(MetadataResetEvent event) {
+			metadata = new MetadataStore();
+			super.metadataReset(event);
+		}
+
+		//
+		// Events with metadata to resolve
+		//
+
+		@Override
+		public void monitorInflate(MonitorInflateEvent event) {
+			resolveClass(event.clazz());
+			super.monitorInflate(event);
+		}
+
+		@Override
+		public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+			resolveStack(event.stack());
+			super.monitorContendedEnter(event);
+		}
+
+		@Override
+		public void monitorContendedExited(MonitorContendedExitedEvent event) {
+			resolveStack(event.stack());
+			super.monitorContendedExited(event);
+		}
+
+		@Override
+		public void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event) {
+			resolveStack(event.stack());
+			super.nativeMonitorContendedLock(event);
+		}
+
+		@Override
+		public void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event) {
+			resolveStack(event.stack());
+			super.nativeMonitorContendedUnlocked(event);
+		}
+
+		@Override
+		public void threadParkBegin(ThreadParkBeginEvent event) {
+			resolveClass(event.clazz());
+			resolveStack(event.stack());
+			super.threadParkBegin(event);
+		}
+
+		@Override
+		public void threadUnpark(ThreadUnparkEvent event) {
+			resolveThread(event.unparkedThread());
+			resolveStack(event.stack());
+			super.threadUnpark(event);
+		}
+
+		@Override
+		public void group(GroupEvent event) {
+			resolveClass(event.clazz());
+			super.group(event);
+		}
+
+		@Override
+		public void threadStateChange(ThreadStateChangeEvent event) {
+			resolveThread(event.affectedThread());
+			super.threadStateChange(event);
+		}
+
+		@Override
+		public void threadInterrupt(ThreadInterruptEvent event) {
+			resolveThread(event.affectedThread());
+			super.threadInterrupt(event);
+		}
+	}
+
+	private final TraceEventHandler resolveHandler;
+	private final PersistentMetadataStore persistentMetadata = new PersistentMetadataStore();
+	private MetadataStore metadata = new MetadataStore();
+
+	public TraceEventMetadataResolveHandler(TraceEventHandler delegate) {
+		resolveHandler = new ResolveHandler(delegate);
+	}
+
+	private JavaThread resolveThread(MetadataRef<JavaThread> thread) {
+		thread.setMetadata(persistentMetadata.getOrAddJavaThread(thread.identifier()));
+		return thread.metadata();
+	}
+
+	private JavaClass resolveClass(MetadataRef<JavaClass> clazz) {
+		clazz.setMetadata(metadata.getOrAddClass(clazz.identifier()));
+		return clazz.metadata();
+	}
+
+	private JavaStack resolveStack(MetadataRef<JavaStack> stack) {
+		stack.setMetadata(metadata.getOrAddStack(stack.identifier()));
+		return stack.metadata();
+	}
+
+	@Override
+	public void handle(TraceEvent event) {
+		resolveThread(event.thread());
+		event.accept(resolveHandler);
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		resolveHandler.putStatistics(map);
+	}
+
+	@Override
+	public void resetStatistics() {
+		resolveHandler.resetStatistics();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventMultiHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventMultiHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventMultiHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Map;
+
+import sun.evtracing.parser.TraceEvent;
+
+public class TraceEventMultiHandler extends TraceEventUniversalHandler {
+	private final TraceEventHandler[] delegates;
+
+	public TraceEventMultiHandler(TraceEventHandler... delegates) {
+		this.delegates = delegates;
+	}
+
+	@Override
+	public void handle(TraceEvent event) {
+		for (int i = 0; i < delegates.length; i++) {
+			event.accept(delegates[i]);
+		}
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		for (int i = 0; i < delegates.length; i++) {
+			delegates[i].putStatistics(map);
+		}
+	}
+
+	@Override
+	public void resetStatistics() {
+		for (int i = 0; i < delegates.length; i++) {
+			delegates[i].resetStatistics();
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventNopProcessor.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventNopProcessor.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventNopProcessor.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import sun.evtracing.TraceBuffer;
+
+@SuppressWarnings("try")
+public class TraceEventNopProcessor implements TraceProcessor {
+
+	@Override
+	public void close() throws Exception {
+	}
+
+	@Override
+	public void process(TraceBuffer buffer) throws Exception {
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventPrintHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventPrintHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventPrintHandler.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import static java.lang.System.err;
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.SafepointBeginEvent;
+import sun.evtracing.parser.SafepointEndEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+
+public class TraceEventPrintHandler extends DelegateTraceEventHandler {
+
+	private long time = -1;
+
+	public TraceEventPrintHandler(TraceEventHandler delegate) {
+		super(delegate);
+	}
+
+	private String update(long time) {
+		long diff = time - this.time;
+		if (this.time == -1) {
+			diff = 0;
+		}
+		this.time = time;
+		return String.format("time +%05d", diff / 100);
+	}
+
+	@Override
+	public void threadStart(ThreadStartEvent event) {
+		err.printf("thread %d %s start: \"%s\"%n", event.thread().identifier(), update(event.timestamp()), event.name());
+		super.threadStart(event);
+	}
+
+	@Override
+	public void threadNameChange(ThreadNameChangeEvent event) {
+		err.printf("thread %d %s name change of thread %d: \"%s\"%n", event.thread().identifier(), update(event.timestamp()), event.affectedThread().identifier(), event.newName());
+		super.threadNameChange(event);
+	}
+
+	@Override
+	public void threadStateChange(ThreadStateChangeEvent event) {
+		err.printf("thread %d %s state change of thread %d: %s%n", event.thread().identifier(), update(event.timestamp()), event.affectedThread().identifier(), event.newState().toString());
+		super.threadStateChange(event);
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+		err.printf("thread %d %s interrupt of thread %d%n", event.thread().identifier(), update(event.timestamp()), event.affectedThread().identifier());
+		super.threadInterrupt(event);
+	}
+
+	@Override
+	public void threadExit(ThreadExitEvent event) {
+		err.printf("thread %d %s end%n", event.thread().identifier(), update(event.timestamp()));
+		super.threadExit(event);
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		err.printf("thread %d %s seq %05d park begin nestingLevel %d isAbsolute %b for %d%n", event.thread().identifier(), update(event.timestamp()), event.sequenceNumber(), event.nestingLevel(), event.isAbsolute(), event.parkTime());
+		super.threadParkBegin(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		err.printf("thread %d %s seq %05d park end %s caused by unpark %d%n", event.thread().identifier(), update(event.timestamp()), event.sequenceNumber(), event.parkReturnCode(), event.unparkSequenceNumber());
+		super.threadParkEnd(event);
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+		err.printf("thread %d %s seq %05d unpark thread %d replaced unpark %d%n", event.thread().identifier(), update(event.timestamp()), event.sequenceNumber(), event.unparkedThread().identifier(), event.chainedSequenceNumber());
+		super.threadUnpark(event);
+	}
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+		err.printf("thread %d %s inflated monitor %d%n", event.thread().identifier(), update(event.timestamp()), event.monitor());
+		super.monitorInflate(event);
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+		err.printf("thread %d %s deflated monitor %d%n", event.thread().identifier(), update(event.timestamp()), event.monitor());
+		super.monitorDeflate(event);
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+		err.printf("thread %d %s contended enter on %d with stack trace %d%n", event.thread().identifier(), update(event.timestamp()), event.monitor(), event.stack().identifier());
+		super.monitorContendedEnter(event);
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+		err.printf("thread %d %s contended entered on %d%n", event.thread().identifier(), update(event.timestamp()), event.monitor());
+		super.monitorContendedEntered(event);
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+		err.printf("thread %d %s contended exited on %d with stack trace %d%n", event.thread().identifier(), update(event.timestamp()), event.monitor(), event.stack().identifier());
+		super.monitorContendedExited(event);
+	}
+
+	@Override
+	public void classMetadata(ClassMetadataEvent event) {
+		err.printf("class %d from class loader %d has name %s%n", event.clazz(), event.classLoader(), event.name());
+		super.classMetadata(event);
+	}
+
+	@Override
+	public void safepointBegin(SafepointBeginEvent event) {
+		err.printf("thread %d %s begin safepoint %s%n", event.thread().identifier(), update(event.timestamp()), event.reason().toString());
+		super.safepointBegin(event);
+	}
+
+	@Override
+	public void safepointEnd(SafepointEndEvent event) {
+		err.printf("thread %d %s end safepoint, %d op(s) processed%n", event.thread().identifier(), update(event.timestamp()), event.processedOps());
+		super.safepointEnd(event);
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+		err.printf("thread %d %s end VM%n", event.thread().identifier(), update(event.timestamp()));
+		super.endVM(event);
+	}
+
+	@Override
+	public void methodMetadata(MethodMetadataEvent event) {
+		err.printf("method %d from class %d has name %s and signature %s%n", event.method(), event.clazz().identifier(), event.name(), event.signature());
+		super.methodMetadata(event);
+	}
+
+	@Override
+	public void classLoaderUnload(ClassLoaderUnloadEvent event) {
+		err.printf("class loader %d unloaded%n", event.classLoader());
+		super.classLoaderUnload(event);
+	}
+
+	@Override
+	public void stackMetadata(StackMetadataEvent event) {
+		err.printf("stack trace %d with %d frames%n", event.stack(), event.methods().length);
+		super.stackMetadata(event);
+	}
+
+	@Override
+	public void metadataReset(MetadataResetEvent event) {
+		err.printf("thread %d metadata reset%n", event.thread().identifier());
+		super.metadataReset(event);
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		err.printf("thread %d group %d %d src %s@%s%n", event.thread().identifier(), event.sequenceBeginReference(), event.sequenceNumber(), event.clazz().metadata().name(), Integer.toHexString(event.obj()));
+		super.group(event);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventReorderHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventReorderHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventReorderHandler.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorDummyEvent;
+import sun.evtracing.parser.MonitorEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.GlobalSequenceOrderedEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.NativeMonitorDummyEvent;
+import sun.evtracing.parser.NativeMonitorEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+
+public class TraceEventReorderHandler extends DelegateTraceEventHandler {
+
+	private int maxGlobalQueueLength = 0;
+	private int maxMonitorQueueLength = 0;
+
+	private final SequenceOrderedEventQueue globalQueue = new SequenceOrderedEventQueue(delegateHandler());
+	private final Map<Long, SequenceOrderedEventQueue> monitorQueues = new HashMap<>();
+	private final Map<Long, SequenceOrderedEventQueue> nativeMonitorQueues = new HashMap<>();
+
+	public TraceEventReorderHandler(TraceEventHandler handler) {
+		super(handler);
+	}
+
+	private SequenceOrderedEventQueue getOrCreateMonitorQueue(long monitor) {
+		return monitorQueues.computeIfAbsent(monitor, t -> new SequenceOrderedEventQueue(delegateHandler()));
+	}
+
+	private SequenceOrderedEventQueue getOrCreateNativeMonitorQueue(long monitor) {
+		return nativeMonitorQueues.computeIfAbsent(monitor, t -> new SequenceOrderedEventQueue(delegateHandler()));
+	}
+
+	private void handleGlobalSequenceOrderedEvent(GlobalSequenceOrderedEvent event) {
+		globalQueue.addEvent(event);
+		maxGlobalQueueLength = Math.max(maxGlobalQueueLength, globalQueue.size());
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+		handleGlobalSequenceOrderedEvent(event);
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		handleGlobalSequenceOrderedEvent(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		handleGlobalSequenceOrderedEvent(event);
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+		handleGlobalSequenceOrderedEvent(event);
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		handleGlobalSequenceOrderedEvent(event);
+	}
+
+	private void handleMonitorEvent(MonitorEvent event) {
+		SequenceOrderedEventQueue q = getOrCreateMonitorQueue(event.monitor());
+		q.addEvent(event);
+		maxMonitorQueueLength = Math.max(maxMonitorQueueLength, q.size());
+	}
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+		handleMonitorEvent(event);
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+		handleMonitorEvent(event);
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+		handleMonitorEvent(event);
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+		handleMonitorEvent(event);
+	}
+	
+	@Override
+	public void monitorDummy(MonitorDummyEvent event) {
+		handleMonitorEvent(event);
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+		handleMonitorEvent(event);
+	}
+
+	private void handleNativeMonitorEvent(NativeMonitorEvent event) {
+		SequenceOrderedEventQueue q = getOrCreateNativeMonitorQueue(event.monitor());
+		q.addEvent(event);
+		maxMonitorQueueLength = Math.max(maxMonitorQueueLength, q.size());
+	}
+
+	@Override
+	public void nativeMonitorInfo(NativeMonitorInfoEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void nativeMonitorDestroy(NativeMonitorDestroyEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void nativeMonitorDummy(NativeMonitorDummyEvent event) {
+		handleNativeMonitorEvent(event);
+	}
+
+	@Override
+	public void metadataReset(MetadataResetEvent event) {
+		// at this point, we must have received all missing events from Java(!) threads
+		assert globalQueue.size() == 0;
+		assert !monitorQueues.values().stream().anyMatch(q -> (q.size() != 0));
+		super.metadataReset(event);
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		map.put("max_global_queue_length", (double) maxGlobalQueueLength);
+		map.put("max_monitor_queue_length", (double) maxMonitorQueueLength);
+		map.put("monitor_queues", (double) monitorQueues.size());
+		super.putStatistics(map);
+	}
+
+	@Override
+	public void resetStatistics() {
+		maxGlobalQueueLength = maxMonitorQueueLength = 0;
+		super.resetStatistics();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventUniversalHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventUniversalHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventUniversalHandler.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import java.util.Map;
+
+import sun.evtracing.parser.ClassLoaderUnloadEvent;
+import sun.evtracing.parser.ClassMetadataEvent;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.IdenticalStacksMetadataEvent;
+import sun.evtracing.parser.MarkerEvent;
+import sun.evtracing.parser.MetadataResetEvent;
+import sun.evtracing.parser.MethodMetadataEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorDummyEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.NativeSymbolMetadataEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.NativeMonitorDummyEvent;
+import sun.evtracing.parser.SafepointBeginEvent;
+import sun.evtracing.parser.SafepointEndEvent;
+import sun.evtracing.parser.StackMetadataEvent;
+import sun.evtracing.parser.StackMetadataExtendedEvent;
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadNameChangeEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.ThreadStateChangeEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.TraceEvent;
+import sun.evtracing.parser.VMEndEvent;
+
+public abstract class TraceEventUniversalHandler implements TraceEventHandler {
+
+	static {
+		Sanity.assertNoInheritedAbstractMethods(TraceEventUniversalHandler.class);
+	}
+
+	public abstract void handle(TraceEvent event);
+
+	@Override
+	public void threadStart(ThreadStartEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadNameChange(ThreadNameChangeEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadStateChange(ThreadStateChangeEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadExit(ThreadExitEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+		handle(event);
+	}
+	
+	@Override
+	public void monitorDummy(MonitorDummyEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void safepointBegin(SafepointBeginEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void safepointEnd(SafepointEndEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void classMetadata(ClassMetadataEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void methodMetadata(MethodMetadataEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void classLoaderUnload(ClassLoaderUnloadEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void stackMetadata(StackMetadataEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void identicalStacksMetadata(IdenticalStacksMetadataEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void metadataReset(MetadataResetEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorInfo(NativeMonitorInfoEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLock(NativeMonitorContendedLockEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedLocked(NativeMonitorContendedLockedEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorContendedUnlocked(NativeMonitorContendedUnlockedEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorDestroy(NativeMonitorDestroyEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeMonitorDummy(NativeMonitorDummyEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void stackMetadataExtended(StackMetadataExtendedEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void nativeSymbolMetadata(NativeSymbolMetadataEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public void marker(MarkerEvent event) {
+		handle(event);
+	}
+
+	@Override
+	public abstract void putStatistics(Map<String, Double> map);
+
+	@Override
+	public abstract void resetStatistics();
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceEventValidateHandler.java b/src/java.base/share/classes/sun/evtracing/processing/TraceEventValidateHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceEventValidateHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+public class TraceEventValidateHandler extends AbstractTraceEventHandler {
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/TraceProcessor.java b/src/java.base/share/classes/sun/evtracing/processing/TraceProcessor.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/TraceProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing;
+
+import sun.evtracing.TraceBuffer;
+
+@SuppressWarnings("try")
+public interface TraceProcessor extends AutoCloseable {
+
+	public void process(TraceBuffer buffer) throws Exception;
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/Compression.java b/src/java.base/share/classes/sun/evtracing/processing/io/Compression.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/Compression.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package sun.evtracing.processing.io;
+
+import java.io.IOException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+public class Compression {
+
+	public static boolean isSupported() {
+		return false;
+	}
+
+	public static WritableByteChannel createCompressingChannel(WritableByteChannel channel) throws IOException {
+		throw new UnsupportedOperationException();
+	}
+
+	public static ReadableByteChannel createDecompressingChannel(ReadableByteChannel ch) throws IOException {
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/CountingReadableByteChannel.java b/src/java.base/share/classes/sun/evtracing/processing/io/CountingReadableByteChannel.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/CountingReadableByteChannel.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.io;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+public class CountingReadableByteChannel implements ReadableByteChannel {
+
+	private final ReadableByteChannel inner;
+	private long bytesRead;
+
+	public CountingReadableByteChannel(ReadableByteChannel inner) {
+		this.inner = inner;
+	}
+
+	@Override
+	public int read(ByteBuffer dst) throws IOException {
+		int bytes = inner.read(dst);
+		bytesRead += bytes;
+		return bytes;
+	}
+
+	@Override
+	public boolean isOpen() {
+		return inner.isOpen();
+	}
+
+	@Override
+	public void close() throws IOException {
+		inner.close();
+	}
+
+	public long bytesRead() {
+		return bytesRead;
+	}
+
+	public void resetBytesRead() {
+		bytesRead = 0;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/CountingWritableByteChannel.java b/src/java.base/share/classes/sun/evtracing/processing/io/CountingWritableByteChannel.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/CountingWritableByteChannel.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.io;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+class CountingWritableByteChannel implements WritableByteChannel {
+
+	private final WritableByteChannel inner;
+	private long bytesWritten;
+
+	public CountingWritableByteChannel(WritableByteChannel inner) {
+		this.inner = inner;
+	}
+
+	@Override
+	public boolean isOpen() {
+		return inner.isOpen();
+	}
+
+	@Override
+	public void close() throws IOException {
+		inner.close();
+	}
+
+	@Override
+	public int write(ByteBuffer src) throws IOException {
+		int written = inner.write(src);
+		bytesWritten += written;
+		return written;
+	}
+
+	public long bytesWritten() {
+		return bytesWritten;
+	}
+
+	public void resetBytesWritten() {
+		bytesWritten = 0;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelReader.java b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelReader.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelReader.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.io;
+
+import static sun.evtracing.processing.io.TraceDataFormat.BYTE_ORDER;
+import static sun.evtracing.processing.io.TraceDataFormat.FLAG_COMPRESSED;
+import static sun.evtracing.processing.io.TraceDataFormat.MAGIC;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+import sun.evtracing.TraceBuffer;
+import sun.evtracing.processing.ProgressCallback;
+import sun.evtracing.processing.TraceProcessor;
+
+public class TraceDataChannelReader implements AutoCloseable {
+
+	private final ReadableByteChannel channel;
+	private final TraceProcessor processor;
+
+	public TraceDataChannelReader(ReadableByteChannel channel, TraceProcessor processor) {
+		this.channel = channel;
+		this.processor = processor;
+	}
+
+	public void readToEnd(ProgressCallback callback) throws Exception {
+		CountingReadableByteChannel input = new CountingReadableByteChannel(channel);
+		ReadableByteChannel ch = input;
+
+		ByteBuffer header = ByteBuffer.allocate(Long.BYTES + Integer.BYTES);
+		header.order(BYTE_ORDER);
+		header.limit(Integer.BYTES * 2);
+		readFully(ch, header);
+
+		header.rewind();
+		if (header.getInt() != MAGIC) {
+			throw new RuntimeException("expected magic");
+		}
+		int flags = header.getInt();
+		if ((flags & FLAG_COMPRESSED) != 0) {
+			ch = Compression.createDecompressingChannel(ch);
+		}
+
+		header.limit(Long.BYTES + Integer.BYTES);
+		header.rewind();
+		while (header.rewind() != null && tryReadFully(ch, header)) {
+			header.rewind();
+			long thread = header.getLong();
+			int length = header.getInt();
+			assert length >= 0;
+
+			ByteBuffer events = ByteBuffer.allocate(length);
+			events.order(BYTE_ORDER);
+			readFully(ch, events);
+
+			events.rewind();
+			processor.process(new TraceBuffer(events, thread));
+
+			if (callback != null) {
+				callback.bufferRead();
+				callback.totalInputBytesRead(input.bytesRead());
+			}
+		}
+	}
+
+	private boolean tryReadFully(ReadableByteChannel ch, ByteBuffer buffer) throws IOException {
+		int total = 0;
+		do {
+			int bytes = ch.read(buffer);
+			if (bytes < 0) {
+				if (total == 0) {
+					return false;
+				}
+				throw new EOFException("mid-buffer");
+			}
+			total += bytes;
+		} while (total != buffer.limit());
+		return true;
+	}
+
+	private void readFully(ReadableByteChannel ch, ByteBuffer buffer) throws IOException {
+		if (!tryReadFully(ch, buffer)) {
+			throw new EOFException("start");
+		}
+	}
+
+	@Override
+	public void close() throws IOException {
+		channel.close();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelWriter.java b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelWriter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataChannelWriter.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.io;
+
+import static sun.evtracing.processing.io.TraceDataFormat.BYTE_ORDER;
+import static sun.evtracing.processing.io.TraceDataFormat.FLAG_COMPRESSED;
+import static sun.evtracing.processing.io.TraceDataFormat.MAGIC;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.util.Map;
+
+import sun.evtracing.StatisticsProvider;
+import sun.evtracing.TraceBuffer;
+import sun.evtracing.processing.TraceProcessor;
+
+
+public class TraceDataChannelWriter implements TraceProcessor, StatisticsProvider {
+
+	private final CountingWritableByteChannel channel;
+	private final CountingWritableByteChannel compressed;
+
+	public TraceDataChannelWriter(WritableByteChannel channel) throws IOException {
+		this(channel, false);
+	}
+
+	public TraceDataChannelWriter(WritableByteChannel channel, boolean compress) throws IOException {
+		writeFileHeader(channel, compress ? FLAG_COMPRESSED : 0);
+		if (compress) {
+			this.compressed = new CountingWritableByteChannel(channel);
+			channel = Compression.createCompressingChannel(this.compressed);
+		} else {
+			this.compressed = null;
+		}
+		this.channel = new CountingWritableByteChannel(channel);
+	}
+
+	private void writeFileHeader(WritableByteChannel bc, int flags) throws IOException {
+		ByteBuffer header = ByteBuffer.allocate(Integer.BYTES * 2);
+		header.order(BYTE_ORDER);
+		header.putInt(MAGIC);
+		header.putInt(flags);
+		header.rewind();
+		bc.write(header);
+	}
+
+	@Override
+	public void process(TraceBuffer buffer) throws IOException {
+		writeHeader(buffer);
+		ByteBuffer bytes = buffer.bytes();
+		assert bytes.order() == BYTE_ORDER;
+		assert bytes.position() == 0;
+		channel.write(bytes);
+	}
+
+	private void writeHeader(TraceBuffer buffer) throws IOException {
+		ByteBuffer header = ByteBuffer.allocate(Long.BYTES + Integer.BYTES);
+		header.order(TraceDataFormat.BYTE_ORDER);
+		header.putLong(buffer.thread());
+		header.putInt(buffer.bytes().capacity());
+		header.rewind();
+		channel.write(header);
+	}
+
+	@Override
+	public void close() throws IOException {
+		channel.close();
+	}
+
+	@Override
+	public void putStatistics(Map<String, Double> map) {
+		map.put("written_trace_bytes", (double) channel.bytesWritten());
+		if (compressed != null) {
+			map.put("written_compressed_trace_bytes", (double) compressed.bytesWritten());
+		}
+	}
+
+	@Override
+	public void resetStatistics() {
+		channel.resetBytesWritten();
+		if (compressed != null) {
+			compressed.resetBytesWritten();
+		}
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataFormat.java b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataFormat.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/io/TraceDataFormat.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.io;
+
+import java.nio.ByteOrder;
+
+public class TraceDataFormat {
+	static final int MAGIC = 0x724CEF17;
+	static final int FLAG_COMPRESSED = 0x1;
+	static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorAnalyser.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.JavaImmutableSingleObjectStack;
+
+public class MonitorAnalyser {
+
+	private final JavaObjectStack objectStack;
+	private final ContentionProcessor processor;
+	private final Map<JavaThread, MonitorContender> contenders = new HashMap<>();
+
+	private MonitorAnalyser(JavaObjectStack object, ContentionProcessor processor) {
+		this.objectStack = object;
+		this.processor = processor;
+	}
+
+	public void enter(MonitorContendedEnterEvent event) {
+		assert !contenders.containsKey(event.thread().metadata());
+		contenders.put(event.thread().metadata(), MonitorContender.forEnter(objectStack, event, processor));
+	}
+
+	public void entered(MonitorContendedEnteredEvent event) {
+		MonitorContender owner = contenders.remove(event.thread().metadata());
+		owner.monitorContendedEntered(event);
+	}
+
+	public void exited(MonitorContendedExitedEvent event) {
+		contenders.values().forEach(c -> c.contenderExitedMonitor(event));
+	}
+
+	public void deflate(MonitorDeflateEvent event) {
+		assert contenders.isEmpty();
+	}
+
+	public static MonitorAnalyser forInflate(MonitorInflateEvent event, ContentionProcessor processor) {
+		JavaObject obj = JavaObject.get(event.object(), event.clazz().metadata());
+		return new MonitorAnalyser(new JavaImmutableSingleObjectStack(obj), processor);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorContender.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorContender.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/MonitorContender.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorEnterWait;
+import sun.evtracing.parser.MonitorEnteredFlags;
+import sun.evtracing.parser.MonitorEvent;
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+
+public class MonitorContender {
+
+	private final JavaObjectStack objectStack;
+	private final ContentionProcessor processor;
+	private final MonitorContendedEnterEvent enter;
+
+	private MonitorEvent lastEvent;
+
+	public static MonitorContender forEnter(JavaObjectStack objectStack, MonitorContendedEnterEvent event, ContentionProcessor processor) {
+		return new MonitorContender(objectStack, event, processor);
+	}
+
+	private MonitorContender(JavaObjectStack objectStack, MonitorContendedEnterEvent event, ContentionProcessor processor) {
+		this.objectStack = objectStack;
+		this.enter = event;
+		this.processor = processor;
+		this.lastEvent = event;
+	}
+
+	private Group group() {
+		if (enter.afterWait() != MonitorEnterWait.NoWait) {
+			return Group.MonitorWaitReentry;
+		}
+		return Group.Monitors;
+	}
+
+	private boolean wasEntered() {
+		return (lastEvent.type() == TraceEventType.MonitorContendedEntered);
+	}
+
+	void contenderExitedMonitor(MonitorContendedExitedEvent exit) {
+		assert !wasEntered();
+		long startTime = lastEvent.timestamp();
+		long duration = exit.timestamp() - startTime;
+		processor.submit(new Contention(group(), enter.thread().metadata(), exit.thread().metadata(), enter.stack().metadata(), exit.stack().metadata(), objectStack, startTime, duration));
+		lastEvent = exit;
+	}
+
+	void monitorContendedEntered(MonitorContendedEnteredEvent entered) {
+		assert !wasEntered();
+		if (entered.flags().contains(MonitorEnteredFlags.Queued)) {
+			if (entered.flags().contains(MonitorEnteredFlags.Parked)) {
+				Sanity.warnIf(lastEvent == enter, "entered monitor after parking without prior contender exit (rare race)");					
+			} else {
+				Sanity.warnIf(lastEvent == enter, "entered monitor after queueing without prior contender exit (race)");					
+			}
+		} else {
+			// the thread managed to obtain the lock only by spinning, not entering
+			// itself on any queue. therefore, the contender could not have noticed it
+			// and has not written an exit event unless another thread was waiting.
+		}
+		// attribute period between last exit and entered to unknown
+		long startTime = lastEvent.timestamp();
+		long duration = entered.timestamp() - startTime;
+		processor.submit(new Contention(group(), enter.thread().metadata(), JavaThread.UNKNOWN, enter.stack().metadata(), JavaStack.UNKNOWN, objectStack, startTime, duration));
+		lastEvent = entered;
+	}
+
+	void monitorContendedExited(long time) {
+		// nothing to do so far
+	}
+
+	@Override
+	public String toString() {
+		return enter.thread().metadata().toString() + " blocking on " + objectStack.toString();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorAnalyser.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorInfoEvent;
+import sun.evtracing.parser.NativeMonitorDestroyEvent;
+import sun.evtracing.parser.metadata.JavaClass;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.JavaImmutableSingleObjectStack;
+
+public class NativeMonitorAnalyser {
+
+	private final JavaObjectStack objectStack;
+	private final ContentionProcessor processor;
+	private final Map<JavaThread, NativeMonitorContender> contenders = new HashMap<>();
+
+	private NativeMonitorAnalyser(JavaObjectStack objectStack, ContentionProcessor processor) {
+		this.objectStack = objectStack;
+		this.processor = processor;
+	}
+
+	public void lock(NativeMonitorContendedLockEvent event) {
+		assert !contenders.containsKey(event.thread().metadata());
+		contenders.put(event.thread().metadata(), NativeMonitorContender.forLock(objectStack, event, processor));
+	}
+
+	public void locked(NativeMonitorContendedLockedEvent event) {
+		NativeMonitorContender owner = contenders.remove(event.thread().metadata());
+		owner.monitorContendedLocked(event);
+	}
+
+	public void unlocked(NativeMonitorContendedUnlockedEvent event) {
+		contenders.values().forEach(c -> c.contenderUnlockedMonitor(event));
+	}
+
+	public void destroy(NativeMonitorDestroyEvent event) {
+		assert contenders.isEmpty();
+	}
+
+	public static NativeMonitorAnalyser forInfo(NativeMonitorInfoEvent event, ContentionProcessor processor) {
+		JavaClass fakeClass = new JavaClass(event.monitor());
+		String fakeClassName = "hotspot/locks/" + event.name().replace('/', '_').replace('[', '_');
+		fakeClass.set(Long.MAX_VALUE, fakeClassName);
+		JavaObject fakeObject = JavaObject.get(Long.hashCode(event.monitor()), fakeClass);
+		return new NativeMonitorAnalyser(new JavaImmutableSingleObjectStack(fakeObject), processor);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorContender.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorContender.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/NativeMonitorContender.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.parser.MonitorEnterWait;
+import sun.evtracing.parser.NativeMonitorContendedLockEvent;
+import sun.evtracing.parser.NativeMonitorContendedLockedEvent;
+import sun.evtracing.parser.NativeMonitorContendedUnlockedEvent;
+import sun.evtracing.parser.NativeMonitorEvent;
+import sun.evtracing.parser.TraceEventType;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+
+public class NativeMonitorContender {
+
+	private final JavaObjectStack objectStack;
+	private final ContentionProcessor processor;
+	private final NativeMonitorContendedLockEvent enter;
+
+	private NativeMonitorEvent lastEvent;
+
+	public static NativeMonitorContender forLock(JavaObjectStack objectStack, NativeMonitorContendedLockEvent event, ContentionProcessor processor) {
+		return new NativeMonitorContender(objectStack, event, processor);
+	}
+
+	private NativeMonitorContender(JavaObjectStack objectStack, NativeMonitorContendedLockEvent event, ContentionProcessor processor) {
+		this.objectStack = objectStack;
+		this.enter = event;
+		this.processor = processor;
+		this.lastEvent = event;
+	}
+
+	private Group group() {
+		if (enter.afterWait() != MonitorEnterWait.NoWait) {
+			return Group.NativeMonitorsWaitReentry;
+		}
+		return Group.NativeMonitors;
+	}
+
+	private boolean wasLocked() {
+		return (lastEvent.type() == TraceEventType.NativeMonitorContendedLocked);
+	}
+
+	void contenderUnlockedMonitor(NativeMonitorContendedUnlockedEvent exit) {
+		assert !wasLocked();
+		long startTime = lastEvent.timestamp();
+		long duration = exit.timestamp() - startTime;
+		processor.submit(new Contention(group(), enter.thread().metadata(), exit.thread().metadata(), enter.stack().metadata(), exit.stack().metadata(), objectStack, startTime, duration));
+		lastEvent = exit;
+	}
+
+	void monitorContendedLocked(NativeMonitorContendedLockedEvent entered) {
+		assert !wasLocked();
+		// attribute period between last exit and entered to unknown
+		long startTime = lastEvent.timestamp();
+		long duration = entered.timestamp() - startTime;
+		processor.submit(new Contention(group(), enter.thread().metadata(), JavaThread.UNKNOWN, enter.stack().metadata(), JavaStack.UNKNOWN, objectStack, startTime, duration));
+		lastEvent = entered;
+	}
+
+	void monitorContendedUnlocked(long time) {
+		// nothing to do so far
+	}
+
+	@Override
+	public String toString() {
+		return enter.thread().metadata().toString() + " blocking on " + objectStack.toString();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/NumberStatistic.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/NumberStatistic.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/NumberStatistic.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+public class NumberStatistic {
+	public static NumberStatistic merge(NumberStatistic x, NumberStatistic y) {
+		NumberStatistic s = new NumberStatistic();
+		s.max = Math.max(x.max, y.max);
+		s.count = x.count + y.count;
+		s.sum = x.sum + y.sum;
+		return s;
+	}
+
+	private long max;
+	private long sum;
+	private long count;
+
+	public long getSum() {
+		return sum;
+	}
+
+	public double getAverage() {
+		if (count > 0) {
+			return sum / count;
+		} else {
+			return Double.NaN;
+		}
+	}
+
+	public long getMax() {
+		return max;
+	}
+
+	public void add(long value) {
+		max = Math.max(max, value);
+		sum += value;
+		count++;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkAnalyser.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.JavaObjectArrayStack;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkAnalyser {
+	private static final int UNSIGNED_BYTE_VALUES = 1 << Byte.SIZE;
+
+	private final ParkBlockerAnalyser dispatcher;
+
+	private ParkEventTuple currentTuple = null;
+	private final Map<Long, ThreadUnparkEvent> unmatchedUnpark = new HashMap<>();
+	private boolean unmatchedInterrupt = false;
+
+	@SuppressWarnings({"unchecked", "rawtypes"})
+	private final List<ParkEventTuple>[] group = new ArrayList[UNSIGNED_BYTE_VALUES];
+	private int currentNestingLevel;
+
+	private class ConsumingUnparkEventIterator implements Iterator<ThreadUnparkEvent> {
+		private long nextChainedSeq;
+
+		public ConsumingUnparkEventIterator(long nextChainedSeq) {
+			this.nextChainedSeq = nextChainedSeq;
+		}
+
+		@Override
+		public boolean hasNext() {
+			return nextChainedSeq > 0;
+		}
+
+		@Override
+		public ThreadUnparkEvent next() {
+			ThreadUnparkEvent e = unmatchedUnpark.remove(nextChainedSeq);
+			if (e == null) {
+				throw new NoSuchElementException("Unpark " + nextChainedSeq + " not found");
+			}
+			nextChainedSeq = e.chainedSequenceNumber();
+			return e;
+		}
+	}
+
+	public ParkAnalyser(ParkBlockerAnalyser dispatcher) {
+		this.dispatcher = dispatcher;
+	}
+
+	public void begin(ThreadParkBeginEvent event) {
+		assert event.sequenceNumber() > 0;
+		assert currentTuple == null;
+
+		int nestingLevel = event.nestingLevel();
+		JavaObjectStack blockerStack = new JavaObjectArrayStack(nestingLevel + 1);
+		blockerStack.setObject(nestingLevel, JavaObject.get(event.blockerObject(), event.clazz().metadata()));
+		currentTuple = new ParkEventTuple(event, blockerStack);
+
+		dispatcher.begin(currentTuple);
+	}
+
+	public void end(ThreadParkEndEvent event) {
+		assert event.sequenceNumber() > 0;
+		assert event.sequenceNumber() > event.unparkSequenceNumber();
+		assert currentTuple != null;
+		assert currentTuple.begin() != null;
+		assert currentTuple.end() == null;
+		assert currentTuple.unpark() == null;
+		assert event.sequenceNumber() > currentTuple.begin().sequenceNumber();
+		assert event.timestamp() >= currentTuple.begin().timestamp(); // hopefully
+
+		currentTuple.setEnd(event);
+		dispatcher.end(currentTuple);
+
+		if (event.parkReturnCode().hasUnpark()) {
+			assert event.unparkSequenceNumber() > 0;
+
+			ThreadUnparkEvent unpark = unmatchedUnpark.remove(event.unparkSequenceNumber());
+			assert unpark != null;
+
+			ignorePrecedingUnparks(unpark.chainedSequenceNumber());
+
+			currentTuple.setUnpark(unpark);
+
+			currentTuple.setInterrupted(unmatchedInterrupt);
+			unmatchedInterrupt = false;
+		} else {
+			assert event.unparkSequenceNumber() == 0 || event.unparkSequenceNumber() == -1;
+		}
+
+		int nestingLevel = currentTuple.begin().nestingLevel();
+		if (nestingLevel > 0) {
+			keepContention(nestingLevel, currentTuple);
+		} else {
+			dispatcher.finish(currentTuple);
+		}
+
+		currentTuple = null;
+	}
+
+	public void unpark(ThreadUnparkEvent event) {
+		assert event.sequenceNumber() > 0;
+		unmatchedUnpark.put(event.sequenceNumber(), event);
+	}
+
+	public void interrupt(ThreadInterruptEvent event) {
+		assert event.sequenceNumber() > 0;
+		unmatchedInterrupt = true;
+	}
+
+	public void group(GroupEvent event) {
+		List<ParkEventTuple> parks = group[currentNestingLevel];
+		if (parks != null) {
+			JavaObject blocker = JavaObject.get(event.obj(), event.clazz().metadata());
+			for (ParkEventTuple tuple : parks) {
+				tuple.blocker().setObject(currentNestingLevel, blocker);
+			}
+			group[currentNestingLevel] = null;
+			if (currentNestingLevel > 0) {
+				currentNestingLevel--;
+				List<ParkEventTuple> contentionsNext = groupLevel(currentNestingLevel);
+				contentionsNext.addAll(parks);
+			} else {
+				for (ParkEventTuple tuple : parks) {
+					dispatcher.finish(tuple);
+				}
+			}
+		}
+	}
+
+	private void ignorePrecedingUnparks(long precedingUnparkSeq) {
+		Iterator<ThreadUnparkEvent> it = new ConsumingUnparkEventIterator(precedingUnparkSeq);
+		while (it.hasNext()) {
+			it.next();
+		}
+	}
+
+	private void keepContention(int nestingLevel, ParkEventTuple p) {
+		int level = nestingLevel - 1;
+		List<ParkEventTuple> parks = groupLevel(level);
+
+		assert currentNestingLevel <= level;
+		currentNestingLevel = level;
+
+		parks.add(p);
+	}
+
+	private List<ParkEventTuple> groupLevel(int nestingLevel) {
+		List<ParkEventTuple> groupLevel = group[nestingLevel];
+		if (groupLevel == null) {
+			group[nestingLevel] = groupLevel = new ArrayList<>();
+		}
+		return groupLevel;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAbstractQueuedSynchronizerAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAbstractQueuedSynchronizerAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAbstractQueuedSynchronizerAnalyser.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import sun.evtracing.parser.GlobalSequenceOrderedEvent;
+import sun.evtracing.parser.ParkReturnCode;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public abstract class ParkBlockerAbstractQueuedSynchronizerAnalyser implements ParkBlockerAnalyser {
+	// Defines how to handle time between unpark and parkEnd
+	public enum BlameShiftingMode {
+		ACCURATE,	// shift to unknown
+		PREVIOUS,	// shift to previous lock holder
+		NEXT,		// shift to next lock holder
+	}
+
+	@FunctionalInterface
+	public interface PrevNextConsumer<T> {
+		public void accept(T prev, T cur, T next);
+	}
+
+	private static final BlameShiftingMode blameShiftingMode = BlameShiftingMode.valueOf(System.getProperty("sun.evtracing.jucBlameShifitingMode", "NEXT"));
+	private final ContentionProcessor cproc;
+	private final Set<ParkEventTuple> parker = new HashSet<>();
+	private long lastEnd;
+	private long submittedDuration;
+
+	public ParkBlockerAbstractQueuedSynchronizerAnalyser(ContentionProcessor cproc) {
+		this.cproc = cproc;
+	}
+
+	@Override
+	public void begin(ParkEventTuple tuple) {
+		parker.add(tuple);
+	}
+
+	@Override
+	public void end(ParkEventTuple tuple) {
+		parker.remove(tuple);
+
+		for (ParkEventTuple t : parker) {
+			t.addOverlapping(tuple);
+		}
+	}
+
+	@Override
+	public void finish(ParkEventTuple tuple) {
+		try {
+			List<ParkEventTuple> overlapping = tuple.overlapping().stream()
+				.filter(t -> !t.isInterrupted() && t.knownOwner())
+				.sorted(new ParkEventTupleUnparkComparator())
+				.collect(Collectors.toList());
+
+			overlapping.add(tuple);
+
+			lastEnd = tuple.begin().timestamp();
+			submittedDuration = 0;
+			iterateWithPrevNext(overlapping, (prev, cur, next) -> processOverlappingContention(tuple, prev, cur, next));
+
+			assert tuple.end().timestamp() - tuple.begin().timestamp() == submittedDuration;
+		} catch (AssertionError | RuntimeException e) {
+			ParkEventTupleJsonSerializer.serialize("traceviewer_timestamp.json", tuple, false);
+			ParkEventTupleJsonSerializer.serialize("traceviewer_sequence.json", tuple, true);
+			throw e;
+		} finally {
+			lastEnd = 0;
+			submittedDuration = 0;
+		}
+	}
+
+	private <T> void iterateWithPrevNext(Iterable<T> iterable, PrevNextConsumer<T> consumer) {
+		T prev;
+		T cur = null;
+		T next = null;
+		for (T t : iterable) {
+			prev = cur;
+			cur = next;
+			next = t;
+			if (cur != null) {
+				consumer.accept(prev, cur, next);
+			}
+		}
+		if (next != null) {
+			consumer.accept(cur, next, null);
+		}
+	}
+
+	private void processOverlappingContention(ParkEventTuple tuple, ParkEventTuple prev, ParkEventTuple cur, ParkEventTuple next) {
+		if (Sanity.isEnabled()) {
+			assertContentionTransition(tuple, prev, cur, next);
+		}
+
+		boolean submitKnown;
+		if (next != null) {
+			submitKnown = cur.knownOwner() && tuple.begin().sequenceNumber() < cur.unpark().sequenceNumber();
+		} else {
+			assert cur == tuple;
+			submitKnown = cur.knownOwner() && cur.causedContention();
+			if (!submitKnown && cur.end().parkReturnCode() == ParkReturnCode.TimedOut) {
+				// TODO: Special handling necessary for pushing remaining duration
+			}
+		}
+		if (submitKnown) {
+			JavaThread contendingThread = cur.end().thread().metadata();
+			JavaThread ownerThread;
+			JavaStack ownerSite;
+			if (isShared(cur)) {
+				ownerThread = sharedThread();
+				ownerSite = sharedSite();
+			} else {
+				ownerThread = cur.unpark().thread().metadata();
+				assert contendingThread.threadId() != ownerThread.threadId();
+				ownerSite = cur.unpark().stack().metadata();
+			}
+			long unparkTime;
+			if (blameShiftingMode == BlameShiftingMode.PREVIOUS) {
+				unparkTime = cur.end().timestamp();
+			} else {
+				unparkTime = cur.unpark().timestamp();
+			}
+			long duration = unparkTime - lastEnd;
+
+			submitContention(tuple, ownerThread, ownerSite, lastEnd, duration);
+
+			lastEnd = unparkTime;
+		}
+
+		if (next == null || (blameShiftingMode != BlameShiftingMode.NEXT && isSequentialUnpark(cur, next))) {
+			long endTime = cur.end().timestamp();
+			long duration = endTime - lastEnd;
+
+			if (duration != 0) {
+				submitContention(tuple, JavaThread.UNKNOWN, JavaStack.UNKNOWN, lastEnd, duration);
+
+				lastEnd = endTime;
+			}
+		}
+	}
+
+	abstract boolean isShared(ParkEventTuple cur);
+	abstract JavaThread sharedThread();
+	abstract JavaStack sharedSite();
+
+	private boolean isSequentialUnpark(ParkEventTuple cur, ParkEventTuple next) {
+		return cur.end().sequenceNumber() < next.end().unparkSequenceNumber();
+	}
+
+	private void assertContentionTransition(ParkEventTuple tuple, ParkEventTuple prev, ParkEventTuple cur, ParkEventTuple next) {
+		if (next != null) {
+			// cur.begin().sequenceNumber() < tuple.begin().sequenceNumber() is not always fulfilled
+			// as a thread may have to park multiple times because the lock was sneaked by other threads
+			assert tuple.begin().sequenceNumber() < cur.end().sequenceNumber();
+			assert cur.end().sequenceNumber() < tuple.end().sequenceNumber();
+		}
+
+		if (prev != null) {
+			boolean sequentialUnpark = cur.knownOwner() && prev.end().sequenceNumber() < cur.unpark().sequenceNumber();
+			GlobalSequenceOrderedEvent prevLastEvent;
+			if (sequentialUnpark) {
+				prevLastEvent = prev.end();
+			} else {
+				prevLastEvent = prev.unpark();
+			}
+			// prev.begin().sequenceNumber() < cur.begin().sequenceNumber() is not always fulfilled
+			// as the begin sequence number does not correspond to the enqueuing order
+			assert prevLastEvent.sequenceNumber() < cur.end().sequenceNumber();
+			if (next != null || sequentialUnpark) {
+				assert prevLastEvent.sequenceNumber() < cur.unpark().sequenceNumber();
+			}
+			if (!cur.knownOwner()) {
+				assert next == null;
+				assert cur == tuple;
+				// ignore
+			} else if (!sequentialUnpark) {
+				// unpark out of queue order -> last owner sneaked the lock
+				// concurrent unpark -> multiple unpark/end overlap
+				if (prev.end().sequenceNumber() < cur.end().sequenceNumber()) {
+					if (!prev.causedContention() || !cur.causedContention()) {
+						// unharmful concurrent unpark
+					} else {
+						Sanity.warn("inaccurate blame-shifting during concurrent unpark");
+					}
+				} else if (next != null || prev.unpark().sequenceNumber() < cur.unpark().sequenceNumber()) {
+					//assert !prev.causedContention() || !cur.causedContention();
+				}
+			} else if (prev.begin().thread().identifier() == cur.unpark().thread().identifier()) {
+				// unpark according to queue order -> last owner followed queue order
+				// cur.begin().sequenceNumber() < prevLastEvent.sequenceNumber() is not always fulfilled
+				// as the begin sequence number does not correspond to the enqueuing order
+			} else if (prev.begin().thread().identifier() == cur.begin().thread().identifier()) {
+				// unpark out of queue order -> last owner sneaked the lock
+				// thread already parked again
+				assert prevLastEvent.sequenceNumber() < cur.begin().sequenceNumber();
+			} else if (!prev.causedContention()) {
+				// unpark out of queue order -> last owner sneaked the lock
+				// previous wakeup was spurious
+			} else {
+				// unpark out of queue order -> last owner sneaked the lock
+				// special case:
+				// * T1 owns lock, T2, T4 is next on the wait queue
+				// * T1 unparks T2
+				// * T2 returns from park call
+				// * some thread interrupts T2
+				// * T2 does not acquire lock and cancels its queue entry
+				// * T3 sneaks the lock
+				// * T3 unparks T4 as T2 is already canceled
+				// * T2 tries to unpark a successor
+			}
+		}
+	}
+
+	private void submitContention(ParkEventTuple tuple, JavaThread ownerThread, JavaStack ownerSite, long startTime, long duration) {
+		JavaThread contendingThread = tuple.end().thread().metadata();
+		JavaStack contendingSite = tuple.begin().stack().metadata();
+		JavaObjectStack blocker = tuple.blocker();
+
+		cproc.submit(new Contention(Group.JavaUtilConcurrent, contendingThread, ownerThread, contendingSite, ownerSite, blocker, startTime, duration));
+		submittedDuration += duration;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerAnalyser.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public interface ParkBlockerAnalyser {
+	void begin(ParkEventTuple tuple);
+	void end(ParkEventTuple tuple);
+	void finish(ParkEventTuple tuple);
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerDispatcher.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerDispatcher.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerDispatcher.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkBlockerDispatcher implements ParkBlockerAnalyser {
+	private final ContentionProcessor cproc;
+	private final ParkBlockerAnalyser nopAnalyser;
+
+	private final Map<JavaObject, ParkBlockerAnalyser> analyser = new HashMap<>();
+
+	public ParkBlockerDispatcher(ContentionProcessor cproc) {
+		this(cproc, null);
+	}
+
+	public ParkBlockerDispatcher(ContentionProcessor cproc, Pattern[] condWaitPatterns) {
+		this.cproc = cproc;
+		this.nopAnalyser = new ParkBlockerNopAnalyser(cproc, condWaitPatterns);
+	}
+
+	private ParkBlockerAnalyser getOrCreate(ParkEventTuple tuple) {
+		JavaObject blocker = tuple.blocker().top();
+
+		ParkBlockerAnalyser a = analyser.get(blocker);
+		if (a != null) {
+			return a;
+		}
+
+		a = create(blocker);
+		if (a != null) {
+			analyser.put(blocker, a);
+			return a;
+		}
+
+		return nopAnalyser;
+	}
+
+	private ParkBlockerAnalyser create(JavaObject obj) {
+		switch (obj.clazz().name()) {
+		case "java/util/concurrent/locks/ReentrantLock$FairSync":
+		case "java/util/concurrent/locks/ReentrantLock$NonfairSync":
+			return new ParkBlockerReentrantLockAnalyser(cproc);
+		case "java/util/concurrent/locks/ReentrantReadWriteLock$FairSync":
+		case "java/util/concurrent/locks/ReentrantReadWriteLock$NonfairSync":
+			return new ParkBlockerReentrantReadWriteLockAnalyser(cproc);
+		default:
+			return null;
+		}
+	}
+
+	@Override
+	public void begin(ParkEventTuple tuple) {
+		getOrCreate(tuple).begin(tuple);
+	}
+
+	@Override
+	public void end(ParkEventTuple tuple) {
+		getOrCreate(tuple).end(tuple);
+	}
+
+	@Override
+	public void finish(ParkEventTuple tuple) {
+		getOrCreate(tuple).finish(tuple);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerNopAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerNopAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerNopAnalyser.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkBlockerNopAnalyser implements ParkBlockerAnalyser {
+	private final ContentionProcessor cproc;
+
+	private final Pattern[] condWaitPatterns;
+
+	public ParkBlockerNopAnalyser(ContentionProcessor cproc, Pattern[] condWaitPatterns) {
+		this.cproc = cproc;
+		this.condWaitPatterns = condWaitPatterns;
+	}
+
+	@Override
+	public void begin(ParkEventTuple tuple) {
+		// nothing
+	}
+
+	@Override
+	public void end(ParkEventTuple tuple) {
+		// nothing
+	}
+
+	@Override
+	public void finish(ParkEventTuple tuple) {
+		JavaThread contendingThread = tuple.end().thread().metadata();
+		JavaThread ownerThread = JavaThread.UNKNOWN;
+		JavaStack contendingSite = tuple.begin().stack().metadata();
+		JavaStack ownerSite = JavaStack.UNKNOWN;
+		JavaObjectStack blocker = tuple.blocker();
+		long startTime = tuple.begin().timestamp();
+		long duration = tuple.end().timestamp() - startTime;
+
+		Group group = Group.JavaUtilConcurrent;
+		if (condWaitPatterns != null) {
+			for (Pattern p : condWaitPatterns) {
+				Matcher m = p.matcher(blocker.top().clazz().toString());
+				if (m.matches()) {
+					group = Group.JavaUtilConcurrentConditionalWaiting;
+					break;
+				}
+			}
+		}
+
+		cproc.submit(new Contention(group, contendingThread, ownerThread, contendingSite, ownerSite, blocker, startTime, duration));
+	}
+	
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantLockAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantLockAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantLockAnalyser.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkBlockerReentrantLockAnalyser extends ParkBlockerAbstractQueuedSynchronizerAnalyser {
+	public ParkBlockerReentrantLockAnalyser(ContentionProcessor cproc) {
+		super(cproc);
+	}
+
+	@Override
+	boolean isShared(ParkEventTuple cur) {
+		return false;
+	}
+
+	@Override
+	JavaThread sharedThread() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	JavaStack sharedSite() {
+		throw new UnsupportedOperationException();
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantReadWriteLockAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantReadWriteLockAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkBlockerReentrantReadWriteLockAnalyser.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaStackFrame;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkBlockerReentrantReadWriteLockAnalyser extends ParkBlockerAbstractQueuedSynchronizerAnalyser {
+	public ParkBlockerReentrantReadWriteLockAnalyser(ContentionProcessor cproc) {
+		super(cproc);
+	}
+
+	@Override
+	boolean isShared(ParkEventTuple cur) {
+		for (JavaStackFrame f : cur.unpark().stack().metadata()) {
+			switch (f.method().clazz().name()) {
+			case "java/util/concurrent/locks/ReentrantReadWriteLock$ReadLock":
+				return true;
+			case "java/util/concurrent/locks/ReentrantReadWriteLock$WriteLock":
+				return false;
+			}
+		}
+		Sanity.warn("unknown lock type, maybe spurious wakeup");
+		return false;
+	}
+
+	@Override
+	JavaThread sharedThread() {
+		return JavaThread.READERS;
+	}
+
+	@Override
+	JavaStack sharedSite() {
+		return JavaStack.READERS;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleJsonSerializer.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleJsonSerializer.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleJsonSerializer.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import sun.evtracing.parser.SequenceOrderedEvent;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+public class ParkEventTupleJsonSerializer {
+	private final PrintStream ps;
+	private final ParkEventTuple tuple;
+	private final boolean seqAsTimestamp;
+	private long flowId;
+
+	public static void serialize(String outputFile, ParkEventTuple tuple, boolean seqAsTimestamp) {
+		try {
+			ParkEventTupleJsonSerializer serializer = new ParkEventTupleJsonSerializer(new PrintStream(outputFile), tuple, seqAsTimestamp);
+			serializer.serialize();
+		} catch (FileNotFoundException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	public ParkEventTupleJsonSerializer(PrintStream ps, ParkEventTuple tuple, boolean seqAsTimestamp) {
+		this.ps = ps;
+		this.tuple = tuple;
+		this.seqAsTimestamp = seqAsTimestamp;
+		flowId = 0;
+	}
+
+	private void serialize() {
+		ps.println("[");
+		ps.print("{\"name\":\"process_name\",\"ph\":\"M\",\"pid\":1,\"args\":{\"name\":\"java\"}}");
+		printTuple(tuple);
+		for (ParkEventTuple t : tuple.overlapping()) {
+			printTuple(t);
+		}
+		ps.println("\n]");
+	}
+
+	private void printTuple(ParkEventTuple tuple) {
+		printThread(tuple.begin().thread().metadata());
+		if (tuple.unpark() != null) {
+			printThread(tuple.unpark().thread().metadata());
+		}
+
+		String name = tuple.begin().clazz().metadata().prettyName(true);
+		long startTime = timeFrom(tuple.begin());
+		long thread = tuple.begin().thread().identifier();
+		String isAbsolute = String.valueOf(tuple.begin().isAbsolute());
+		long parkTime = tuple.begin().parkTime();
+		String objectHash = Integer.toHexString(tuple.begin().blockerObject());
+		JavaStack jstack = tuple.begin().stack().metadata();
+		String stack;
+		if (jstack.isSet()) {
+			stack = StreamSupport.stream(jstack.spliterator(), false)
+						.map(frame -> "\"" + (frame.method().isSet() ? frame.method().prettyDescriptor(true) : "(unknown)") + "\"")
+						.collect(Collectors.joining(","));
+		} else {
+			stack = "";
+		}
+		int nestingLevel = tuple.begin().nestingLevel();
+		long endTime = timeFrom(tuple.end());
+		long duration = endTime - startTime;
+		long beginSeq = tuple.begin().sequenceNumber();
+		long unparkSeq = tuple.end().unparkSequenceNumber();
+		long endSeq = tuple.end().sequenceNumber();
+		String parkReturnCode = tuple.end().parkReturnCode().name();
+		ps.printf(",\n{\"name\":\"%s\",\"cat\":\"park\",\"ph\":\"X\",\"ts\":%d,\"dur\":%d,\"pid\":1,\"tid\":%d,\"args\":{\"Arg isAbsolute\":%s,\"Arg time\":%d,\"Identity Hash Code\":\"%s\",\"Stack\":[%s],\"Nesting Level\":%d,\"Seq Begin\":%d,\"Seq Unpark\":%d,\"Seq End\":%d,\"Return Code\":\"%s\"}}",
+				name, startTime, duration, thread, isAbsolute, parkTime, objectHash, stack, nestingLevel, beginSeq, unparkSeq, endSeq, parkReturnCode);
+
+		if (tuple.unpark() != null) {
+			flowId++;
+			long unparkTime = timeFrom(tuple.unpark());
+			ps.printf(",\n{\"name\":\"unpark\",\"cat\":\"park\",\"ph\":\"%s\",\"ts\":%d,\"id\":%d,\"pid\":1,\"tid\":%d}", unparkTime < endTime ? "s" : "f", unparkTime, flowId, tuple.unpark().thread().identifier());
+			ps.printf(",\n{\"name\":\"unparked\",\"cat\":\"park\",\"ph\":\"%s\",\"ts\":%d,\"id\":%d,\"pid\":1,\"tid\":%d}", unparkTime < endTime ? "f" : "s", endTime, flowId, tuple.unpark().unparkedThread().identifier());
+		}
+	}
+
+	private void printThread(JavaThread thread) {
+		ps.printf(",\n{\"name\":\"thread_name\",\"ph\":\"M\",\"pid\":1,\"tid\":%d,\"args\":{\"name\":\"%s\"}}", thread.threadId(), thread.name());
+	}
+
+	private long timeFrom(SequenceOrderedEvent e) {
+		if (seqAsTimestamp) {
+			return e.sequenceNumber();
+		} else {
+			return e.timestamp() / 1000;
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleUnparkComparator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleUnparkComparator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ParkEventTupleUnparkComparator.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.Comparator;
+
+import sun.evtracing.processing.statistics.metadata.ParkEventTuple;
+
+class ParkEventTupleUnparkComparator implements Comparator<ParkEventTuple> {
+	@Override
+	public int compare(ParkEventTuple o1, ParkEventTuple o2) {
+		if (o1.unpark() == o2.unpark()) {
+			return 0;
+		}
+		if (o1.unpark() == null) {
+			return -1;
+		}
+		if (o2.unpark() == null) {
+			return 1;
+		}
+		return Long.compare(o1.unpark().sequenceNumber(), o2.unpark().sequenceNumber());
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/Statistics.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/Statistics.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/Statistics.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.Map;
+
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.Aggregator;
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+
+public interface Statistics {
+
+	Map<JavaThread, Aggregator> contendingThreads();
+
+	Map<JavaClassStack, Aggregator> blockerClasses();
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/StatisticsPrinter.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/StatisticsPrinter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/StatisticsPrinter.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaStackFrame;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.Aggregator;
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+
+public class StatisticsPrinter {
+
+	private static final int REPEAT_HEADING_EVERY_N_LINES = 50;
+
+	private final Statistics statistics;
+	private final PrintStream out;
+
+	public StatisticsPrinter(Statistics stats, OutputStream out) {
+		this.statistics = stats;
+		this.out = new PrintStream(out);
+	}
+
+	public void print() {
+		printContendingThreadStatistics();
+		printBlockerClassesStatistics();
+	}
+
+	private void printContendingThreadStatistics() {
+		int i = 0;
+		for (Entry<JavaThread, Aggregator> e : statistics.contendingThreads().entrySet()) {
+			JavaThread t = e.getKey();
+			NumberStatistic s = e.getValue().statistic();
+			if (i++ % REPEAT_HEADING_EVERY_N_LINES == 0) {
+				out.printf("===== THREADS (overall contention) =============================================%n");
+				out.printf("   tid threadname           | runtime  | contTotal   cont%%   contAvg  contMax |%n");
+				out.printf("--------------------------------------------------------------------------------%n");
+			}
+			out.printf("%6d %-20s | %8.1f | %9s  %6s  %8s  %7s%n", t.threadId(), limitLength(nullToString(t.name()), 20),
+					toMs(t.totalRuntime()),
+					formatOrDashIfZero("%9.1f", toMs(s.getSum())), formatOrDashIfZero("%5.1f%%", asPct(s.getSum(), t.totalRuntime())), formatOrDashIfNaN("%8.2f", toMs(s.getAverage())), formatOrDashIfZero("%7.1f", toMs(s.getMax())));
+		}
+		out.println();
+	}
+
+	private void printBlockerHeading(int i) {
+		if (i % REPEAT_HEADING_EVERY_N_LINES == 0) {
+			out.printf("===== BLOCKER CLASSES, CONTENDING SITE, OWNER SITE ==========================================================================%n");
+			out.printf(" blocker class / contending site / owner site                                        |  contTotal   cont%%   contAvg  contMax%n");
+			out.printf("-----------------------------------------------------------------------------------------------------------------------------%n");
+		}
+	}
+
+	private void printBlockerClassesStatistics() {
+		NumberStatistic total = new NumberStatistic();
+		for (Aggregator agg : statistics.blockerClasses().values()) {
+			total = NumberStatistic.merge(total, agg.statistic());
+		}
+
+		int i = 0;
+		printBlockerHeading(i++);
+		out.printf("%-84s | %10.1f  %6s  %8.2f  %7.1f%n", "<total>",
+				toMs(total.getSum()), formatOrDashIfZero("%5.1f%%", 100), toMs(total.getAverage()), toMs(total.getMax()));
+
+		for (Entry<JavaClassStack, Aggregator> e0 : sortByTotalDescending(statistics.blockerClasses().entrySet())) {
+			JavaClassStack k0 = e0.getKey();
+			NumberStatistic s0 = e0.getValue().statistic();
+
+			printBlockerHeading(i++);
+			String classes = Arrays.stream(k0.classes()).map(c -> c.prettyName(true)).collect(Collectors.joining(", "));
+			out.printf("  %-82s | %10.1f  %6s  %8.2f  %7.1f%n", limitLength(classes, 82),
+					toMs(s0.getSum()), formatOrDashIfZero("%5.1f%%", asPct(s0.getSum(), total.getSum())), toMs(s0.getAverage()), toMs(s0.getMax()));
+
+			Map<?, Aggregator> contendingSites = e0.getValue().children();
+			for (Entry<?, Aggregator> e1 : sortByTotalDescending(contendingSites.entrySet())) {
+				JavaStack k1 = (JavaStack) e1.getKey();
+				NumberStatistic s1 = e1.getValue().statistic();
+
+				printBlockerHeading(i++);
+				out.printf("    %-80s | %10.1f  %6s  %8.2f  %7.1f%n", stackAsString(k1, 80),
+						toMs(s1.getSum()), formatOrDashIfZero("%5.1f%%", asPct(s1.getSum(), total.getSum())), toMs(s1.getAverage()), toMs(s1.getMax()));
+
+				Map<?, Aggregator> ownerSites = e1.getValue().children();
+				for (Entry<?, Aggregator> e2 : sortByTotalDescending(ownerSites.entrySet())) {
+					JavaStack k2 = (JavaStack) e2.getKey();
+					NumberStatistic s2 = e2.getValue().statistic();
+
+					printBlockerHeading(i++);
+					out.printf("      %-78s | %10.1f  %6s  %8.2f  %7.1f%n", stackAsString(k2, 78),
+							toMs(s2.getSum()), formatOrDashIfZero("%5.1f%%", asPct(s2.getSum(), total.getSum())), toMs(s2.getAverage()), toMs(s2.getMax()));
+				}
+			}
+		}
+		out.println();
+	}
+
+	private<T> Iterable<Entry<T, Aggregator>> sortByTotalDescending(Set<Entry<T, Aggregator>> set) {
+		Comparator<? super Entry<T, Aggregator>> cmp = ((x, y) -> Long.signum(y.getValue().statistic().getSum() - x.getValue().statistic().getSum()));
+		return set.stream().sorted(cmp)::iterator;
+	}
+
+	private String stackAsString(JavaStack stack, int maxLength) {
+		if (stack.isUnknown()) {
+			return ("<unknown>");
+		}
+		if (!stack.isSet()) {
+			return ("<unset>");
+		}
+
+		StringBuilder builder = new StringBuilder();
+		int count = 0;
+		for (JavaStackFrame frame : stack) {
+			String descriptor = frame.method().prettyDescriptor(true);
+			if (builder.length() != 0) {
+				builder.append(", ");
+				if (builder.length() + descriptor.length() > maxLength) {
+					String remaining = String.format("[+%d]", stack.frameCount() - count);
+					if (builder.length() > maxLength - remaining.length()) {
+						builder.setLength(maxLength - remaining.length());
+					}
+					builder.append(remaining);
+					break;
+				}
+			}
+			builder.append(descriptor);
+			count++;
+		}
+		return builder.toString();
+	}
+
+	private double asPct(double value, double total) {
+		return value * 100 / total;
+	}
+
+	private double toMs(double nanoseconds) {
+		return nanoseconds / 1000000.0;
+	}
+
+	private String formatOrDashIfZero(String format, double value) {
+		if (value == 0) {
+			return "-";
+		}
+		return formatOrDashIfNaN(format, value);
+	}
+
+	private String formatOrDashIfNaN(String format, double value) {
+		if (Double.isNaN(value)) {
+			return "-";
+		}
+		return String.format(format, value);
+			
+	}
+
+	private String limitLength(String value, int maxLength) {
+		if (value.length() > maxLength) {
+			return value.substring(0, maxLength - 2) + "..";
+		} else {
+			return value;
+		}
+	}
+
+	private String nullToString(String value) {
+		if (value == null) {
+			return "<null>";
+		}
+		return value;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/ThreadAnalyser.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/ThreadAnalyser.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/ThreadAnalyser.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import sun.evtracing.parser.ThreadExitEvent;
+import sun.evtracing.parser.ThreadStartEvent;
+import sun.evtracing.parser.VMEndEvent;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.JavaImmutableSingleObjectStack;
+
+public class ThreadAnalyser implements ContentionProcessor {
+
+	private static class ThreadLifetime {
+		final long start;
+		long contended;
+
+		public ThreadLifetime(long start) {
+			this.start = start;
+		}
+	}
+
+	private final Map<JavaThread, ThreadLifetime> threads = new HashMap<>();
+
+	private final ContentionProcessor delegate;
+
+	public ThreadAnalyser(ContentionProcessor delegate) {
+		this.delegate = delegate;
+	}
+
+	public void start(ThreadStartEvent event) {
+		assert !threads.containsKey(event.thread().metadata());
+
+		threads.put(event.thread().metadata(), new ThreadLifetime(event.timestamp()));
+	}
+
+	@Override
+	public void submit(Contention c) {
+		if (threads.containsKey(c.contendingThread)) {
+			threads.get(c.contendingThread).contended += c.duration;
+		}
+
+		delegate.submit(c);
+	}
+
+	public void exit(ThreadExitEvent event) {
+		JavaThread thread = event.thread().metadata();
+		accountThread(thread, threads.remove(thread), event.timestamp());
+	}
+
+	private void accountThread(JavaThread thread, ThreadLifetime record, long timestamp) {
+		long uncontended = timestamp - record.start - record.contended;
+		delegate.submit(new Contention(Group.Uncontended, thread, JavaThread.UNCONTENDED, JavaStack.UNCONTENDED, JavaStack.UNCONTENDED, new JavaImmutableSingleObjectStack(JavaObject.UNCONTENDED), record.start, uncontended));
+	}
+
+	public void endVM(VMEndEvent event) {
+		Iterator<Map.Entry<JavaThread, ThreadLifetime>> it = threads.entrySet().iterator();
+		while (it.hasNext()) {
+			Map.Entry<JavaThread, ThreadLifetime> entry = it.next();
+			accountThread(entry.getKey(), entry.getValue(), event.timestamp());
+			it.remove();
+		}
+	}
+
+	@Override
+	public void merge() {
+		delegate.merge();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/TraceEventStatisticsHandler.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/TraceEventStatisticsHandler.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/TraceEventStatisticsHandler.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics;
+
+import java.util.HashMap;
+import java.util.Map;
+import sun.evtracing.parser.GroupEvent;
+import sun.evtracing.parser.MonitorContendedEnterEvent;
+import sun.evtracing.parser.MonitorContendedEnteredEvent;
+import sun.evtracing.parser.MonitorContendedExitedEvent;
+import sun.evtracing.parser.MonitorDeflateEvent;
+import sun.evtracing.parser.MonitorInflateEvent;
+import sun.evtracing.parser.ThreadInterruptEvent;
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+import sun.evtracing.parser.VMEndEvent;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MethodFilter;
+import sun.evtracing.processing.AbstractTraceEventHandler;
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.aggregator.AggregationConfiguration;
+import sun.evtracing.processing.statistics.aggregator.Aggregator;
+import sun.evtracing.processing.statistics.aggregator.BlockerClassAggregator;
+import sun.evtracing.processing.statistics.aggregator.BlockerClassAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContendingSiteAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContendingThreadAggregator;
+import sun.evtracing.processing.statistics.aggregator.ContendingThreadAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.ContentionProcessor;
+import sun.evtracing.processing.statistics.aggregator.LeafAggregatorFactory;
+import sun.evtracing.processing.statistics.aggregator.MultiAggregator;
+import sun.evtracing.processing.statistics.aggregator.NegativeDurationContentionFilter;
+import sun.evtracing.processing.statistics.aggregator.OwnerSiteAggregatorFactory;
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+
+public class TraceEventStatisticsHandler extends AbstractTraceEventHandler {
+
+	private final Map<Long, ParkAnalyser> parkAnalyser = new HashMap<>();
+	private final ParkBlockerAnalyser parkBlockerDispatcher;
+	private final Map<Long, MonitorAnalyser> monitorAnalysers = new HashMap<>();
+	private final ContendingThreadAggregator contendingThreadAggregator;
+	private final BlockerClassAggregator blockerClassAggregator;
+	private final MultiAggregator aggregators = new MultiAggregator();
+	private final ContentionProcessor processor;
+
+	public TraceEventStatisticsHandler() {
+		AggregationConfiguration configuration = new AggregationConfiguration(MethodFilter.NO_FILTER);
+		contendingThreadAggregator = new ContendingThreadAggregatorFactory(new LeafAggregatorFactory(configuration), configuration).create();
+		ContendingSiteAggregatorFactory factories = new ContendingSiteAggregatorFactory(new OwnerSiteAggregatorFactory(new LeafAggregatorFactory(configuration), configuration), configuration);
+		blockerClassAggregator = new BlockerClassAggregatorFactory(factories, configuration).create();
+		aggregators.add(contendingThreadAggregator);
+		aggregators.add(blockerClassAggregator);
+		processor = new NegativeDurationContentionFilter(aggregators);
+		parkBlockerDispatcher = new ParkBlockerDispatcher(processor);
+	}
+
+	private final Statistics result = new Statistics() {
+		@Override
+		public Map<JavaThread, Aggregator> contendingThreads() {
+			return contendingThreadAggregator.children();
+		}
+
+		@Override
+		public Map<JavaClassStack, Aggregator> blockerClasses() {
+			return blockerClassAggregator.children();
+		}
+	};
+
+	public Statistics result() {
+		return result;
+	}
+
+	@Override
+	public void endVM(VMEndEvent event) {
+		processor.merge();
+
+		Sanity.printCollectedWarnings();
+	}
+
+	private ParkAnalyser getOrCreateParkAnalyser(long thread) {
+		return parkAnalyser.computeIfAbsent(thread, t -> new ParkAnalyser(parkBlockerDispatcher));
+	}
+
+	@Override
+	public void threadParkBegin(ThreadParkBeginEvent event) {
+		ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+		pa.begin(event);
+	}
+
+	@Override
+	public void threadParkEnd(ThreadParkEndEvent event) {
+		ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+		pa.end(event);
+	}
+
+	@Override
+	public void threadUnpark(ThreadUnparkEvent event) {
+		ParkAnalyser pa = getOrCreateParkAnalyser(event.unparkedThread().identifier());
+		pa.unpark(event);
+	}
+
+	@Override
+	public void threadInterrupt(ThreadInterruptEvent event) {
+		ParkAnalyser pa = getOrCreateParkAnalyser(event.affectedThread().identifier());
+		pa.interrupt(event);
+	}
+
+	@Override
+	public void group(GroupEvent event) {
+		ParkAnalyser pa = getOrCreateParkAnalyser(event.thread().identifier());
+		pa.group(event);
+	}
+
+	//
+	// Monitors
+	//
+
+	// NOTE: we are guaranteed only that we get events for a particular monitor
+	//       in the correct order. However, events of one monitor can be
+	//       interleaved with events of other monitors, and events of the same
+	//       thread are no longer in the order in which they were written.
+
+	@Override
+	public void monitorInflate(MonitorInflateEvent event) {
+		assert !monitorAnalysers.containsKey(event.monitor());
+		MonitorAnalyser ma = MonitorAnalyser.forInflate(event, processor);
+		monitorAnalysers.put(event.monitor(), ma);
+	}
+
+	@Override
+	public void monitorContendedEnter(MonitorContendedEnterEvent event) {
+		MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+		ma.enter(event);
+	}
+
+	@Override
+	public void monitorContendedEntered(MonitorContendedEnteredEvent event) {
+		MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+		ma.entered(event);
+	}
+
+	@Override
+	public void monitorContendedExited(MonitorContendedExitedEvent event) {
+		MonitorAnalyser ma = monitorAnalysers.get(event.monitor());
+		ma.exited(event);
+	}
+
+	@Override
+	public void monitorDeflate(MonitorDeflateEvent event) {
+		MonitorAnalyser ma = monitorAnalysers.remove(event.monitor());
+		ma.deflate(event);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregationConfiguration.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregationConfiguration.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregationConfiguration.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.MethodFilter;
+
+public class AggregationConfiguration {
+
+	private final MethodFilter filter;
+	
+	private final boolean absoluteDurationFilterEnabled;
+	
+	private final boolean relativeDurationFilterEnabled;
+	
+	private final long absoluteDurationFilterThreshold;
+	
+	private final double relativeDurationFilterThreshold;
+	
+	public AggregationConfiguration(MethodFilter filter) {
+		this(filter, false, false, 0, 0);
+	}
+
+	public AggregationConfiguration(MethodFilter filter, boolean absoluteDurationFilterEnabled, boolean relativeDurationFilterEnabled, long absoluteDurationFilterThreshold, double relativeDurationFilterThreshold) {
+		this.filter = filter;
+		this.absoluteDurationFilterEnabled = absoluteDurationFilterEnabled;
+		this.relativeDurationFilterEnabled = relativeDurationFilterEnabled;
+		this.absoluteDurationFilterThreshold = absoluteDurationFilterThreshold;
+		this.relativeDurationFilterThreshold = relativeDurationFilterThreshold;
+	}
+
+	public MethodFilter filter() {
+		return filter;
+	}
+
+	public boolean isAbsoluteDurationFilterEnabled() {
+		return absoluteDurationFilterEnabled;
+	}
+	
+	public boolean isRelativeDurationFilterEnabled() {
+		return relativeDurationFilterEnabled;
+	}
+	
+	public long absoluteDurationFilterThreshold() {
+		return absoluteDurationFilterThreshold;
+	}
+
+	public double relativeDurationFilterThreshold() {
+		return relativeDurationFilterThreshold;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/Aggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/Aggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/Aggregator.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Map;
+
+import sun.evtracing.processing.statistics.NumberStatistic;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public abstract class Aggregator implements ContentionProcessor {
+	private final AggregatorFactory<? extends Aggregator> factory;
+	private final NumberStatistic statistic;
+	
+	public Aggregator(AggregatorFactory<? extends Aggregator> factory) {
+		this.factory = factory;
+		statistic = new NumberStatistic();
+	}
+
+	public Aggregator(Aggregator x, Aggregator y) {
+		assert x.factory == y.factory;
+		factory = x.factory;
+
+		statistic = NumberStatistic.merge(x.statistic, y.statistic);
+	}
+
+	public AggregatorFactory<? extends Aggregator> factory() {
+		return factory;
+	}
+
+	public NumberStatistic statistic() {
+		return statistic;
+	}
+
+	@Override
+	public void submit(Contention c) {
+		statistic.add(c.duration);
+		submitToChildren(c);
+	}
+
+	public abstract void submitToChildren(Contention c);
+
+	@Override
+	public abstract void merge();
+
+	public abstract Map<?, Aggregator> children();
+	
+	public abstract <R> R accept(AggregatorVisitor<R> v, Object element);
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public abstract class AggregatorFactory<T extends Aggregator> {
+	private final AggregatorFactory<? extends Aggregator> nextFactory;
+	private final AggregationConfiguration configuration;
+
+	public AggregatorFactory(AggregationConfiguration configuration) {
+		this(null, configuration);
+	}
+
+	public AggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		this.nextFactory = nextFactory;
+		this.configuration = configuration;
+	}
+
+	public abstract T create();
+
+	public abstract T merge(T x, T y);
+
+	public AggregationConfiguration configuration() {
+		return configuration;
+	}
+
+	T mergeChecked(Aggregator x, Aggregator y) {
+		if (x.factory() != this) {
+			throw new IllegalArgumentException("aggregator x not an instance of factory");
+		}
+		if (y.factory() != this) {
+			throw new IllegalArgumentException("aggregator y not an instance of factory");
+		}
+		@SuppressWarnings("unchecked")
+		T xt = (T) x;
+		@SuppressWarnings("unchecked")
+		T yt = (T) y;
+		return merge(xt, yt);
+	}
+
+	AggregatorFactory<? extends Aggregator> nextFactory() {
+		return nextFactory;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorVisitor.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorVisitor.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/AggregatorVisitor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.parser.metadata.MethodFilter;
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+
+public interface AggregatorVisitor<R> {
+	
+	public R visitBlocker(JavaObjectStack blocker);
+	public R visitBlockerClass(JavaClassStack blockerClass);
+	public R visitContendingMethod(JavaMethod method);
+	public R visitOwnerMethod(JavaMethod method);
+	public R visitContendingSite(JavaStack site, MethodFilter filter);
+	public R visitOwnerSite(JavaStack site, MethodFilter filter);
+	public R visitContendingThread(JavaThread thread);
+	public R visitOwnerThread(JavaThread thread);
+	public R visitGroup(Group group);
+	
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class BlockerAggregator extends ComplexReflexiveAggregator<JavaObjectStack> {
+	BlockerAggregator(BlockerAggregatorFactory factory) {
+		super(factory);
+	}
+
+	BlockerAggregator(BlockerAggregator x, BlockerAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected JavaObjectStack createDurationFilteredChild() {
+		return JavaObjectStack.HIDDEN;
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.blocker, c);
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitBlocker((JavaObjectStack) element);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class BlockerAggregatorFactory extends AggregatorFactory<BlockerAggregator> {
+	public BlockerAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public BlockerAggregator create() {
+		return new BlockerAggregator(this);
+	}
+
+	@Override
+	public BlockerAggregator merge(BlockerAggregator x, BlockerAggregator y) {
+		return new BlockerAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.statistics.metadata.JavaClassStack;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class BlockerClassAggregator extends ComplexReflexiveAggregator<JavaClassStack> {
+	BlockerClassAggregator(BlockerClassAggregatorFactory factory) {
+		super(factory);
+	}
+
+	BlockerClassAggregator(BlockerClassAggregator x, BlockerClassAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected JavaClassStack createDurationFilteredChild() {
+		return JavaClassStack.HIDDEN;
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.blocker.getClassStack(), c);
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitBlockerClass((JavaClassStack) element);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/BlockerClassAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class BlockerClassAggregatorFactory extends AggregatorFactory<BlockerClassAggregator> {
+	public BlockerClassAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public BlockerClassAggregator create() {
+		return new BlockerClassAggregator(this);
+	}
+
+	@Override
+	public BlockerClassAggregator merge(BlockerClassAggregator x, BlockerClassAggregator y) {
+		return new BlockerClassAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexAggregator.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public abstract class ComplexAggregator<I, O> extends Aggregator {
+	protected Map<I, Aggregator> children = new HashMap<>();
+
+	ComplexAggregator(AggregatorFactory<? extends ComplexAggregator<I, O>> factory) {
+		super(factory);
+	}
+
+	ComplexAggregator(ComplexAggregator<I, O> x, ComplexAggregator<I, O> y) {
+		super(x, y);
+
+		children.putAll(x.children);
+		for (Entry<I, Aggregator> e : y.children.entrySet()) {
+			children.merge(e.getKey(), e.getValue(), (u, v) -> {
+				u.merge();
+				v.merge();
+				return u.factory().mergeChecked(u, v);
+			});
+		}
+	}
+
+	@Override
+	public abstract Map<O, Aggregator> children();
+
+	Aggregator createChild() {
+		return factory().nextFactory().create();
+	}
+
+	void submitToChildren(I key, Contention c) {
+		Aggregator child = children.computeIfAbsent(key, x -> createChild());
+		child.submit(c);
+	}
+
+	@Override
+	public void merge() {
+		filterDuration();
+		for (Aggregator child : children.values()) {
+			child.merge();
+		}
+	}
+	
+	private void filterDuration() {
+		AggregationConfiguration config = factory().configuration();
+		if (config.isAbsoluteDurationFilterEnabled() || config.isRelativeDurationFilterEnabled()) {
+			long threshold;
+			if (config.isAbsoluteDurationFilterEnabled() && config.isRelativeDurationFilterEnabled()) {
+				threshold = Math.max((long) (statistic().getSum() * config.relativeDurationFilterThreshold()), config.absoluteDurationFilterThreshold());
+			} else if (config.isAbsoluteDurationFilterEnabled()) {
+				threshold = config.absoluteDurationFilterThreshold();
+			} else {
+				threshold = (long) (statistic().getSum() * config.relativeDurationFilterThreshold());
+			}
+
+			Map<I, Aggregator> affected = new HashMap<>();
+			Iterator<Entry<I, Aggregator>> it = children.entrySet().iterator();
+			while (it.hasNext()) {
+				Map.Entry<I, Aggregator> entry = it.next();
+				if (entry.getValue().statistic().getSum() < threshold) {
+					affected.put(entry.getKey(), entry.getValue());
+					it.remove();
+				}
+			}
+
+			if (affected.size() > 1) {
+				Aggregator merged = affected.values().stream().reduce((x, y) -> x.factory().mergeChecked(x, y)).get();
+				children.put(createDurationFilteredChild(), merged);
+			} else {
+				// don't filter if only one child would be affected
+				children.putAll(affected);
+			}
+		}
+	}
+	
+	protected abstract I createDurationFilteredChild();
+
+	void mergeChildren(Comparator<? super I> cmp) {
+		ArrayList<I> sorted = new ArrayList<>(children.keySet());
+		sorted.sort(cmp);
+
+		Map<I, Aggregator> merged = new HashMap<>();
+		I current = null;
+		Aggregator currentChild = null;
+		for (I next : sorted) {
+			Aggregator nextChild = children.get(next);
+			if (current != null) {
+				if (cmp.compare(current, next) == 0) {
+					currentChild = currentChild.factory().mergeChecked(currentChild, nextChild);
+				} else {
+					merged.put(current, currentChild);
+					current = next;
+					currentChild = nextChild;
+				}
+			} else {
+				current = next;
+				currentChild = nextChild;
+			}
+		}
+		if (current != null) {
+			merged.put(current, currentChild);
+		}
+		children = merged;
+		filterDuration();
+		for (Aggregator child : children.values()) {
+			child.merge();
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexReflexiveAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexReflexiveAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ComplexReflexiveAggregator.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Collections;
+import java.util.Map;
+
+public abstract class ComplexReflexiveAggregator<T> extends ComplexAggregator<T, T> {
+
+	ComplexReflexiveAggregator(AggregatorFactory<? extends ComplexAggregator<T, T>> factory) {
+		super(factory);
+	}
+
+	public ComplexReflexiveAggregator(ComplexAggregator<T, T> x, ComplexAggregator<T, T> y) {
+		super(x, y);
+	}
+
+	@Override
+	public Map<T, Aggregator> children() {
+		return Collections.unmodifiableMap(children);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class ContendingMethodAggregator extends MethodAggregator {
+
+	ContendingMethodAggregator(AggregatorFactory<? extends ContendingMethodAggregator> factory) {
+		super(factory);
+	}
+	
+	ContendingMethodAggregator(ContendingMethodAggregator x, ContendingMethodAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		super.submitToChildren(c.contendingSite, c);
+	}
+	
+	
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitContendingMethod((JavaMethod) element);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingMethodAggregatorFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class ContendingMethodAggregatorFactory extends AggregatorFactory<ContendingMethodAggregator> {
+	
+	public ContendingMethodAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public ContendingMethodAggregator create() {
+		return new ContendingMethodAggregator(this);
+	}
+
+	@Override
+	public ContendingMethodAggregator merge(ContendingMethodAggregator x, ContendingMethodAggregator y) {
+		return new ContendingMethodAggregator(x, y);
+	}
+	
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class ContendingSiteAggregator extends SiteAggregator {
+	ContendingSiteAggregator(ContendingSiteAggregatorFactory factory) {
+		super(factory);
+	}
+
+	ContendingSiteAggregator(ContendingSiteAggregator x, ContendingSiteAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.contendingSite, c);
+	}
+	
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitContendingSite((JavaStack) element, factory().configuration().filter());
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingSiteAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class ContendingSiteAggregatorFactory extends AggregatorFactory<ContendingSiteAggregator> {
+	public ContendingSiteAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public ContendingSiteAggregator create() {
+		return new ContendingSiteAggregator(this);
+	}
+
+	@Override
+	public ContendingSiteAggregator merge(ContendingSiteAggregator x, ContendingSiteAggregator y) {
+		return new ContendingSiteAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class ContendingThreadAggregator extends ComplexReflexiveAggregator<JavaThread> {
+	ContendingThreadAggregator(ContendingThreadAggregatorFactory factory) {
+		super(factory);
+	}
+
+	ContendingThreadAggregator(ContendingThreadAggregator x, ContendingThreadAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected JavaThread createDurationFilteredChild() {
+		return JavaThread.HIDDEN;
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.contendingThread, c);
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitContendingThread((JavaThread) element);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContendingThreadAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class ContendingThreadAggregatorFactory extends AggregatorFactory<ContendingThreadAggregator> {
+	public ContendingThreadAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public ContendingThreadAggregator create() {
+		return new ContendingThreadAggregator(this);
+	}
+
+	@Override
+	public ContendingThreadAggregator merge(ContendingThreadAggregator x, ContendingThreadAggregator y) {
+		return new ContendingThreadAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionCacher.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionCacher.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionCacher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class ContentionCacher implements ContentionProcessor {
+
+	public static interface ProgressCallback {
+		void progressChanged(int progress, int outOf);
+	}
+
+	public static void replay(List<Contention> contentions, ContentionProcessor processor, ProgressCallback callback) {
+		int i = 0;
+		for (Contention c : contentions) {
+			processor.submit(c);
+
+			i++;
+			callback.progressChanged(i, contentions.size());
+		}
+		processor.merge();
+	}
+
+	private final Map<CumulatedContention, CumulatedContention> contentions = new HashMap<>();
+
+	private final ContentionProcessor delegate;
+
+	private boolean cachingCompleted = false;
+
+	public ContentionCacher(ContentionProcessor delegate) {
+		this.delegate = delegate;
+	}
+
+	@Override
+	public void submit(Contention c) {
+		assert !cachingCompleted;
+
+		CumulatedContention cc = new CumulatedContention(c);
+		CumulatedContention existingOrNew = contentions.computeIfAbsent(cc, key -> key);
+		existingOrNew.cumulate(c.duration);
+
+		delegate.submit(c);
+	}
+
+	@Override
+	public void merge() {
+		assert !cachingCompleted;
+
+		delegate.merge();
+	}
+
+	public List<Contention> complete() {
+		assert !cachingCompleted;
+
+		cachingCompleted = true;
+		List<Contention> list = contentions.keySet().stream().map(CumulatedContention::createContention).collect(Collectors.toList());
+		return Collections.unmodifiableList(list);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionProcessor.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionProcessor.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/ContentionProcessor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public interface ContentionProcessor {
+	void submit(Contention c);
+
+	void merge();
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/CumulatedContention.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/CumulatedContention.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/CumulatedContention.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Objects;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.JavaObject;
+import sun.evtracing.processing.statistics.metadata.JavaObjectStack;
+
+public class CumulatedContention {
+
+	private final Contention contention;
+	
+	private long cumulatedDuration = 0;
+	
+	public CumulatedContention(Contention contention) {
+		this.contention = contention;
+	}
+	
+	public void cumulate(long duration) {
+		cumulatedDuration += duration;
+	}
+	
+	public Contention createContention() {
+		return new Contention(contention.group, contention.contendingThread, contention.ownerThread, contention.contendingSite, contention.ownerSite, contention.blocker, contention.startTime, cumulatedDuration);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (!(obj instanceof CumulatedContention)) {
+			return false;
+		}
+		CumulatedContention c = (CumulatedContention) obj;
+		return 	this.contention.contendingSite == c.contention.contendingSite &&
+				this.contention.contendingThread == c.contention.contendingThread &&
+				this.contention.group == c.contention.group &&
+				this.contention.ownerSite == c.contention.ownerSite &&
+				this.contention.ownerThread == c.contention.ownerThread &&
+				Objects.equals(this.contention.blocker, c.contention.blocker);
+	}
+	
+	@Override
+	public int hashCode() {
+		int hash = 5;
+		hash = 31 * hash + System.identityHashCode(contention.contendingSite);
+		hash = 31 * hash + System.identityHashCode(contention.contendingThread);
+		hash = 31 * hash + System.identityHashCode(contention.group);
+		hash = 31 * hash + System.identityHashCode(contention.ownerSite);
+		hash = 31 * hash + System.identityHashCode(contention.ownerThread);
+		hash = 31 * hash + blockerHashCode(contention.blocker);
+		return hash;
+	}
+	
+	private int blockerHashCode(JavaObjectStack o) {
+		int hash = 5;
+		for (JavaObject jo : o.objects()) {
+			hash = 31 * hash + jo.identityHash();
+			hash = 31 * hash + System.identityHashCode(jo.clazz());
+		}
+		return hash;
+	}
+	
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.statistics.metadata.Group;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class GroupAggregator extends ComplexReflexiveAggregator<Group> {
+	GroupAggregator(GroupAggregatorFactory factory) {
+		super(factory);
+	}
+
+	GroupAggregator(GroupAggregator x, GroupAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected Group createDurationFilteredChild() {
+		return Group.Hidden;
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.group, c);
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitGroup((Group) element);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class GroupAggregatorFactory extends AggregatorFactory<GroupAggregator> {
+	public GroupAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public GroupAggregator create() {
+		return new GroupAggregator(this);
+	}
+
+	@Override
+	public GroupAggregator merge(GroupAggregator x, GroupAggregator y) {
+		return new GroupAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupContentionFilter.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupContentionFilter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/GroupContentionFilter.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.EnumSet;
+import sun.evtracing.processing.statistics.metadata.Contention;
+import sun.evtracing.processing.statistics.metadata.Group;
+
+public class GroupContentionFilter implements ContentionProcessor {
+
+	private final ContentionProcessor delegate;
+
+	private final EnumSet<Group> allowedGroups;
+
+	private long unaccountedContentionTime = 0;
+
+	public GroupContentionFilter(ContentionProcessor delegate, EnumSet<Group> allowedGroups) {
+		this.delegate = delegate;
+		this.allowedGroups = allowedGroups;
+	}
+
+	@Override
+	public void submit(Contention c) {
+		if (allowedGroups.contains(c.group)) {
+			delegate.submit(c);
+		} else {
+			if (c.group != Group.Uncontended) {
+				unaccountedContentionTime += c.duration;
+			}
+		}
+	}
+
+	@Override
+	public void merge() {
+		delegate.merge();
+	}
+
+	public long unaccountedContentionTime() {
+		return unaccountedContentionTime;
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregator.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Collections;
+import java.util.Map;
+
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class LeafAggregator extends Aggregator {
+	LeafAggregator(LeafAggregatorFactory factory) {
+		super(factory);
+	}
+
+	LeafAggregator(LeafAggregator x, LeafAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		// nothing to do
+	}
+
+	@Override
+	public void merge() {
+		// nothing to do
+	}
+
+	@Override
+	public Map<?, Aggregator> children() {
+		return Collections.emptyMap();
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		throw new UnsupportedOperationException("leaf aggregators do not have children");
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/LeafAggregatorFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class LeafAggregatorFactory extends AggregatorFactory<LeafAggregator> {
+
+	public LeafAggregatorFactory(AggregationConfiguration configuration) {
+		super(configuration);
+	}
+
+	@Override
+	public LeafAggregator create() {
+		return new LeafAggregator(this);
+	}
+
+	@Override
+	public LeafAggregator merge(LeafAggregator x, LeafAggregator y) {
+		return new LeafAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MethodAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MethodAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MethodAggregator.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.TreeMap;
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.MethodFilter;
+import sun.evtracing.parser.metadata.JavaStackDeepComparator;
+
+public abstract class MethodAggregator extends ComplexAggregator<JavaStack, JavaMethod> {
+
+	MethodAggregator(AggregatorFactory<? extends MethodAggregator> factory) {
+		super(factory);
+	}
+
+	MethodAggregator(MethodAggregator x, MethodAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	public Map<JavaMethod, Aggregator> children() {
+		// use custom comparator to avoid equals() in JavaMethod; since the
+		// stack has already been merged, just add every method to the map
+		final Comparator<JavaMethod> cmp = (JavaMethod m1, JavaMethod m2) -> 1;
+		Map<JavaMethod, Aggregator> methods = new TreeMap<>(cmp);
+		children.forEach((stack, agg) -> {
+			JavaMethod method;
+			if (!stack.isSet()) {
+				method = JavaMethod.MISSING;
+			} else if (JavaStack.UNKNOWN.equals(stack)) {
+				method = JavaMethod.UNKNOWN;
+			} else if (JavaStack.UNCONTENDED.equals(stack)) {
+				method = JavaMethod.UNCONTENDED;
+			} else if (JavaStack.READERS.equals(stack)) {
+				method = JavaMethod.READERS;
+			} else if (JavaStack.HIDDEN.equals(stack)) {
+				method = JavaMethod.HIDDEN;
+			} else {
+				MethodFilter filter = factory().configuration().filter();
+				method = filter.getFirstUnmatched(stack);
+			}
+			methods.put(method, agg);
+		});
+		return Collections.unmodifiableMap(methods);
+	}
+
+	@Override
+	protected JavaStack createDurationFilteredChild() {
+		return JavaStack.HIDDEN;
+	}
+
+	@Override
+	public void merge() {
+		MethodFilter filter = factory().configuration().filter();
+		mergeChildren(JavaStackDeepComparator.forTopMethodOnly(filter));
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MultiAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MultiAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/MultiAggregator.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class MultiAggregator implements ContentionProcessor {
+	private final List<Aggregator> aggregators;
+
+	public MultiAggregator() {
+		aggregators = new ArrayList<>();
+	}
+
+	public void add(Aggregator a) {
+		aggregators.add(a);
+	}
+
+	public void remove(Aggregator a) {
+		aggregators.remove(a);
+	}
+
+	@Override
+	public void submit(Contention c) {
+		for (ContentionProcessor a : aggregators) {
+			a.submit(c);
+		}
+	}
+
+	@Override
+	public void merge() {
+		for (ContentionProcessor a : aggregators) {
+			a.merge();
+		}
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/NegativeDurationContentionFilter.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/NegativeDurationContentionFilter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/NegativeDurationContentionFilter.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.Sanity;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class NegativeDurationContentionFilter implements ContentionProcessor {
+
+    private final ContentionProcessor delegate;
+
+    public NegativeDurationContentionFilter(ContentionProcessor delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public void submit(Contention c) {
+        if (c.duration >= 0) {
+            delegate.submit(c);
+        } else {
+            // The participating threads typically execute on different CPUs. The
+            // clocks of different CPUs are always slightly out of sync, which
+            // results in some error. In some cases, this causes small durations to
+            // become negative.
+
+            // TODO: filtering negative durations is ok for computing sums, but for
+            // correct counts and averages, we need to find a way to deal with them.
+
+            if (c.duration < -1000000) {
+                Sanity.warn("dropped contention with negative duration above 1ms: %.3f ms", c.duration / (1000.f * 1000));
+            } else {
+                Sanity.warn("dropped contention with negative duration in sub-millisecond range: %.3f us", c.duration);
+            }
+        }
+    }
+
+    @Override
+    public void merge() {
+        delegate.merge();
+    }
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaMethod;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class OwnerMethodAggregator extends MethodAggregator {
+
+	OwnerMethodAggregator(AggregatorFactory<? extends OwnerMethodAggregator> factory) {
+		super(factory);
+	}
+	
+	OwnerMethodAggregator(OwnerMethodAggregator x, OwnerMethodAggregator y) {
+		super(x, y);
+	}
+	
+	@Override
+	public void submitToChildren(Contention c) {
+		super.submitToChildren(c.ownerSite, c);
+	}
+	
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitOwnerMethod((JavaMethod) element);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerMethodAggregatorFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class OwnerMethodAggregatorFactory extends AggregatorFactory<OwnerMethodAggregator> {
+	
+	public OwnerMethodAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public OwnerMethodAggregator create() {
+		return new OwnerMethodAggregator(this);
+	}
+
+	@Override
+	public OwnerMethodAggregator merge(OwnerMethodAggregator x, OwnerMethodAggregator y) {
+		return new OwnerMethodAggregator(x, y);
+	}
+	
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class OwnerSiteAggregator extends SiteAggregator {
+	OwnerSiteAggregator(OwnerSiteAggregatorFactory factory) {
+		super(factory);
+	}
+
+	OwnerSiteAggregator(OwnerSiteAggregator x, OwnerSiteAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.ownerSite, c);
+	}
+	
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitOwnerSite((JavaStack) element, factory().configuration().filter());
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerSiteAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class OwnerSiteAggregatorFactory extends AggregatorFactory<OwnerSiteAggregator> {
+	public OwnerSiteAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public OwnerSiteAggregator create() {
+		return new OwnerSiteAggregator(this);
+	}
+
+	@Override
+	public OwnerSiteAggregator merge(OwnerSiteAggregator x, OwnerSiteAggregator y) {
+		return new OwnerSiteAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregator.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaThread;
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class OwnerThreadAggregator extends ComplexReflexiveAggregator<JavaThread> {
+	OwnerThreadAggregator(OwnerThreadAggregatorFactory factory) {
+		super(factory);
+	}
+
+	OwnerThreadAggregator(OwnerThreadAggregator x, OwnerThreadAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected JavaThread createDurationFilteredChild() {
+		return JavaThread.HIDDEN;
+	}
+
+	@Override
+	public void submitToChildren(Contention c) {
+		submitToChildren(c.ownerThread, c);
+	}
+
+	@Override
+	public <R> R accept(AggregatorVisitor<R> v, Object element) {
+		return v.visitOwnerThread((JavaThread) element);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregatorFactory.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregatorFactory.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/OwnerThreadAggregatorFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+public class OwnerThreadAggregatorFactory extends AggregatorFactory<OwnerThreadAggregator> {
+	public OwnerThreadAggregatorFactory(AggregatorFactory<? extends Aggregator> nextFactory, AggregationConfiguration configuration) {
+		super(nextFactory, configuration);
+	}
+
+	@Override
+	public OwnerThreadAggregator create() {
+		return new OwnerThreadAggregator(this);
+	}
+
+	@Override
+	public OwnerThreadAggregator merge(OwnerThreadAggregator x, OwnerThreadAggregator y) {
+		return new OwnerThreadAggregator(x, y);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/SiteAggregator.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/SiteAggregator.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/SiteAggregator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaStackDeepComparator;
+
+public abstract class SiteAggregator extends ComplexReflexiveAggregator<JavaStack> {
+	public SiteAggregator(AggregatorFactory<? extends SiteAggregator> factory) {
+		super(factory);
+	}
+
+	public SiteAggregator(SiteAggregator x, SiteAggregator y) {
+		super(x, y);
+	}
+
+	@Override
+	protected JavaStack createDurationFilteredChild() {
+		return JavaStack.HIDDEN;
+	}
+
+	@Override
+	public void merge() {
+		mergeChildren(JavaStackDeepComparator.INSTANCE);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/TimeSpanContentionFilter.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/TimeSpanContentionFilter.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/aggregator/TimeSpanContentionFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.aggregator;
+
+import sun.evtracing.processing.statistics.metadata.Contention;
+
+public class TimeSpanContentionFilter implements ContentionProcessor {
+
+	public static final long UNRESTRICTED = -1;
+
+	private final ContentionProcessor delegate;
+	private final long begin;
+	private final long end;
+
+	public TimeSpanContentionFilter(ContentionProcessor delegate, long begin, long end) {
+		assert begin == UNRESTRICTED || begin >= 0;
+		assert end == UNRESTRICTED || end >= 0;
+		assert (begin == UNRESTRICTED || end == UNRESTRICTED || begin <= end);
+
+		this.delegate = delegate;
+		this.begin = begin;
+		this.end = end;
+	}
+
+	@Override
+	public void submit(Contention c) {
+		if (end == UNRESTRICTED || c.startTime < end) {
+			long endTime = c.startTime + c.duration;
+			if (begin == UNRESTRICTED || endTime > begin) {
+				// truncate
+				long adjStartTime = c.startTime;
+				if (begin != UNRESTRICTED && c.startTime < begin) {
+					adjStartTime = begin;
+				}
+				long adjEndTime = endTime;
+				if (end != UNRESTRICTED && endTime > end) {
+					adjEndTime = end;
+				}
+				if (adjStartTime != c.startTime || adjEndTime != endTime) {
+					c = new Contention(c.group, c.contendingThread, c.ownerThread, c.contendingSite, c.ownerSite, c.blocker, adjStartTime, adjEndTime - adjStartTime);
+				}
+
+				delegate.submit(c);
+			}
+		}
+	}
+
+	@Override
+	public void merge() {
+		delegate.merge();
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Contention.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Contention.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Contention.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import sun.evtracing.parser.metadata.JavaStack;
+import sun.evtracing.parser.metadata.JavaThread;
+
+public class Contention {
+	public final Group group;
+	public final JavaThread contendingThread;
+	public final JavaThread ownerThread;
+	public final JavaStack contendingSite;
+	public final JavaStack ownerSite;
+	public final JavaObjectStack blocker;
+	public final long startTime;
+	public final long duration;
+
+	public Contention(Group group, JavaThread contendingThread, JavaThread ownerThread, JavaStack contendingSite, JavaStack ownerSite, JavaObjectStack blocker, long startTime, long duration) {
+		this.group = group;
+		this.contendingThread = contendingThread;
+		this.ownerThread = ownerThread;
+		this.contendingSite = contendingSite;
+		this.ownerSite = ownerSite;
+		this.blocker = blocker;
+		this.startTime = startTime;
+		this.duration = duration;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Group.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Group.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/Group.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+public enum Group {
+	Monitors("Monitors"),
+	MonitorWaitReentry("Monitor reentry after Object.wait()"),
+	NativeMonitors("Native Monitors"),
+	NativeMonitorsWaitReentry("Native monitor reentry after wait()"),
+	JavaUtilConcurrent("java.util.concurrent"),
+	JavaUtilConcurrentConditionalWaiting("java.util.concurrent conditional waiting"),
+	Uncontended("Uncontended"),
+	Hidden("(hidden)")
+	;
+
+	private final String name;
+
+	private Group(String name) {
+		this.name = name;
+	}
+
+	@Override
+	public String toString() {
+		return name;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaClassStack.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaClassStack.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaClassStack.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import sun.evtracing.parser.metadata.JavaClass;
+
+public class JavaClassStack {
+	
+	public static final JavaClassStack HIDDEN = new JavaClassStack(JavaClass.UNKNOWN) {
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	};
+	
+	private final JavaClass[] classes;
+
+	public JavaClassStack(JavaClass... classes) {
+		this.classes = classes;
+	}
+
+	public JavaClass[] classes() {
+		return classes;
+	}
+
+	@Override
+	public int hashCode() {
+		return Arrays.hashCode(classes);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null || getClass() != obj.getClass())
+			return false;
+
+		JavaClassStack other = (JavaClassStack) obj;
+		return Arrays.equals(classes, other.classes);
+	}
+
+	@Override
+	public String toString() {
+		return Arrays.stream(classes).map(c -> c.toString()).collect(Collectors.joining(", "));
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaImmutableSingleObjectStack.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaImmutableSingleObjectStack.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaImmutableSingleObjectStack.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 - 2016 Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package sun.evtracing.processing.statistics.metadata;
+
+public class JavaImmutableSingleObjectStack extends JavaObjectStack {
+
+	private final JavaObject object;
+	private JavaClassStack cachedClassStack = null;
+
+	public JavaImmutableSingleObjectStack(JavaObject object) {
+		assert (object != null);
+		this.object = object;
+	}
+
+	@Override
+	public JavaObject top() {
+		return object;
+	}
+
+	@Override
+	public JavaObject[] objects() {
+		return new JavaObject[]{ object };
+	}
+
+	@Override
+	public void setObject(int number, JavaObject obj) {
+		throw new UnsupportedOperationException("immutable");
+	}
+
+	@Override
+	public JavaClassStack getClassStack() {
+		if (cachedClassStack == null) {
+			cachedClassStack = new JavaClassStack(object.clazz());
+		}
+		return cachedClassStack;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObject.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObject.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObject.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import sun.evtracing.parser.metadata.JavaClass;
+
+public class JavaObject {
+
+	private static class SpecialJavaObject extends JavaObject {
+		static final int IDENTITY_HASH = 0;
+		public SpecialJavaObject(JavaClass clazz) {
+			super(IDENTITY_HASH, clazz);
+		}
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	};
+	public static final JavaObject UNKNOWN = new SpecialJavaObject(JavaClass.UNKNOWN);
+	public static final JavaObject UNCONTENDED = new SpecialJavaObject(JavaClass.UNCONTENDED);
+
+	public static JavaObject get(int object, JavaClass clazz) {
+		if (object == SpecialJavaObject.IDENTITY_HASH) {
+			if (clazz == JavaClass.UNKNOWN) {
+				return JavaObject.UNKNOWN;
+			}
+			if (clazz == JavaClass.UNCONTENDED) {
+				return JavaObject.UNCONTENDED;
+			}
+		}
+		return new JavaObject(object, clazz);
+	}
+
+	private final int object;
+	private final JavaClass clazz;
+
+	private JavaObject(int object, JavaClass clazz) {
+		assert clazz != null;
+		this.object = object;
+		this.clazz = clazz;
+	}
+
+	public int identityHash() {
+		return object;
+	}
+
+	public JavaClass clazz() {
+		return clazz;
+	}
+
+	@Override
+	public int hashCode() {
+		return object * 31 + clazz.hashCode();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (obj instanceof JavaObject) {
+			JavaObject other = (JavaObject) obj;
+			return (object == other.object && clazz.equals(other.clazz));
+		}
+		return false;
+	}
+
+	@Override
+	public String toString() {
+		return clazz.prettyName(true) + " @" + Integer.toHexString(object);
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectArrayStack.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectArrayStack.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectArrayStack.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import java.util.Arrays;
+import sun.evtracing.parser.metadata.JavaClass;
+
+public class JavaObjectArrayStack extends JavaObjectStack {
+
+	private final JavaObject[] objects;
+
+	public JavaObjectArrayStack(JavaObject... objects) {
+		this.objects = objects;
+	}
+
+	public JavaObjectArrayStack(int size) {
+		this.objects = new JavaObject[size];
+	}
+
+	@Override
+	public JavaObject top() {
+		JavaObject top = objects[objects.length - 1];
+		assert top != null;
+		return top;
+	}
+
+	@Override
+	public JavaObject[] objects() {
+		assert Arrays.stream(objects).allMatch(o -> o != null);
+		return objects;
+	}
+
+	@Override
+	public void setObject(int number, JavaObject obj) {
+		assert number < objects.length;
+		assert objects[number] == null;
+		objects[number] = obj;
+	}
+
+	@Override
+	public JavaClassStack getClassStack() {
+		JavaClass[] classes = new JavaClass[objects.length];
+		for (int i = 0; i < objects.length; i++) {
+			classes[i] = objects[i].clazz();
+		}
+		return new JavaClassStack(classes);
+	}
+
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectStack.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectStack.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/JavaObjectStack.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import java.util.Arrays;
+
+public abstract class JavaObjectStack {
+
+	public static final JavaObjectStack HIDDEN = new JavaObjectArrayStack(0) {
+		@Override
+		public boolean equals(Object obj) {
+			return (this == obj);
+		}
+	};
+
+	public abstract JavaObject top();
+
+	public abstract JavaObject[] objects();
+
+	public abstract void setObject(int number, JavaObject obj);
+
+	public abstract JavaClassStack getClassStack();
+
+	@Override
+	public int hashCode() {
+		return Arrays.hashCode(objects());
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj instanceof JavaObjectStack) {
+			JavaObjectStack other = (JavaObjectStack) obj;
+			return Arrays.equals(objects(), other.objects());
+		}
+		return false;
+	}
+}
diff --git a/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/ParkEventTuple.java b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/ParkEventTuple.java
new file mode 100644
--- /dev/null
+++ b/src/java.base/share/classes/sun/evtracing/processing/statistics/metadata/ParkEventTuple.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, 2015, Dynatrace and/or its affiliates. All rights reserved.
+ * 
+ * This file is part of the Lock Contention Tracing Subsystem for the HotSpot
+ * Virtual Machine, which is developed at Christian Doppler Laboratory on
+ * Monitoring and Evolution of Very-Large-Scale Software Systems. Please
+ * contact us at <http://mevss.jku.at/> if you need additional information
+ * or have any questions.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */ 
+package sun.evtracing.processing.statistics.metadata;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import sun.evtracing.parser.ThreadParkBeginEvent;
+import sun.evtracing.parser.ThreadParkEndEvent;
+import sun.evtracing.parser.ThreadUnparkEvent;
+
+public class ParkEventTuple {
+	private final ThreadParkBeginEvent begin;
+	private ThreadParkEndEvent end;
+	private ThreadUnparkEvent unpark;
+	private boolean interrupted;
+	private final JavaObjectStack blocker;
+	private List<ParkEventTuple> overlapping;
+
+	public ParkEventTuple(ThreadParkBeginEvent begin, JavaObjectStack blocker) {
+		this.begin = begin;
+		this.blocker = blocker;
+	}
+
+	public ThreadParkBeginEvent begin() {
+		return begin;
+	}
+
+	public ThreadParkEndEvent end() {
+		return end;
+	}
+
+	public ThreadUnparkEvent unpark() {
+		return unpark;
+	}
+
+	public boolean isInterrupted() {
+		return interrupted;
+	}
+
+	public JavaObjectStack blocker() {
+		return blocker;
+	}
+
+	public List<ParkEventTuple> overlapping() {
+		if (overlapping == null) {
+			return Collections.emptyList();
+		}
+		return Collections.unmodifiableList(overlapping);
+	}
+
+	public void setInterrupted(boolean interrupted) {
+		this.interrupted = interrupted;
+	}
+
+	public void setEnd(ThreadParkEndEvent end) {
+		this.end = end;
+	}
+
+	public void setUnpark(ThreadUnparkEvent unpark) {
+		this.unpark = unpark;
+	}
+
+	public void addOverlapping(ParkEventTuple tuple) {
+		if (overlapping == null) {
+			overlapping = new ArrayList<>();
+		}
+		overlapping.add(tuple);
+	}
+
+	public boolean knownOwner() {
+		return end.parkReturnCode().hasUnpark();
+	}
+
+	public boolean causedContention() {
+		return end.parkReturnCode().causedContention();
+	}
+}
