Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.btrace;
import java.lang.management.ManagementFactory;
import static java.lang.management.ManagementFactory.*;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.LinkedBlockingQueue;
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.btrace.aggregation.Aggregation;
import com.sun.btrace.aggregation.AggregationKey;
import com.sun.btrace.aggregation.AggregationFunction;
import com.sun.btrace.annotations.OnError;
import com.sun.btrace.annotations.OnExit;
import com.sun.btrace.annotations.OnTimer;
import com.sun.btrace.annotations.OnEvent;
import com.sun.btrace.annotations.OnLowMemory;
import com.sun.btrace.comm.Command;
import com.sun.btrace.comm.ErrorCommand;
import com.sun.btrace.comm.EventCommand;
import com.sun.btrace.comm.ExitCommand;
import com.sun.btrace.comm.MessageCommand;
import com.sun.btrace.comm.NumberDataCommand;
import com.sun.btrace.comm.NumberMapDataCommand;
import com.sun.btrace.comm.StringMapDataCommand;
import com.sun.btrace.comm.GridDataCommand;
import com.sun.btrace.profiling.MethodInvocationProfiler;
import java.lang.management.GarbageCollectorMXBean;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.lang.management.LockInfo;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryNotificationInfo;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.MonitorInfo;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadFactory;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;
import sun.misc.Perf;
import sun.misc.Unsafe;
import sun.reflect.Reflection;
import sun.security.action.GetPropertyAction;
/**
* Helper class used by BTrace built-in functions and
* also acts runtime "manager" for a specific BTrace client
* and sends Commands to the CommandListener passed.
*
* @author A. Sundararajan
* @author Christian Glencross (aggregation support)
* @author Joachim Skeie (GC MBean support, advanced Deque manipulation)
* @author KLynch
*/
public final class BTraceRuntime {
// we need Unsafe to load BTrace class bytes as
// bootstrap class
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static Properties dotWriterProps;
// a dummy BTraceRuntime instance
private static BTraceRuntime dummy;
private static BTraceRuntime NULL;
// are we running with DTrace support enabled?
private static boolean dtraceEnabled;
private static final boolean messageTimestamp = false;
private static final String LINE_SEPARATOR;
final private static Thread samplerThread;
volatile public static long TIMESTAMP = 0L;
static {
dummy = new BTraceRuntime();
NULL = new BTraceRuntime();
LINE_SEPARATOR = System.getProperty("line.separator");
if (Boolean.getBoolean("btrace.timer.sampled")) {
final long interval = Long.parseLong(System.getProperty("btrace.timer.sampled.interval", "500"));
long time = System.nanoTime();
for(int i=0;i<1000;i++) {
unsafe.park(false, interval);
}
time = System.nanoTime() - time;
final long step = (long)(time / 1000);
samplerThread = new Thread(new Runnable() {
public void run() {
while (true) {
unsafe.park(false, interval);
TIMESTAMP+=step;
}
}
}, "BTrace Sampled Timer");
samplerThread.setDaemon(true);
samplerThread.start();
} else {
samplerThread = null;
}
}
private static ThreadEnteredMap map = new ThreadEnteredMap(NULL);
// BTraceRuntime against BTrace class name
private static Map runtimes =
Collections.synchronizedMap(new HashMap());
// jvmstat related stuff
// to read and write perf counters
private static volatile Perf perf;
// interface to read perf counters of this process
private static volatile PerfReader perfReader;
// performance counters created by this client
private static Map counters =
new HashMap();
// Few MBeans used to implement certain built-in functions
private static volatile HotSpotDiagnosticMXBean hotspotMBean;
private static volatile MemoryMXBean memoryMBean;
private static volatile RuntimeMXBean runtimeMBean;
private static volatile ThreadMXBean threadMBean;
private static volatile List gcBeanList;
private static volatile List memPoolList;
// bytecode generator that generates Runnable implementations
private static RunnableGenerator runnableGenerator;
// Per-client state starts here.
// current thread's exception
private ThreadLocal currentException = new ThreadLocal();
// "command line" args supplied by client
private String[] args;
// whether current runtime has been disabled?
private volatile boolean disabled;
// Class object of the BTrace class [of this client]
private String className;
// BTrace Class object corresponding to this client
private Class clazz;
// does the client have exit action?
private Method exitHandler;
// does the client have exception handler action?
private Method exceptionHandler;
// array of timer callback methods
private Method[] timerHandlers;
// map of client event handling methods
private Map eventHandlers;
// low memory handlers
private Map lowMemHandlers;
// timer to run profile provider actions
private volatile Timer timer;
// executer to run low memory handlers
private volatile ExecutorService threadPool;
// Memory MBean listener
private volatile NotificationListener memoryListener;
// Command queue for the client
private volatile LinkedBlockingQueue queue;
private static class SpeculativeQueueManager {
// maximum number of speculative buffers
private static final int MAX_SPECULATIVE_BUFFERS = Short.MAX_VALUE;
// per buffer message limit
private static final int MAX_SPECULATIVE_MSG_LIMIT = Short.MAX_VALUE;
// next speculative buffer id
private int nextSpeculationId;
// speculative buffers map
private ConcurrentHashMap> speculativeQueues;
// per thread current speculative buffer id
private ThreadLocal currentSpeculationId;
SpeculativeQueueManager() {
speculativeQueues = new ConcurrentHashMap>();
currentSpeculationId = new ThreadLocal();
}
void clear() {
speculativeQueues.clear();
speculativeQueues = null;
currentSpeculationId.remove();
currentSpeculationId = null;
}
int speculation() {
int nextId = getNextSpeculationId();
if (nextId != -1) {
speculativeQueues.put(nextId,
new LinkedBlockingQueue(MAX_SPECULATIVE_MSG_LIMIT));
}
return nextId;
}
boolean send(Command cmd) {
Integer curId = currentSpeculationId.get();
if ((curId != null) && (cmd.getType() != Command.EXIT)) {
LinkedBlockingQueue sb = speculativeQueues.get(curId);
if (sb != null) {
try {
sb.add(cmd);
} catch (IllegalStateException ise) {
sb.clear();
sb.add(new MessageCommand("speculative buffer overflow: " + curId));
}
return true;
}
}
return false;
}
void speculate(int id) {
validateId(id);
currentSpeculationId.set(id);
}
void commit(int id, LinkedBlockingQueue result) {
validateId(id);
currentSpeculationId.set(null);
LinkedBlockingQueue sb = speculativeQueues.get(id);
if (sb != null) {
result.addAll(sb);
sb.clear();
}
}
void discard(int id) {
validateId(id);
currentSpeculationId.set(null);
speculativeQueues.get(id).clear();
}
// -- Internals only below this point
private synchronized int getNextSpeculationId() {
if (nextSpeculationId == MAX_SPECULATIVE_BUFFERS) {
return -1;
}
return nextSpeculationId++;
}
private void validateId(int id) {
if (! speculativeQueues.containsKey(id)) {
throw new RuntimeException("invalid speculative buffer id: " + id);
}
}
}
// per client speculative buffer manager
private volatile SpeculativeQueueManager specQueueManager;
// background thread that sends Commands to the handler
private volatile Thread cmdThread;
// CommandListener that receives the Commands
private volatile CommandListener cmdListener;
private Instrumentation instrumentation;
private BTraceRuntime() {
}
public BTraceRuntime(final String className, String[] args,
final CommandListener cmdListener,
Instrumentation inst) {
this.args = args;
this.queue = new LinkedBlockingQueue();
this.specQueueManager = new SpeculativeQueueManager();
this.cmdListener = cmdListener;
this.className = className;
this.instrumentation = inst;
runtimes.put(className, this);
this.cmdThread = new Thread(new Runnable() {
public void run() {
try {
BTraceRuntime.enter();
while (true) {
Command cmd = queue.take();
cmdListener.onCommand(cmd);
if (cmd.getType() == Command.EXIT) {
return;
}
}
} catch (InterruptedException ignored) {
} catch (IOException ignored) {
} finally {
runtimes.put(className, NULL);
queue.clear();
specQueueManager.clear();
BTraceRuntime.leave();
disabled = true;
}
}
});
cmdThread.setDaemon(true);
cmdThread.start();
}
public static boolean classNameExists(String name) {
return runtimes.containsKey(name);
}
public static void init(PerfReader perfRead, RunnableGenerator runGen) {
Class caller = Reflection.getCallerClass(2);
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
// workaround for "Reflection.getCallerClass(int)" problem
// in JDK7u25 - requiring one additional frame to get the caller
if (caller.getName().equals("com.sun.btrace.BTraceRuntime")) {
caller = Reflection.getCallerClass(3);
}
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
throw new SecurityException("unsafe init");
}
}
perfReader = perfRead;
runnableGenerator = runGen;
loadLibrary(perfRead.getClass().getClassLoader());
}
public Class defineClass(byte[] code) {
Class caller = Reflection.getCallerClass(2);
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
// workaround for "Reflection.getCallerClass(int)" problem
// in JDK7u25 - requiring one additional frame to get the caller
if (caller.getName().equals("com.sun.btrace.BTraceRuntime")) {
caller = Reflection.getCallerClass(3);
}
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
throw new SecurityException("unsafe defineClass");
}
}
return defineClassImpl(code, true);
}
public Class defineClass(byte[] code, boolean mustBeBootstrap) {
Class caller = Reflection.getCallerClass(2);
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
// workaround for "Reflection.getCallerClass(int)" problem
// in JDK7u25 - requiring one additional frame to get the caller
if (caller.getName().equals("com.sun.btrace.BTraceRuntime")) {
caller = Reflection.getCallerClass(3);
}
if (! caller.getName().equals("com.sun.btrace.agent.Client")) {
throw new SecurityException("unsafe defineClass");
}
}
return defineClassImpl(code, mustBeBootstrap);
}
/**
* Enter method is called by every probed method just
* before the probe actions start.
*/
public static boolean enter(BTraceRuntime current) {
if (current.disabled) return false;
return map.enter(current);
// // check we have entered already or disabled
// if (current.disabled || (tls.get() != null)) {
// return false;
// } else {
// tls.set(current);
// return true;
// }
}
public static boolean enter() {
return enter(dummy);
}
/**
* Leave method is called by every probed method just
* before the probe actions end (and actual probed
* method continues).
*/
public static void leave() {
map.exit();
// tls.remove();
}
/**
* start method is called by every BTrace (preprocesed) class
* just at the end of it's class initializer.
*/
public static void start() {
BTraceRuntime current = getCurrent();
if (current != null) {
current.startImpl();
}
}
public void handleExit(int exitCode) {
exitImpl(exitCode);
}
public void handleEvent(EventCommand ecmd) {
if (eventHandlers != null) {
String event = ecmd.getEvent();
Method eventHandler = eventHandlers.get(event);
if (eventHandler != null) {
// BTraceRuntime oldRuntime = tls.get();
BTraceRuntime oldRuntime = (BTraceRuntime)map.get();
leave();
try {
eventHandler.invoke(null, (Object[])null);
} catch (Throwable ignored) {
} finally {
if (oldRuntime != null) {
enter(oldRuntime);
}
}
}
}
}
/**
* One instance of BTraceRuntime is created per-client.
* This forClass method creates it. Class passed is the
* preprocessed BTrace program of the client.
*/
public static BTraceRuntime forClass(Class cl) {
BTraceRuntime runtime = runtimes.get(cl.getName());
runtime.init(cl);
return runtime;
}
/**
* Utility to create a new ThreadLocal object. Called
* by preprocessed BTrace class to create ThreadLocal
* for each @TLS variable.
* @param initValue Initial value.
* This value must be either a boxed primitive or {@linkplain Cloneable}.
* In case a {@linkplain Cloneable} value is provided the value is never used directly
* - instead, a new clone of the value is created per thread.
*/
public static ThreadLocal newThreadLocal(
final Object initValue) {
return new ThreadLocal() {
@Override
protected Object initialValue() {
if (initValue == null) return initValue;
if (initValue instanceof Cloneable) {
try {
Class clz = initValue.getClass();
Method m = clz.getDeclaredMethod("clone");
m.setAccessible(true);
return m.invoke(initValue);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return initValue;
}
};
}
// The following constants are copied from VM code
// for jvmstat.
// perf counter variability - we always variable variability
private static final int V_Variable = 3;
// perf counter units
private static final int V_None = 1;
private static final int V_String = 5;
private static final int PERF_STRING_LIMIT = 256;
/**
* Utility to create a new jvmstat perf counter. Called
* by preprocessed BTrace class to create perf counter
* for each @Export variable.
*/
public static void newPerfCounter(String name, String desc, Object value) {
Perf perf = getPerf();
char tc = desc.charAt(0);
switch (tc) {
case 'C':
case 'Z':
case 'B':
case 'S':
case 'I':
case 'J':
case 'F':
case 'D': {
long initValue = (value != null)? ((Number)value).longValue() : 0L;
ByteBuffer b = perf.createLong(name, V_Variable, V_None, initValue);
b.order(ByteOrder.nativeOrder());
counters.put(name, b);
}
break;
case '[':
break;
case 'L': {
if (desc.equals("Ljava/lang/String;")) {
byte[] buf;
if (value != null) {
buf = getStringBytes((String)value);
} else {
buf = new byte[PERF_STRING_LIMIT];
buf[0] = '\0';
}
ByteBuffer b = perf.createByteArray(name, V_Variable, V_String,
buf, buf.length);
counters.put(name, b);
}
}
break;
}
}
/**
* Return the value of integer perf. counter of given name.
*/
public static int getPerfInt(String name) {
return (int) getPerfLong(name);
}
/**
* Write the value of integer perf. counter of given name.
*/
public static void putPerfInt(int value, String name) {
long l = (long)value;
putPerfLong(l, name);
}
/**
* Return the value of float perf. counter of given name.
*/
public static float getPerfFloat(String name) {
int val = getPerfInt(name);
return Float.intBitsToFloat(val);
}
/**
* Write the value of float perf. counter of given name.
*/
public static void putPerfFloat(float value, String name) {
int i = Float.floatToRawIntBits(value);
putPerfInt(i, name);
}
/**
* Return the value of long perf. counter of given name.
*/
public static long getPerfLong(String name) {
ByteBuffer b = counters.get(name);
synchronized(b) {
long l = b.getLong();
b.rewind();
return l;
}
}
/**
* Write the value of float perf. counter of given name.
*/
public static void putPerfLong(long value, String name) {
ByteBuffer b = counters.get(name);
synchronized (b) {
b.putLong(value);
b.rewind();
}
}
/**
* Return the value of double perf. counter of given name.
*/
public static double getPerfDouble(String name) {
long val = getPerfLong(name);
return Double.longBitsToDouble(val);
}
/**
* write the value of double perf. counter of given name.
*/
public static void putPerfDouble(double value, String name) {
long l = Double.doubleToRawLongBits(value);
putPerfLong(l, name);
}
/**
* Return the value of String perf. counter of given name.
*/
public static String getPerfString(String name) {
ByteBuffer b = counters.get(name);
byte[] buf = new byte[b.limit()];
byte t = (byte)0;
int i = 0;
synchronized (b) {
while ((t = b.get()) != '\0') {
buf[i++] = t;
}
b.rewind();
}
try {
return new String(buf, 0, i, "UTF-8");
} catch (java.io.UnsupportedEncodingException e) {
// ignore, UTF-8 encoding is always known
}
return "";
}
/**
* Write the value of float perf. counter of given name.
*/
public static void putPerfString(String value, String name) {
ByteBuffer b = counters.get(name);
byte[] v = getStringBytes(value);
synchronized (b) {
b.put(v);
b.rewind();
}
}
/**
* Handles exception from BTrace probe actions.
*/
public static void handleException(Throwable th) {
BTraceRuntime current = getCurrent();
if (current != null) {
current.handleExceptionImpl(th);
} else {
th.printStackTrace();
}
}
// package-private interface to BTraceUtils class.
static int speculation() {
BTraceRuntime current = getCurrent();
return current.specQueueManager.speculation();
}
static void speculate(int id) {
BTraceRuntime current = getCurrent();
current.specQueueManager.speculate(id);
}
static void discard(int id) {
BTraceRuntime current = getCurrent();
current.specQueueManager.discard(id);
}
static void commit(int id) {
BTraceRuntime current = getCurrent();
current.specQueueManager.commit(id, current.queue);
}
/**
* Indicates whether two given objects are "equal to" one another.
* For bootstrap classes, returns the result of calling Object.equals()
* override. For non-bootstrap classes, the reference identity comparison
* is done.
*
* @param obj1 first object to compare equality
* @param obj2 second object to compare equality
* @return true if the given objects are equal;
* false otherwise.
*/
static boolean compare(Object obj1, Object obj2) {
if (obj1 instanceof String) {
return obj1.equals(obj2);
} else if (obj1.getClass().getClassLoader() == null) {
if (obj2 == null || obj2.getClass().getClassLoader() == null) {
return obj1.equals(obj2);
} // else fall through..
}
return obj1 == obj2;
}
// BTrace map functions
static Map newHashMap() {
return new BTraceMap(new HashMap());
}
static Map newWeakMap() {
return new BTraceMap(new WeakHashMap());
}
static Deque newDeque() {
return new BTraceDeque(new ArrayDeque());
}
static Appendable newStringBuilder(boolean threadSafe) {
return threadSafe ? new StringBuffer() : new StringBuilder();
}
static Appendable newStringBuilder() {
return newStringBuilder(false);
}
static int size(Collection coll) {
if (coll instanceof BTraceCollection || coll.getClass().getClassLoader() == null) {
return coll.size();
} else {
throw new IllegalArgumentException();
}
}
public static boolean isEmpty(Collection coll) {
if (coll instanceof BTraceCollection || coll.getClass().getClassLoader() == null) {
return coll.isEmpty();
} else {
throw new IllegalArgumentException();
}
}
static boolean contains(Collection coll, Object obj) {
if (coll instanceof BTraceCollection || coll.getClass().getClassLoader() == null) {
for (E e : coll) {
if (compare(e, obj)) {
return true;
}
}
return false;
} else {
throw new IllegalArgumentException();
}
}
static Object[] toArray(Collection collection) {
if (collection == null) {
return new Object[0];
} else {
return collection.toArray();
}
}
static V get(Map map, Object key) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
return map.get(key);
} else {
throw new IllegalArgumentException();
}
}
static boolean containsKey(Map map, Object key) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
return map.containsKey(key);
} else {
throw new IllegalArgumentException();
}
}
static boolean containsValue(Map map, Object value) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
return map.containsValue(value);
} else {
throw new IllegalArgumentException();
}
}
static V put(Map map, K key, V value) {
if (map instanceof BTraceMap) {
return map.put(key, value);
} else {
throw new IllegalArgumentException("not a btrace map");
}
}
static V remove(Map map, Object key) {
if (map instanceof BTraceMap) {
return map.remove(key);
} else {
throw new IllegalArgumentException("not a btrace map");
}
}
static void clear(Map map) {
if (map instanceof BTraceMap) {
map.clear();
} else {
throw new IllegalArgumentException("not a btrace map");
}
}
static int size(Map map) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
return map.size();
} else {
throw new IllegalArgumentException();
}
}
static boolean isEmpty(Map map) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
return map.isEmpty();
} else {
throw new IllegalArgumentException();
}
}
static void putAll(Map src, Map dst) {
dst.putAll(src);
}
static void copy(Map src, Map dst) {
dst.clear();
dst.putAll(src);
}
static void printMap(Map map) {
if (map instanceof BTraceMap ||
map.getClass().getClassLoader() == null) {
synchronized(map) {
Map m = new HashMap();
Set> entries = map.entrySet();
for (Map.Entry