* doc/handbook/jvmti.tex: documentation of the cacao jvmti implementation added to...
[cacao.git] / doc / handbook / jvmti.tex
1 \chapter{Java Virtual Machine Tool Interface (JVMTI)}
2 \section{Introduction} % 1/2
3 Before this work started the basic approach of debugging java code that runs in the CACAO virtual machine was either to enable the command line option \textit{verbose:call}, use gdb or insert debug statements in the java code itself. Debugging java code this way can be a very tedious job. Therefore this work was started with the aim to give developers a better support for debugging java code that runs in the CACAO java virtual machine.
4
5 Other projects had already started similar efforts like SableVM\cite{sablevm} and Redhat in GIJ\cite{gij}. To take advantage of the numerous already existing Java debugging front-ends both project implemented Sun's Java Debug Wire Protocol (JDWP)\cite{jpda}. Whereas the JDWP implementation in SableVM is older and tight coupled with the virtual machine itself, Redhat's implementation been committed to the GNU classpath project and is expected to be integrated in other virtual machines. For this reason the decision has been taken to implement JVMTI\cite{jvmti} as being the lowest layer of the Java Platform Debugger Architecture(JPDA)\cite{jpda}.
6
7 \section{The Sun Java Platform Debugger Architecture (JPDA)} % 2
8 Throughout this document I will refer to the version of the Java Platform Debugger Architecture\cite{jpda} introduced by Sun Microsystems with Java 2 Standard Edition (J2SE) 5.0.
9
10 \subsection{Architecture} % 1
11 As it is sketched out in figure \ref{fig:jdpa} the JPDA is composed by three layers. The highest layer is the Java Debug Interface (JDI) which defines a high level interface which was developed for debugger developers to write remote debuggers easily. 
12
13 JDI itself is built on top of JDWP. The Java Debug Wire Protocol (JDWP) represents the communication layer between the debugger and the debuggee process. 
14
15 The lowest layer in the JPDA is the Java Virtual Machine Tool Interface (JVMTI) which is used by the JDWP back-end to interact with the virtual machine. JVMTI was introduced in J2SE 5.0 and replaced the Java Virtual Machine Debug Interface (JVMDI).
16
17 \begin{figure}[h]
18         \centering
19         \includegraphics[scale=.75]{arch.eps}
20         \caption{Java Platform Debugger Architecture overview\cite{jpda}}
21         \label{fig:jdpa}
22 \end{figure}
23
24
25 According to the JPDA specification a debugger may be built on top of any of this three layers depending on their need of lower level functionalities.
26
27
28 \subsection{Java Virtual Machine Tool Interface (JVMTI)} % 1-2
29 JVMTI is two-way interface that enables its client to get information about the state of the virtual machine and the java program that is being executed or alter it. The client can also set callback function to be informed about the occurrence of specified events.
30
31 \subsubsection{Invoking JVMTI}
32 JVMTI environments can be created either in a so called jvmti agent or in a java native method. Each JVMTI environment contains client defined callbacks, event notification modes, capabilities and a environment local storage. Similar to the JNI opaque pointer the JVMTI environment pointer is used to call JVMTI functions by dereferencing the JVMTI environment pointer twice.
33
34 A jvmti agent is a shared library that contains a \textit{Agent\_OnLoad} function that is called on startup by the virtual machine. In the \textit{Agent\_OnLoad} function an agent is only allowed to call jvmti functions because other parts of the virtual machine are not yet initialized. On shut down the the virtual machine calls \textit{Agent\_UnLoad} to allow the agent to shut down gracefully. The user can specify the jvmti agent by using either the argument \textit{agentlib} or \textit{agentpath}.
35
36 \begin{figure}[h]
37 \begin{verbatim}
38           -agentlib:<agent-lib-name>=<options>
39           -agentpath:<path-to-agent>=<options>
40 \end{verbatim}
41 \caption{Command line arguments to load a JVMTI agent}
42 \end{figure}
43
44 The opaque pointer to a new JVMTI environment can be obtained through the Java Invocation API by calling GetEnv.
45
46 \begin{figure}[h]
47 \begin{verbatim}
48   (*javavm)->
49        GetEnv(javavm, &jvmti_environment, JVMTI_VERSION_1_0)
50 \end{verbatim}
51 \caption{Java Invocation API call to get a new JVMTI environment}
52 \end{figure}
53
54 This can be done in a Java native method or in the AgentOnLoad function.
55
56 \subsubsection{Functions}
57 \label{jvmtifunctions}
58 JVMTI functions get called by dereferencing the JVMTI environment pointer twice. Every JVMTI function has jvmtiError as its return type. As you can see in figure \ref{functioncall} the result of a function call is stored in an variable pointed to by an other parameter to the function call.
59
60 \begin{figure}[h]
61 \begin{verbatim}
62   jint version;
63   ...
64   jvmtiError error = 
65      (*jvmti_environment)->
66           GetVersionNumber(jvmti_environment, &version);
67 \end{verbatim}
68 \caption{Example JVMTI function call to GetVersionNumber.}
69 \label{functioncall}
70 \end{figure}
71
72 The java virtual machine tool interface defines 120 required and optional functions. Their functionality ranges from thread, thread group, stack frame, local variable, heap, class, field, method and system properties inspection and manipulation to setting breakpoints, watch fields or timers. Additionally there are function to support writing JVMTI agents and JVMTI management functions. For a detailed description of the single functions please refer to the JVMTI specification\cite{jvmti}.
73
74 The functions that can be called within a particular environment are restricted by the phase in which the virtual machine is currently running and the capabilities that a given JVMTI environment has obtained by the virtual machine.
75
76 JVMTI defines the phase \textit{onload}, \textit{primordial}, \textit{start}, \textit{live} and \textit{dead}. The \textit{onload} phase takes just as long as the AgentOnLoad function is running. Between the \textit{onload} and the \textit{start} phase there is the \textit{primordial} phase. In this phase only some jvmti functions can be called and JNI is not live yet. From \textit{start} phase on JNI calls are allowed but the virtual machine is not yet fully initialized. In the \textit{live} phase the java virtual machine is fully initialized. The final phase is \textit{dead}, which is active during the termination of the virtual machine.
77
78 The java virtual machine tool interface has required and optional functions. The capabilities of a JVMTI environment show what optional function may be called by a given environment. A new environment has no optional capabilities enabled. Therefore to call optional functions the function \textit{Add Capabilities} has to be called first. To get all available capabilities a call to \textit{Get Potential Capabilities} is needed.
79
80
81 \subsubsection{Events}
82 JVMTI defines 30 events that can occur on a breakpoint hit, single step, class or method state change, exceptions, phase change, garbages collections, method invocation, monitor enter, field access, thread start or end. For a detailed description of the single events please refer to the JVMTI specification\cite{jvmti}.
83
84 As for JVMTI functions, events are influenced by the phase the virtual machine is in and the capabilities of the JVMTI environment. To be able to handle events a JVMTI agent needs to set callback function that will be executed by the virtual machine on occurrence of the event. This is done by calling \textit{Set Event Callbacks}. After setting event callbacks, events have to be enabled by calling \textit{Set Event Notification Mode}. This function may return an error if the capability for a given event is not available in the current JVMTI environment.
85
86 \section{GNU classpath JDWP} % 2
87 GNU classpath JDWP is almost a complete implementation of Sun's JDWP specification. The drawback is that it was not build with JVMTI in mind. Therefore a few adaptions were needed to make it work with JVMTI and CACAO.
88
89 \subsection{Invocation} % 1/2
90 Because CACAO should work with existing Java debugging front-ends, like eclipse\cite{eclipse}, it was chosen to make the command line arguments compatible with Sun's JDK. Therefore JDWP can be started in CACAO by using either the \textit{-agentlib}, \textit{-agentpath} or the old \textit{-Xdebug} and \textit{-Xrunjdwp} arguments. 
91
92 \begin{figure}[h]
93 \begin{verbatim}
94
95                   cacao -agentlib:jdwp=help
96 \end{verbatim}
97 \caption{Invocation of cacao jdwp help}
98 \end{figure}
99
100 The invocation of GNU classpath JDWP itself is the same for both kind of arguments. On start-up of CACAO, immediately after all command line arguments for the virtual machine have been processed, the JVMTI agent libjdwp.so is called.
101
102 In its Agent\_OnLoad function all JDWP related options are processed, a new JVMTI environment is created, all JDWP relevant callbacks are set, all capabilities are added and the \textit{VM\_INIT} event is enabled. 
103
104 The \textit{VM\_INIT} event is triggered after the virtual machine has been fully initialized and before the main class is executed. In the callback a new GNU classpath JDWP object is created and the JDWP listening thread is started. This permits the user to take control of the execution of the java program before it effectively starts.
105
106 \subsection{JDWP-JVMTI interface} % 1 /2
107 After the JDWP listening thread has been started, every communication between GNU classpath JDWP and CACAO JVMTI takes place through the JDWP-JVMTI glue code. It consists of the implementation of all java native methods in the VMVirtualMachine, VMMethod and VMFrame classes of the gnu.classpath.jdwp package and the callback functions in VMJdwp.
108
109 The GNU classpath JDWP native methods contain all virtual machine dependent functions that JDWP needs. Because CACAO supports JVMTI those native methods are implemented using different JVMTI function calls.
110
111 To facilitate the delivery of JVMTI events to the JDWP layer, new \texttt{gnu.classpath.jdwp.event}-objects are created. Each event type is enclosed in its own event class.  Each of those event objects represent a single event which is sent by calling the static java method \texttt{Jdwp.notify(event ev)}. This is done within each JVMTI callback function using JNI function calls.
112
113
114
115 \section{JVMTI implementation in CACAO} % 5
116
117 The main goals that led the development of JVMTI in CACAO were to enable developers to debug their software efficiently and minimize the influence and interference of JVMTI code on the normal runtime behaviour of the CACAO virtual machine.
118
119 \subsection{Architecture} % 1
120
121 The architectural decisions for the JVMTI implementation in CACAO were mainly complicated by the fact that CACAO uses a just in time compiler to execute java code. Due to that, key functionality, like \textit{breakpoint} and \textit{single step} events, need \textit{ptrace}\cite{ptrace} support.
122
123 The easiest way to implement other JVMTI events would be to compile direct function calls for firing jvmti events in the normal CACAO code. This approach is used to implement events that are supposed to happen rarely, like thread-start/end or phase change events.
124
125 If this approach would be used on events that occur very often, like \textit{Method Enter} and \textit{Method Exit}, the runtime behaviour would be strongly influenced by a significant slow down of the virtual machine. The fact that JVMTI can be started and stopped multiple times during the lifetime of the virtual machine, makes this problem even worse because of that the event firing code needs to be always compiled in and therefore slowing down the virtual machine even in situations where no debugging facility is needed.
126
127 \subsubsection{Debugging support processes}
128 As mentioned earlier the CACAO JVMTI implementation needs \textit{ptrace} to implement breakpoints and other events. Due to that a parent (debugger) process, that handles traps (\texttt{SIGTRAP}) and other signals, is needed. 
129
130 Such a debugger process needs to be aware of many operating system, library and processor specifics. Because of that, and due to the fact that CACAO runs on several different processor, library and operating system configurations, the decision has been taken to use GNU debugger\cite{gdb} (\textit{gdb}) as debugger process and control gdb with a third process (\textit{cacaodbgserver}).
131
132 \begin{figure}[h]
133 \begin{verbatim}
134                 cacao 
135                    \_  -cacaodbgserver
136                             \_  -gdb
137 \end{verbatim}
138 \caption{Process structure of a running JVMTI session}
139 \label{processstructure}
140 \end{figure}
141
142
143 The gdb and its control process are lunched by need during the creation of a new JVMTI environment and are killed after the last JVMTI environment gets disposed.
144
145 \subsubsection{Event handling with traps}
146 \label{eventhandling}
147 Gdb normally implements breakpoints by using so called trap instructions. These instructions (e.g. \texttt{int3} on i386) are put in the place where the breakpoint has to be fired. On execution of a trap instruction the operating system sends a \texttt{SIGTRAP} signal to the tracing process. At that point the tracing process is able to inspect and change the traced process.
148
149 Setting trap instructions in CACAO JVMTI is a major problem if a trap lays in JIT compiler generated code because there is the need for JIT compiler support to get the appropriate position where to put the trap. The second JIT compiler issue is related to the possibility of the JIT compiler to patch and recompile a method. Such patching or recompilation will overwrite existing trap instructions. The way CACAO deals with these issues is described in section \ref{traps}.
150
151 CACAO JVMTI has to execute the appropriate event callbacks if it gets a \texttt{SIGTRAP}. To accomplish this the controlling process \textit{cacaodbgserver} uses the gdb process to call \texttt{jvmti\_cacao\_generic\_breakpointhandler} from within the current execution thread of the cacao virtual machine. This function executes all enabled event callbacks, for this kind of event, in the current execution thread. It is important to note that during the execution of a callback the execution of other virtual machine java threads is not stopped. To explicitly stop other running threads the JVMTI function SuspendThread has to be called.
152
153 %call
154 % continuing thread execution
155
156 \subsubsection{JLocation format}
157 \label{jlocation}
158 JLocation is the return type of many JVMTI functions and events representing some java bytecode location in the virtual machine. Sun's JVMTI specification\cite{jvmti} leaves the JLocation type intentionally unconstrained. The greatest functionality is achieved with JLocation indicating the bytecode index of a java instruction, but virtual machines, like CACAO, that do not have an appropriate mapping to the bytecode indexing scheme are allowed to use the native program counter or some other representation. This format has to be ``A 64 bit value, representing a monotonically increasing executable position within a method. -1 indicates a native method.''\cite{jvmti}. 
159
160 % mapping - line number
161
162 \begin{table}[h]
163 \begin{center}
164 \begin{tabular}{|l|l|l|}
165 \hline
166 \multicolumn{3}{|c|}{Mapping to JLocation}\\\hline
167 function/event Name & support functionality & available \\\hline
168 \hline
169 Get Stack Trace  & stacktrace &line number \\\hline
170 Get Frame Location & stacktrace & line number\\\hline %  : return the location of the instruction currently executing
171 Get Line Number Table & line number table & line number \\\hline
172 Get Method Location &   line number table  & line number \\\hline
173 Breakpoint & stacktrace  & line number \\\hline
174 SingleStep & stacktrace  & line number \\\hline
175 Exception & stacktrace   & line number \\\hline
176 Exception Catch & stacktrace & line number \\\hline
177 Get Local Variable Table & local variable table and &\\
178                                     & line number table & line number \\\hline
179 Field Access & stacktrace & line number \\\hline
180 Field Modification & stacktrace & line number \\\hline
181 Compiled Method Load & line number table & line number \\\hline
182 \hline
183 \multicolumn{3}{|c|}{Mapping from JLocation} \\\hline
184 \hline
185 function/event Name & support functionality & available \\\hline
186 Set Breakpoint & line number table   & line number\\\hline
187 Clear Breakpoint &  line number table  & line number \\\hline
188 \end{tabular}
189 \end{center}
190 \caption{Needed JLocation mapping}
191 \label{JLocationmapping}
192 \end{table} 
193
194 The decision has been taken to use a JLocation format other then bytecode index and native program counter. As you can see in table \ref{JLocationmapping} all JVMTI function and events could support line numbers as being the JLocation format in the CACAO virtual machine. Therefore line numbers will be used as JLocations. The second column (support functionality) of table \ref{JLocationmapping} specifies the functions and data structures that are needed to get a correct JLocation value.
195
196 \subsubsection{Enabling traps}
197 \label{traps}
198 As described in section \ref{eventhandling}, there are two major issues using traps in JIT compiler generated code. 
199
200 The first issue, concerning the mapping of a JLocation position to a native program counter position, can be dealt with by the JIT compiler, by filling in the line number table with current native program counter values. This is already done by the JIT compiler to support java stack traces. Furthermore the JIT compiler has to mark special positions like method enter/exit, exception throwing and exception catching. Figure \ref{scenariocompile} shows a high level pseudo code of how the JIT compiler can support JVMTI events.
201
202 \begin{figure}[h]
203 \begin{verbatim}
204
205 - compile method
206 - fill in line number table with native pc values
207 - if ((breakpoints or method enter or method exit or
208       exception or exception catch) events are enabled) 
209         call jvmti to set traps with current pc values
210 \end{verbatim}
211 \caption{Scenario: (re-)compile a method}
212 \label{scenariocompile}
213 \end{figure}
214
215
216 The second issue, about overwriting existing traps during a recompilation or patching of an already compiled method, can be dealt with by updating the line number table and special positions before resetting those traps. Figure \ref{scenariopatch} shows a high level pseudo code of how the CACO patcher can support JVMTI events.
217
218 \begin{figure}[h]
219 \begin{verbatim}
220
221 - patch method
222 - update line number table with native pc values
223 - if ((breakpoints or method enter or method exit or
224       exception or exception catch) events are enabled) 
225         call jvmti to reset traps with updated pc values
226 \end{verbatim}
227 \caption{Scenario: patch an already compiled method}
228 \label{scenariopatch}
229 \end{figure}
230
231 This approach moreover has the advantage to allow JVMTI to easily disable some or all traps if they are no more needed.
232
233 \subsection{Implemented Features} % 2
234 As described in section \ref{jvmtifunctions}, JVMTI has many optional funtcions and events. CACAO does not implement all optional JVMTI function and events yet. Table \ref{implementedfunctions} and \ref{implementedevents} show what functions and events CACAO JVMTI supports.
235
236 \begin{table} [h]
237 \begin{center}
238 \begin{tabular}{|l|l|}
239 \hline
240 Function category & Supported functions\\\hline\hline
241 Memory Management& all \\\hline
242 Thread& all \\\hline
243 Thread Group& all \\\hline
244 Stack Frame& Pop Frame and Notify Frame Pop missing \\\hline
245 Heap& only Force Garbage Collection \\\hline
246 Local Variables& none \\\hline
247 Breakpoint& all ? \\\hline
248 Watched Field& none \\\hline
249 Class& Get Source Debug Extension and \\
250         &  Redefine Classes missing \\\hline
251 Object& GetObjectMonitorUsage missing \\\hline
252 Field& IsFieldSynthetic missing \\\hline
253 Method& Is Method Synthetic and \\
254            & Is Method Obsolete missing \\\hline
255 Raw Monitor& all \\\hline
256 JNI Function Interception& all \\\hline
257 Event Management& Generate Events missing \\\hline
258 Extension Mechanism& cacao jvmti has no extended functions \\\hline
259 Capability& all \\\hline
260 Timers& Get Timer Information, Get Time \\\hline
261 System Properties& all \\\hline
262 General& all \\\hline
263  \end{tabular}\end{center}
264 \caption{Supported JVMTI functions in CACAO}
265 \label{implementedfunctions}
266 \end{table} 
267
268
269 \begin{table} [h]
270 \begin{center}
271 \begin{tabular}{|l|c|}
272 \hline
273 Event groups & Supported\\\hline\hline
274 Breakpoint/Single Step & yes \\ % todo
275 Class File Load Hook/Load/Prepare  & yes \\ % to test
276 Compiled Method Load/Unload  & no\\
277 Data Dump Request  & yes \\
278 Dynamic Code Generated  & yes \\
279 Exception/Exception Catch  & yes \\
280 Field Access/Modification  & no \\
281 Frame Pop  & no \\
282 Garbage Collection Finish/Start  & no \\
283 Method Entry/Exit  & yes \\
284 Monitor Contended Enter/Entered  & yes \\
285 Monitor Wait/Waited  & yes \\
286 Native Method Bind  & yes \\
287 Object Free  & no \\
288 Thread Start/End  & yes \\
289 VM Start/Initialization/Death Event  & yes \\
290 VM Object Allocation  & no \\
291 \hline
292 \end{tabular}\end{center}
293 \caption{Supported JVMTI events in CACAO}
294 \label{implementedevents}
295 \end{table} 
296
297 \subsection{Further work}
298 As JVMTI is a huge interface not all functionality is already implemented in CACAO. To further ease debugging of Java programs, support of inspecting and changing local variables should be added. 
299
300 Beside debugging JVMTI is also meant to support profiling which is not supported at all in the current CACAO JVMTI implementation.
301
302