|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectsofya.ed.structural.SocketProbe
public final class SocketProbe
The SocketProbe class is responsible for transmitting instrumentation trace statements from the subject to the event dispatcher. It is calls to methods implemented by this class which are actually inserted into subjects by the instrumentor.
This class establishes a persistent socket connection to the event
dispatcher on a specified port and implements the instrumentation methods
which send trace messages to the dispatcher over that socket. The
instrumentor is responsible for inserting a call to the start
method of this class as the first executable instruction of a subject class.
This will create an instance of this class which has connected a socket to
the dispatcher and is kept alive as a daemon thread.
To enable this mechanism to work with the greatest possible genericity, and to avoid naming and dynamic linking conflicts when an instrumented dispatcher is being run as a subject, this class is handled in a special fashion. When a dispatcher runs, it constructs a jar file which contains this class (among others) and prepends the jar file to the bootstrap classpath for the subject. Thus when a subject seeks to resolve a call to the static methods implemented by this class, the first definition of the class to be located by the class loader is the one provided on the bootstrap classpath, including when the subject is an instrumented dispatcher. However, since the bootstrap classpath contains no other Sofya related classes (except SConstants, which as an* interface contains no code, and is universally backwards compatible), all other subject classes will be found by the class loader in their expected locations on the subject's own classpath. Note that this also means that the SocketProbe runs inside the same JVM that is running the subject, so the fact that an instrumented dispatcher locates the shared SocketProbe before it locates its own is not problematic (it will however copy its own SocketProbe when constructing its own jar file for its subject).
When the SocketProbe itself is instrumented, the instrumentor inserts special calls to methods of the same name in a class named SocketProbeAlt. That class is created dynamically by the invoking dispatcher at runtime, as a clone of its SocketProbe, and shared in the same manner. This permits the instrumented SocketProbe to call instrumentation methods that do not resolve to itself and cause infinite recursion.
With this mechanism it is possible to create a chain of dispatchers
executing other dispatchers as subjects, although intervention to set the
ports correctly is required beyond the first subject dispatcher. This is
likely only useful up to the second level of self analysis, as data
obtained from further chaining is redundant. (The first level of sel
analysis will provide trace information for the
SocketProcessingStrategy.processProbesSynchronized(java.net.Socket, sofya.ed.structural.ControlData)
method
and the second level of self analysis will provide trace information for
SocketProcessingStrategy.processProbes(java.net.Socket, sofya.ed.structural.ControlData)
).
ProgramEventDispatcher
,
cfInstrumentor
Nested Class Summary |
---|
Nested classes/interfaces inherited from interface sofya.base.SConstants |
---|
SConstants.BlockLabel, SConstants.BlockObjectType, SConstants.BlockSubType, SConstants.BlockType, SConstants.BranchObjectType, SConstants.BranchType, SConstants.EDObjectType, SConstants.TraceObjectType |
Field Summary | |
---|---|
protected static int |
BRANCH_EXIT_MARKER
Constant which marks in the sequence array that the current method is exiting. |
protected static int |
NEW_METHOD_MARKER
Constant which marks that the next element in the object sequence array contains the index to a new method signature. |
static int[] |
sequenceArray
Array which stores the hit object IDs sequentially, using special marker/index pairs to indicate entry into new methods. |
static int |
sequenceIndex
Index pointing to the next open entry in the sequence array. |
Fields inherited from interface sofya.base.SConstants |
---|
DEFAULT_PORT, INST_COMPATIBLE, INST_OLD_UNSUPPORTED, INST_OPT_NORMAL, INST_OPT_SEQUENCE, SIG_CHKALIVE, SIG_ECHO |
Constructor Summary | |
---|---|
protected |
SocketProbe(int port)
Standard constructor. |
Method Summary | |
---|---|
static void |
finish()
|
static byte[] |
getObjectArray(java.lang.String mSignature,
int objCount)
Gets the byte array recording which trace objects have been witnessed in a given method. |
static void |
markMethodInSequence(java.lang.String mSignature,
int objCount)
Inserts a new method marker and index into the sequence array. |
void |
run()
Runs the (daemon) thread. |
static void |
start(int port,
int _instMode,
boolean _doTimestamps,
boolean _useSignalSocket,
int _objType)
Creates SocketProbe and starts daemon thread to keep it memory resident. |
static void |
writeObjectCount(java.lang.String mSignature,
int objCount)
Writes the number of objects (trace entities) in the current method to the socket so that the event dispatcher can notify listeners. |
static void |
writeSequenceData()
Writes the current contents of the object sequence array to the socket to be relayed to listeners by the event dispatcher. |
static void |
writeTraceMessage(int bId,
java.lang.String mSignature)
Transmits a trace message to the event dispatcher via the socket. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
protected static final int NEW_METHOD_MARKER
protected static final int BRANCH_EXIT_MARKER
public static int[] sequenceArray
public static int sequenceIndex
writeSequenceData
when the array is filled.
Constructor Detail |
---|
protected SocketProbe(int port)
Attempts to open the static socket used to send trace messages to the
event dispatcher. This constructor should be called by
start(int, int, boolean, boolean, int)
, which will be invoked by the subject with the
port number embedded by the Instrumentor
. Naturally, if
the subject is instrumented on a different port than the event dispatcher
is listening on, this action will fail. If the connection cannot be made,
the system exits (an action which will occur before any subject code
is executed).
port
- Port number to be used to connect the socket. This should
be set by the instrumentor and supplied by the subject via a call to
start(int, int, boolean, boolean, int)
.Method Detail |
---|
public static void start(int port, int _instMode, boolean _doTimestamps, boolean _useSignalSocket, int _objType)
Creates an instance of the SocketProbe connected to the specified
port. Once the SocketProbe is created it is executed in a daemon thread.
This guarantees that the same SocketProbe object will handle all
instrumentation and ensures that the underlying socket remains
persistent. It is run as a daemon thread to ensure that it is terminated
automatically when the subject is finished. The thread itself does not
take any action (See run()
). If this method has
already been called by the current subject, it returns immediately
without taking any action.
The Instrumentor
should guarantee that a call
to this method is inserted into the subject class as the first possible
executable statement in the class, either in the static initializer
(<clinit>) or in main. This will ensure that all
instrumentation is sent correctly. If SocketProbe itself is instrumented,
a call to this method on SocketProbeAlt (the clone of the invoking
filter's SocketProbe, see ProgramEventDispatcher
) will be
inserted in its static initializer, which allows the SocketProbe to be
traced without introducing infinite recursion scenarios.
If the subject being run is an event dispacher, the subject
dispatcher's SocketProbe will be running in its own subject's JVM. As a
result, to trace the SocketProbe (logically considered a component of the
subject event dispatcher), the main invoking dispatcher will need to
accept two instrumentation connections, one from the subject event
dispatcher and one from the SocketProbe. This requires it to synchronize
the trace messages it receives. To make this possible, the
doTimestamping
flag should be set by the instrumentor, which
will cause the SocketProbe to insert timestamps at the front of each
trace message, which can then be used by the event dispatcher to
order the trace messages. Under no other circumstance should this flag
be set. (See ProgramEventDispatcher
).
All parameters should be set by the instrumentor.
port
- Port number to be used to connect the socket._instMode
- Integer flag specifying the type of instrumentation
present in the subject._doTimestamps
- Flag indicating whether trace messages are to be
timestamped. This is only used with the subject is an event dispatcher._useSignalSocket
- Flag indicating whether a signal socket
connection should be made to the event dispatcher. This is only used
when the subject is an event dispatcher._objType
- Integer flag specifying the type of program entity
traced by the instrumentation present in the subject.public static void finish()
public void run()
The run method simply sleeps indefinitely, so as to keep the same instance of the SocketProbe alive. Note that the run method is uninterruptable. Instead, since it is running as a daemon thread, it will die automatically when the subject exits.
run
in interface java.lang.Runnable
public static void writeTraceMessage(int bId, java.lang.String mSignature)
The correct port should be set by start(int, int, boolean, boolean, int)
and thus
will be known internally as part of the state of the SocketProbe
object. Since the SocketProbe object is kept resident by the daemon
thread, any class throughout the subject can call this method and
successfully transmit a message, assuming start(int, int, boolean, boolean, int)
has been called previously.
A single threaded subject can only call this method sequentially, resulting in typical in-order processing of trace statements. Multithreaded subjects, however, may call this method from different threads, in which case the order of processing of trace statements is not guaranteed to be deterministic. The actual transmission of the message through the socket is synchronized, however, ensuring that the message will not be corrupted.
This method will not block unless the buffer of the underlying socket has been filled.
bId
- The ID of the trace object marked by this instrumentation
probe.mSignature
- Full signature of the method which contains
the trace object being marked.public static byte[] getObjectArray(java.lang.String mSignature, int objCount)
If this is the first time the method has been traced (or the method has been removed from the cache), an array of the necessary size is allocated and initialized. Calls to this method are inserted at the beginning of methods in the subject by the instrumentor.
mSignature
- Signature of the method for which the byte array
is to be retrieved. The signature guarantees uniqueness.objCount
- Number of trace objects in the method, used only
when the array must be allocated. This value should be determined
by the CFG builder and set by the instrumentor.
public static void markMethodInSequence(java.lang.String mSignature, int objCount)
A map is checked to see if an index has already been created for the given signature string. If it has, the existing index is retrieved, otherwise a new index is created and added. A new method marker is then inserted, followed by the index to the signature string. The index pointer is advanced by two so that it is left pointing to the next open element in the array. If advancing the pointer two elements will exceed the size of the array, the array is first committed to the trace and the pointer is reset to zero before proceeding.
mSignature
- Signature of the method which has been entered
and needs to be marked in the array.objCount
- Number of trace objects in the method.public static void writeSequenceData()
New-method markers are used to transmit object IDs in a series
of chunks associated with the correct method signature string.
If the array begins with a continuation of object IDs for a method
from the previous contents of the array, the
currentMethodSig
field is used to properly associate
the objects with that method. When this method returns, all of the
object IDs currently in the array will have been transmitted to the
filter and the array index pointer reset to zero.
public static void writeObjectCount(java.lang.String mSignature, int objCount)
mSignature
- Signature of the method for which the object count
is being sent.objCount
- Number of objects in the method.
|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |