org.netbeans.lib.profiler.server.ProfilerRuntimeCPU Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.lib.profiler.server;
import java.lang.reflect.Method;
import java.util.List;
import org.netbeans.lib.profiler.global.Platform;
import org.netbeans.lib.profiler.server.system.Stacks;
import org.netbeans.lib.profiler.server.system.Timers;
/**
* This class contains the functionality that is common for all CPU profiling methods available in JFluid.
*
* @author Tomas Hurka
* @author Misha Dmitriev
*/
public class ProfilerRuntimeCPU extends ProfilerRuntime {
//~ Static fields/initializers -----------------------------------------------------------------------------------------------
private static final boolean DEBUG = false;
private static final int MAX_STRING_LENGTH = 2048;
static final Object NO_RET_VALUE = new Object();
private static int nProfiledThreadsLimit;
protected static int nProfiledThreadsAllowed;
protected static int stackDepthLimit = Integer.MAX_VALUE;
protected static boolean enableFirstTimeMethodInvoke;
// The following flag is used to prevent deadlock inside getThreadInfo() by forcing immediate return from methodEntry() etc.
// in case methodEntry() (typically when it's injected in some core class method) is executed on behalf of some profiler server thread,
// when all target app threads are suspended. In that case, some thread may be suspended within getThreadInfo(), holding the lock.
// It is also used to disable instrumentation to be on the safe side when we e.g. detach from a running multithreaded application -
// it looks as if in this case de-instrumentation may not immediately propagate everywhere.
protected static volatile boolean recursiveInstrumentationDisabled = false;
// ------------------------------------------ Timers -----------------------------------------------
protected static boolean absoluteTimerOn;
// ------------------------------------------ Timers -----------------------------------------------
protected static boolean threadCPUTimerOn;
protected static boolean waitTrackingEnabled;
protected static boolean sleepTrackingEnabled;
// ---------------------------------- Profile Data Acquisition --------------------------------------
protected static boolean[] instrMethodInvoked;
private static boolean javaLangReflectMethodInvokeInterceptEnabled = false;
private static Method getRequestedSessionIdMethod;
private static Method getMethodMethod;
private static Method getServletPathMethod;
//~ Methods ------------------------------------------------------------------------------------------------------------------
// See the comment in writeTimeStampedEvent() below, marked with (***)
// On all OSes except Linux, the upper byte of value returned by Timers.getCurrentTimeInCounts() will be zero - timer
// calculates time from program start or from machine start. But on Linux it seems to be timeofday or something. We have
// to take measures here to return time in the same format as used for collected data.
public static long getAbsTimeStampInCollectedFormat() {
return Timers.getCurrentTimeInCounts() & 72057594037927935L; //0xFFFFFFFFFFFFFF, i.e. 7 bytes
}
public static void setInstrMethodsInvoked(boolean[] methodInvoked) {
instrMethodInvoked = methodInvoked;
}
public static void setJavaLangReflectMethodInvokeInterceptEnabled(boolean v) {
javaLangReflectMethodInvokeInterceptEnabled = v;
}
public static void setNProfiledThreadsLimit(int num) {
nProfiledThreadsLimit = nProfiledThreadsAllowed = num;
}
public static void setStackDepthLimit(int num) {
stackDepthLimit = num;
}
public static void setWaitAndSleepTracking(boolean waitTracking, boolean sleepTracking) {
waitTrackingEnabled = waitTracking;
sleepTrackingEnabled = sleepTracking;
}
public static void setTimerTypes(boolean absolute, boolean threadCPU) {
if (threadCPU != threadCPUTimerOn && Platform.isSolaris()) {
Timers.enableMicrostateAccounting(threadCPU);
}
absoluteTimerOn = absolute;
threadCPUTimerOn = threadCPU;
}
public static void enableFirstTimeMethodInvoke(boolean enabled) {
enableFirstTimeMethodInvoke = enabled;
}
// This is currently used only when calibrating the profiler, to pre-create a ThreadInfo before calling methodEntry/Exit.
// It is done to prevent the system attempting to send a "new thread created" message to the client.
public static void createThreadInfoForCurrentThread() {
ThreadInfo ti = ThreadInfo.getThreadInfo();
ti.initialize();
ti.useEventBuffer();
ti.inCallGraph = false; // Important: this is a correct initial value when ti is used in calibration
}
public static void handleJavaLangReflectMethodInvoke(Method method) {
if (!javaLangReflectMethodInvokeInterceptEnabled) {
return;
}
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (!ti.isInitialized() || !ti.inCallGraph) {
return; // ti == null may happen if instrumentation has been removed or data collectors reset
}
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
externalActionsHandler.handleReflectiveInvoke(method);
ti.inProfilingRuntimeMethod--;
}
public static void handleServletDoMethod(Object request) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (!ti.isInitialized()) {
System.out.println("No thread for servlet request"); // NOI18N
return;
}
ti.inProfilingRuntimeMethod++;
servletDoMethodHook(ti, request);
ti.inProfilingRuntimeMethod--;
}
public static void resetProfilerCollectors() {
nProfiledThreadsAllowed = nProfiledThreadsLimit;
}
public static void resumeCurrentThreadTimer() {
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (!ti.isInitialized() || !ti.inCallGraph) {
return;
}
writeAdjustTimeEvent(ti, ti.absEntryTime, ti.threadEntryTime);
ti.inProfilingRuntimeMethod--;
}
// This is currently called in class load hook, to stop counting the time and emitting method entry/exit events while the
// hook and other Java code that it may call are active.
public static ThreadInfo suspendCurrentThreadTimer() {
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (!ti.isInitialized() || !ti.inCallGraph) {
return ti;
}
ti.inProfilingRuntimeMethod++;
// those timestamps are taken here, as opposed to earlier in this method, because we need to make sure we do not
// profile the Timer.get... calls, by increasing the ti.inProfilingRuntimeMethod
// see issue 65614 for a possible impact of this
// http://profiler.netbeans.org/issues/show_bug.cgi?id=65614
ti.absEntryTime = Timers.getCurrentTimeInCounts();
if (threadCPUTimerOn) {
ti.threadEntryTime = Timers.getThreadCPUTimeInNanos();
}
return ti;
}
protected static void clearDataStructures() {
ProfilerRuntime.clearDataStructures();
nProfiledThreadsAllowed = nProfiledThreadsLimit;
}
protected static void createNewDataStructures() {
ProfilerRuntime.createNewDataStructures();
// top level Marker method has stacktrace
Stacks.createNativeStackFrameBuffer(ProfilerRuntimeMemory.MAX_STACK_FRAMES);
}
protected static long currentTimeInCounts() {
return Timers.getCurrentTimeInCounts();
}
protected static void enableProfiling(boolean v) {
recursiveInstrumentationDisabled = !v;
// Doesn't call clearDataStructures() since this is an "abstract" class
}
// ---------------------------------- Handling wait/sleep/monitor times ----------------------------
protected static long monitorEntryCPU(ThreadInfo ti, Object monitor, ThreadInfo ownerTi) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++monitorEntry, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_ENTRY_MONITOR, ti, monitor, ownerTi);
}
return -1;
}
protected static long monitorExitCPU(ThreadInfo ti, Object monitor) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++monitorExit, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_EXIT_MONITOR, ti, monitor);
}
return -1;
}
protected static long sleepEntryCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !sleepTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++sleepEntry, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_ENTRY_SLEEP, ti);
}
return -1;
}
protected static long sleepExitCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !sleepTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++sleepExit, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_EXIT_SLEEP, ti);
}
return -1;
}
protected static long waitEntryCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++waitEntry, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_ENTRY_WAIT, ti);
}
return -1;
}
protected static long waitExitCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++waitExit, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_EXIT_WAIT, ti);
}
return -1;
}
protected static long parkEntryCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++parkEntry, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_ENTRY_PARK, ti);
}
return -1;
}
protected static long parkExitCPU(ThreadInfo ti) {
if (recursiveInstrumentationDisabled || !waitTrackingEnabled) {
return -1; // See the comment at the recursiveInstrumentationDisabled variable declaration
}
if (ti.isInitialized() && ti.inCallGraph) {
//System.out.println("++++++parkExit, depth = " + ti.stackDepth);
return writeWaitTimeEvent(METHOD_EXIT_PARK, ti);
}
return -1;
}
protected static void firstTimeMethodInvoke(final ThreadInfo ti, final char methodId) {
if (enableFirstTimeMethodInvoke) {
long absTimeStamp = Timers.getCurrentTimeInCounts();
long threadTimeStamp = threadCPUTimerOn ? Timers.getThreadCPUTimeInNanos() : 0;
externalActionsHandler.handleFirstTimeMethodInvoke(methodId);
writeAdjustTimeEvent(ti, absTimeStamp, threadTimeStamp);
}
}
static void writeServletDoMethod(ThreadInfo ti, String method, String servletPath, String sessionId) {
int fullInfoLen = 1 + 1 + (servletPath.length() * 2) + 4;
int curPos = ti.evBufPos; // It's important to use a local copy for evBufPos, so that evBufPos is at event boundary at any moment
if ((curPos + fullInfoLen) > ThreadInfo.evBufPosThreshold) {
copyLocalBuffer(ti);
curPos = ti.evBufPos;
}
byte[] evBuf = ti.evBuf;
byte methodId = -1;
int sessionHash = -1;
if (null != method) switch (method) {
case "GET": methodId = 1; break; // NOI18N
case "POST": methodId = 2; break; // NOI18N
case "PUT": methodId = 3; break; // NOI18N
case "DELETE": methodId = 4; break; // NOI18N
default:
break;
}
if (sessionId != null) {
sessionHash = sessionId.hashCode();
}
evBuf[curPos++] = SERVLET_DO_METHOD;
evBuf[curPos++] = methodId;
byte[] name = servletPath.getBytes();
int len = name.length;
evBuf[curPos++] = (byte) ((len >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((len) & 0xFF);
System.arraycopy(name, 0, evBuf, curPos, len);
curPos += len;
evBuf[curPos++] = (byte) ((sessionHash >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((sessionHash >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((sessionHash >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((sessionHash) & 0xFF);
ti.evBufPos = curPos;
}
// ---------------------------------- Writing profiler events --------------------------------------
static void writeTimeStampedEvent(byte eventType, ThreadInfo ti, char methodId) {
int[] stackFrameIds = null;
int currentStackDepth = 0;
if (eventType == MARKER_ENTRY) {
// top-level marker method has stack trace
if (ti.stackDepth == 0) {
stackFrameIds = new int[ProfilerRuntimeMemory.MAX_STACK_FRAMES];
currentStackDepth = Stacks.getCurrentStackFrameIds(ti.getThread(), stackFrameIds.length, stackFrameIds);
currentStackDepth -= ProfilerRuntimeMemory.NO_OF_PROFILER_FRAMES;
} else {
stackFrameIds = new int[0];
}
}
int curPos = ti.evBufPos; // It's important to use a local copy for evBufPos, so that evBufPos is at event boundary at any moment
if (curPos + currentStackDepth*4 > ThreadInfo.evBufPosThreshold) {
copyLocalBuffer(ti);
curPos = ti.evBufPos;
}
byte[] evBuf = ti.evBuf;
if (!ti.isInitialized()) return; // Reset collectors performed when we were already executing instrumentation code
evBuf[curPos++] = eventType;
evBuf[curPos++] = (byte) ((methodId >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((methodId) & 0xFF);
// Note that in the code below, we write only the 7 low bytes of the 64-bit timestamp. The justification is that this saves
// us some performance and memory, and 2^55 == 36028797018963968 ns == 36028797 sec == 10008 hr == 416 days is a sufficent
// representation range for the foreseeable usages of our tool. (***)
if (absoluteTimerOn) {
long absTimeStamp = Timers.getCurrentTimeInCounts();
evBuf[curPos++] = (byte) ((absTimeStamp >> 48) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp >> 40) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp >> 32) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((absTimeStamp) & 0xFF);
if (DEBUG) {
System.out.println("ProfilerRuntimeCPU.DEBUG: Writing event (Abs) type = " + eventType + ", metodId = "
+ (int) methodId + ", timestamp: " + absTimeStamp); // NOI18N
}
}
if (threadCPUTimerOn) {
long threadTimeStamp = Timers.getThreadCPUTimeInNanos();
evBuf[curPos++] = (byte) ((threadTimeStamp >> 48) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp >> 40) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp >> 32) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((threadTimeStamp) & 0xFF);
if (DEBUG) {
System.out.println("ProfilerRuntimeCPU.DEBUG: Writing event (CPU) type = " + eventType + ", metodId = "
+ (int) methodId + ", timestamp: " + threadTimeStamp); // NOI18N
}
}
if (stackFrameIds != null) {
evBuf[curPos++] = (byte) ((currentStackDepth >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((currentStackDepth >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((currentStackDepth) & 0xFF);
int frameIdx = ProfilerRuntimeMemory.NO_OF_PROFILER_FRAMES;
for (int i = 0; i < currentStackDepth; i++) {
evBuf[curPos++] = (byte) ((stackFrameIds[frameIdx] >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((stackFrameIds[frameIdx] >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((stackFrameIds[frameIdx] >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((stackFrameIds[frameIdx]) & 0xFF);
frameIdx++;
}
}
ti.evBufPos = curPos;
}
static long writeWaitTimeEvent(byte eventType, ThreadInfo ti) {
return writeWaitTimeEvent(eventType, ti, null);
}
static void writeParametersEvent(ThreadInfo ti) {
List pars = ti.getParameters();
int parsLength = 0;
if (pars != null) {
for (int i = 0; i < pars.size(); i++) {
parsLength += 1 + getParSize(pars.get(i));
}
}
int fullInfoLen = 1 + 1 + parsLength;
int curPos = ti.evBufPos; // It's important to use a local copy for evBufPos, so that evBufPos is at event boundary at any moment
if ((curPos + fullInfoLen) > ThreadInfo.evBufPosThreshold) {
copyLocalBuffer(ti);
curPos = ti.evBufPos;
}
byte[] evBuf = ti.evBuf;
evBuf[curPos++] = MARKER_ENTRY_PARAMETERS;
if (pars != null) {
evBuf[curPos++] = (byte) pars.size();
for (int i = 0; i < pars.size(); i++) {
curPos = writeParameter(evBuf, curPos, pars.get(i));
}
ti.clearParameters();
} else {
evBuf[curPos++] = 0;
}
ti.evBufPos = curPos;
}
static void writeRetValue(Object ret, ThreadInfo ti) {
if (ret != NO_RET_VALUE) {
ti.addParameter(ret != null ? converToString(ret) : "");
writeParametersEvent(ti);
}
}
private static void servletDoMethodHook(ThreadInfo ti, Object request) {
String servletPath = null;
String method = null;
String requestedSessionId = null;
if (getRequestedSessionIdMethod == null) {
try {
Class requestClass = request.getClass();
getRequestedSessionIdMethod = requestClass.getMethod("getRequestedSessionId", null); // NOI18N
getMethodMethod = requestClass.getMethod("getMethod", null); // NOI18N
getServletPathMethod = requestClass.getMethod("getServletPath", null); // NOI18N
} catch (Exception ex) {
ex.printStackTrace();
return;
}
}
try {
requestedSessionId = (String) getRequestedSessionIdMethod.invoke(request, null);
method = (String) getMethodMethod.invoke(request, null);
servletPath = (String) getServletPathMethod.invoke(request, null);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
writeServletDoMethod(ti, method, servletPath, requestedSessionId);
}
public static void addParameter(boolean b) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(b);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(char c) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(c);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(byte b) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(b);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(short s) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(s);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(int i) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(i);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(long l) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(l);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(float f) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(f);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(double d) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(d);
ti.inProfilingRuntimeMethod--;
}
public static void addParameter(Object b) {
if (recursiveInstrumentationDisabled) {
return;
}
ThreadInfo ti = ThreadInfo.getThreadInfo();
if (ti.inProfilingRuntimeMethod > 0) {
return;
}
ti.inProfilingRuntimeMethod++;
ti.addParameter(b != null ? converToString(b) : "");
ti.inProfilingRuntimeMethod--;
}
private static int getParSize(Object p) {
Class type = p.getClass();
if (type == Integer.class) {
return 4;
} else if (type == Boolean.class) {
return 1;
} else if (type == Byte.class) {
return 1;
} else if (type == Character.class) {
return 2;
} else if (type == Short.class) {
return 2;
} else if (type == Long.class) {
return 8;
} else if (type == Float.class) {
return 4;
} else if (type == Double.class) {
return 8;
} else {
return 2 + truncatedByteLength((String) p);
}
}
private static int writeParameter(byte[] evBuf, int curPos, Object p) {
Class type = p.getClass();
if (type == Integer.class) {
int vp = ((Integer)p);
evBuf[curPos++] = ProfilerInterface.INT;
evBuf[curPos++] = (byte) ((vp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else if (type == Boolean.class) {
boolean vp = ((Boolean)p);
evBuf[curPos++] = ProfilerInterface.BOOLEAN;
evBuf[curPos++] = (byte) (vp ? 1 : 0);
} else if (type == Byte.class) {
byte vp = ((Byte)p);
evBuf[curPos++] = ProfilerInterface.BYTE;
evBuf[curPos++] = vp;
} else if (type == Character.class) {
char vp = ((Character)p);
evBuf[curPos++] = ProfilerInterface.CHAR;
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else if (type == Short.class) {
short vp = ((Short) p);
evBuf[curPos++] = ProfilerInterface.SHORT;
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else if (type == Long.class) {
long vp = ((Long)p);
evBuf[curPos++] = ProfilerInterface.LONG;
evBuf[curPos++] = (byte) ((vp >> 56) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 48) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 40) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 32) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else if (type == Float.class) {
int vp = Float.floatToIntBits((Float)p);
evBuf[curPos++] = ProfilerInterface.FLOAT;
evBuf[curPos++] = (byte) ((vp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else if (type == Double.class) {
long vp = Double.doubleToLongBits(((Double)p));
evBuf[curPos++] = ProfilerInterface.DOUBLE;
evBuf[curPos++] = (byte) ((vp >> 56) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 48) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 40) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 32) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 24) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 16) & 0xFF);
evBuf[curPos++] = (byte) ((vp >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((vp) & 0xFF);
} else {
String sp = (String) p;
int lengthBytes = truncatedByteLength(sp);
evBuf[curPos++] = ProfilerInterface.REFERENCE;
evBuf[curPos++] = (byte) ((lengthBytes >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((lengthBytes) & 0xFF);
for (int i = 0; i < lengthBytes/2; i++) {
char ch = sp.charAt(i);
evBuf[curPos++] = (byte) ((ch >> 8) & 0xFF);
evBuf[curPos++] = (byte) ((ch) & 0xFF);
}
}
return curPos;
}
static String converToString(Object o) {
String clazz = o.getClass().getName();
if (clazz.startsWith("java.lang.")) {
return o.toString();
}
if (clazz.equals("java.sql.Date")) {
return String.valueOf(((java.sql.Date)o).getTime());
}
if (clazz.equals("java.sql.Timestamp")) {
return String.valueOf(((java.sql.Timestamp)o).getTime());
}
if (clazz.equals("java.math.BigDecimal")) {
return o.toString();
}
return getObjectId(o, clazz);
}
private static int truncatedByteLength(String s) {
int length = s.length()*2;
if (length < MAX_STRING_LENGTH) {
return length;
}
return MAX_STRING_LENGTH;
}
private static String getObjectId(Object o, String clazz) {
return clazz + "@" + Integer.toHexString(System.identityHashCode(o));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy