1 \documentclass{article}%
7 \lstloadlanguages{Java,C}
8 \lstset{basicstyle=\scriptsize, numbers=left, tabsize=4, frame=none, breaklines=true}
9 %-------------------------------------------
10 \newtheorem{theorem}{Theorem}
11 \newtheorem{acknowledgement}[theorem]{Acknowledgement}
12 \newtheorem{algorithm}[theorem]{Algorithm}
13 \newtheorem{axiom}[theorem]{Axiom}
14 \newtheorem{case}[theorem]{Case}
15 \newtheorem{claim}[theorem]{Claim}
16 \newtheorem{conclusion}[theorem]{Conclusion}
17 \newtheorem{condition}[theorem]{Condition}
18 \newtheorem{conjecture}[theorem]{Conjecture}
19 \newtheorem{corollary}[theorem]{Corollary}
20 \newtheorem{criterion}[theorem]{Criterion}
21 \newtheorem{definition}[theorem]{Definition}
22 \newtheorem{example}[theorem]{Example}
23 \newtheorem{exercise}[theorem]{Exercise}
24 \newtheorem{lemma}[theorem]{Lemma}
25 \newtheorem{notation}[theorem]{Notation}
26 \newtheorem{problem}[theorem]{Problem}
27 \newtheorem{proposition}[theorem]{Proposition}
28 \newtheorem{remark}[theorem]{Remark}
29 \newtheorem{solution}[theorem]{Solution}
30 \newtheorem{summary}[theorem]{Summary}
31 \newenvironment{proof}[1][Proof]{\textbf{#1.} }{\ \rule{0.5em}{0.5em}}
35 \title{Assertion support \\for the CACAO Virtual Machine}
36 \author{{Gregor Kaufmann}
38 \\gregor@complang.tuwien.ac.at}
39 \date{January 1, 2008}
47 \section{Introduction to assertions in Java}
48 \subsection{General Introduction}
49 The assertion keyword in Java allows to assert the correctness of assumptions made in a program. It was first introdcuded in JDK 1.2 (see JSR41\footnote{http://jcp.org/aboutJava/communityprocess/review/jsr041/publicDraft.html}). An assertion works on an expression, evaluating to a boolean type, that must be true during the execution of a program (or else the execution halts and an exception gets thrown). Short example: a function that calculates from celsius to kelvin. This function might use an assertion to assure that the calculated value is not below 0.
51 An assertion statement comes in two forms:
53 \item \verb'assert BooleanExpression ;'
54 \item \verb'assert BooleanExpression : ValueExpression ;'
56 The "BooleanExpression" can be any java expression resulting in a boolean value. If this "BoolenExpression" evalutes to false an (unnamed) AssertionError gets thrown. The second form of the assertion statement is used to generate detailed error messages: the value of "ValueExpression" gets passed to the constructor of the thrown AssertionError exception, building a more detailed error message. An assertion statement is equal to: if (BooleanExpression == false) throw new AssertionError(ValueExpression); (without the possibility to easily turn on/off this code at runtime).
59 \item \verb'assert val < 10;'
60 \item \verb'assert val > 99: val;'
61 \item \verb'assert isValid(val): val;'
62 \item \verb'assert val.isEnabled(): val.getStatus();'
66 \subsection{Interpreter options}
67 Assertions can be turned on or off at runtime (turned off by default). The following options for the interpreter are available (\verb'>'JDK1.2 and \verb'>'CACAO-0.98):
69 \item \verb'-ea[:<packagename>...|:<classname>]'
70 \item \verb'-enableassertions[:<packagename>...|:<classname>]'
71 \item \verb'-da[:<packagename>...|:<classname>]'
72 \item \verb'-disableassertions[:<packagename>...|:<classname>]'
73 \item \verb'-esa | -enablesystemassertions'
74 \item \verb'-dsa | -disablesystemassertions}'
76 Detailed explanation of the available options:
78 \item{\verb'-enableassertions/-ea' -- \tiny{Turns on assertions for all non-system/user classes}}
79 \item{\verb'-disableassertions/-da' -- \tiny{Turns off assertions for all non-system/user classes}}
80 \item{\verb'-enablesystemassertions/-esa' -- \tiny{Turns on assertions for all system/non-user classes}}
81 \item{\verb'-disablesystemassertions/-dsa' -- \tiny{Turns off assertions for all system/non-user classes}}
82 \item{\verb'-enableassertions/-ea:my.package...' -- \tiny{Turns on assertions for all classes in the "my.package" package (and all subpackages)}}
83 \item{\verb'-disableassertions/-da:my.package...' -- \tiny{Turns off assertions for all classes in the "my.package" package (and all subpackages)}}
84 \item{\verb'-enableassertions/-ea:Myclass' -- \tiny{Turns on assertions a class named "Myclass"}}
85 \item{\verb'-disableassertions/-da:Myclass' -- \tiny{Turns off assertions a class named "Myclass"}}
87 Note 1: Specifing multiple class/package names is possible.
90 Note 2: The assertion switches -ea/-da/-esa/-dsa are currently not implemented correctly in cacao+classpath (use cacao+openjdk or a patched classpath [see section \ref{see1}]).
92 \subsection{Bytecode of an assertion statement} \label{bytecode}
93 The following example shows how an assertion statement is translated into bytecode.
96 I've compiled the following class with JDK-6.0 (other compilers produce slightly different bytecode).
97 \begin{lstlisting}[language=Java]
99 public static void main(String[] args) {
105 The following bytecode gets produced:
107 \begin{lstlisting}[language=Java]
110 0: ldc\_w #5; //class Test
111 3: invokevirtual #6; //Method java/lang/Class.desiredAssertionStatus:()Z
116 14: putstatic #2; //Field \$assertionsDisabled:Z
119 A static block is used to iniatilizes the boolean variable describing the assertion status of the class "Test".
120 The assertion status, as set by the user/vm for, gets loaded (lines 3,4), and saved into constant\_pool[2] (line 9).
122 \begin{lstlisting}[language=Java]
123 public static void main(java.lang.String[]);
127 2: getstatic #2; //Field \$assertionsDisabled:Z
132 13: new #3; //class java/lang/AssertionError
135 18: invokespecial #4; //Method java/lang/AssertionError."<init>":(I)V
139 The assertion status gets loaded from constant\_pool[2] (line 5), if assertions are disabled the function returns immediatly (lines 6,15). Otherwise, the assertion statement gets evaluated and an AssertionError exception gets thrown (lines 6-15).
142 \section{Implementation of java assertions in CACAO}
144 When I started working on the assertion support for cacao, a basic functionality to toggle assertions on and off was already implemented. It was possible to toggle assertions on and off at a systemwide level, but this only worked when cacao was used together with the GNU classpath classes. Because at least something was already implemented, I decided to start my work on cacao+classpath.
147 Each class implements a method called desiredAssertionStatus that returns the desired assertion status of a class, see section \ref{bytecode} on how this is used by an assertion statement.
150 The desiredAssertionStatus method in java.lang.Class of classpath looks like this:
151 \begin{lstlisting}[language=Java,firstnumber=1216]
152 public boolean desiredAssertionStatus()
154 ClassLoader c = getClassLoader();
157 return VMClassLoader.defaultAssertionStatus();
158 if (c.classAssertionStatus != null)
161 status = c.classAssertionStatus.get(getName());
163 return status.equals(Boolean.TRUE);
167 status = ClassLoader.StaticData.
168 systemClassAssertionStatus.get(getName());
170 return status.equals(Boolean.TRUE);
172 if (c.packageAssertionStatus != null)
175 String name = getPackagePortion(getName());
177 status = c.packageAssertionStatus.get(null);
181 status = c.packageAssertionStatus.get(name);
182 name = getPackagePortion(name);
184 while (! "".equals(name) && status == null);
186 return status.equals(Boolean.TRUE);
190 String name = getPackagePortion(getName());
192 status = ClassLoader.StaticData.
193 systemPackageAssertionStatus.get(null);
197 status = ClassLoader.StaticData.
198 systemPackageAssertionStatus.get(name);
199 name = getPackagePortion(name);
201 while (! "".equals(name) && status == null);
203 return status.equals(Boolean.TRUE);
205 return c.defaultAssertionStatus;
208 The ClassLoader class stores the global assertion status for user classes and the individual status for classes and packages:
210 \item{\verb'boolean defaultAssertionStatus'}
211 \item{\verb'Map<String, Boolean> systemPackageAssertionStatus'}
212 \item{\verb'Map<String, Boolean> systemClassAssertionStatus'}
215 \noindent The VMClassLoader class is a special class that needs to implemented by virtual machines that use the classpath classes.
216 The following methods are used by the ClassLoader to initialize the variables above (in the same order):
218 \item{\verb'boolean defaultUserAssertionStatus()'}
219 \item{\verb'Map<String, Boolean> packageAssertionStatus()'}
220 \item{\verb'Map<String, Boolean> classAssertionStatus()'}
222 See: java.lang.Class\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/Class.java?revision=1.54\&root=classpath\&view=markup}, java.lang.ClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/ClassLoader.java?revision=1.62\&root=classpath\&view=markup}, java.lang.VMClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/vm/reference/java/lang/VMClassLoader.java?revision=1.16.2.18\&root=classpath\&view=markup}
227 \item{Implement the methods: defaultUserAssertionStatus, packageAssertionStatus, classAssertionStatus}
228 \item{Write a function to parse the commandline options}
230 See: src/lib/gnu/java/lang/VMClassLoader.java (section \ref{see1}), src/native/vm/gnu/java\_lang\_VMClassLoader.c (section \ref{see2}), src/vm/assertion.c (section \ref{see3}) and src/vm/assertion.c (section \ref{see4})
232 For cacao+openjdk I could reuse most of the code I wrote for cacao+classpath:
234 The desiredAssertionStatus method in java.lang.Class of openjdk looks like this:
235 \begin{lstlisting}[language=Java, firstnumber=2849]
236 public boolean desiredAssertionStatus() {
237 ClassLoader loader = getClassLoader();
238 // If the loader is null this is a system class, so ask the VM
240 return desiredAssertionStatus0(this);
242 synchronized(loader) {
243 // If the classloader has been initialized with
244 // the assertion directives, ask it. Otherwise,
246 return (loader.classAssertionStatus == null ?
247 desiredAssertionStatus0(this) :
248 loader.desiredAssertionStatus(getName()));
253 The native function called by desiredAssertionStatus0 is JVM\_DesiredAssertionStatus, and that's the only function that had to be implemented by me to make assertions work with cacao+openjdk. I've also corrected the implementation of the JVM\_AssertionStatusDirectives function, which is used by java.lang.ClassLoader.
256 See: src/native/vm/sun/jvm.c (section \ref{see5})
259 \section{Patch overview}
260 \subsection{Changed/New files}
262 \item{\verb'configure.ac'}
263 \item{\verb'm4/assertion.m4'}
264 \item{\verb'src/lib/gnu/java/lang/VMClassLoader.java'}
265 \item{\verb'src/native/include/Makefile.am'}
266 \item{\verb'src/native/jni.h'}
267 \item{\verb'src/native/vm/gnu/java_lang_VMClassLoader.c'}
268 \item{\verb'src/native/vm/sun/jvm.c'}
269 \item{\verb'src/vm/Makefile.am'}
270 \item{\verb'src/vm/assertion.c'}
271 \item{\verb'src/vm/assertion.h'}
272 \item{\verb'src/vm/vm.c'}
273 \item{\verb'src/vmcore/class.c'}
274 \item{\verb'src/vmcore/class.h'}
275 \item{\verb'src/vmcore/linker.c'}
276 \item{\verb'src/vmcore/loader.c'}
277 \item{\verb'configure.ac'}
280 \subsection{configure.ac}
281 Added configure option "--enable-assertion" (turned on by default).
283 Most of the assertion code will be turned off if this switch is disabled.
285 Actual configure logic is in m4/assertion.m4.
287 \subsection{m4/assertion.m4}
288 Added autoconf logic to enable/disable building of assertion support.
290 \subsection{src/lib/gnu/java/lang/VMClassLoader.java}
292 Replaced the dummy implementations of:
294 \item{\verb'defaultAssertionStatus'}
295 \item{\verb'packageAssertionStatus'}
296 \item{\verb'classAssertionStatus'}
301 \item{\verb'defaultUserAssertionStatus'}
304 \noindent This function returns the user assertion status. Due to incorrect handling of user/system assertion status in GNU classpath\footnote{http://www.gnu.org/software/classpath/}, enabling (default) system assertions will also enable assertions in all user classes (a patch\footnote{http://www.mail-archive.com/classpath-patches@gnu.org/msg10400/assertion\_cp.patch} to fix this behaviour was submitted in August 07).
306 Actual implementations now call into native code to get status.
308 \subsection{src/native/include/Makefile.am}
311 \item{\verb'java_util_HashMap.h'}
312 \item{\verb'java_util_Map.h'}
314 \noindent Headers needed to allow construction of Map/HashMap in native code.
316 \subsection{src/native/jni.h}
319 \item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
321 \noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
323 \subsection{src/native/vm/gnu/java\_lang\_VMClassLoader.c}
325 This file holds native implementations of the VMClassLoader for GNU classpath.
327 The following functions were added/replaced:
329 \item{\verb'Java_java_lang_VMClassLoader_defaultUserAssertionStatus'}
331 \noindent Native implementation of VMClassLoader.defaultUserAssertionStatus. This function returns the default user assertion status of the system (user\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
333 \item{\verb'Java_java_lang_VMClassLoader_defaultAssertionStatus'}
335 \noindent Previous implemention was replaced. Native implementation of VMClassLoader.defaultAssertionStatus. This function returns the default assertion status of the system (system\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
337 \item{\verb'Java_java_lang_VMClassLoader_packageAssertionStatus0'}
339 \noindent Native implementation of VMClassLoader.packageAssertionStatus. Builds and returns a HashMap containing key and value pairs of packagenames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
341 \item{\verb'Java_java_lang_VMClassLoader_classAssertionStatus0'}
343 \noindent Native implementation of VMClassLoader.classAssertionStatus. Builds and returns a HashMap containing key and value pairs of classnames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
345 \subsection{src/native/jni.h}
348 \item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
350 \noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
352 \subsection{src/native/vm/sun/jvm.c}
354 This file holds various native implementations needed by OpenJDK\footnote{http://openjdk.java.net/}.
356 The following functions were added/replaced:
358 \item{\verb'JVM_DesiredAssertionStatus'}
360 \noindent Dummy implementation was replaced. Returns the desired assertion status for a given class. Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
362 \item{\verb'JVM_AssertionStatusDirectives'}
364 \noindent Previous implementation was incomplete. Builds and returns an AssertionStatusDirectives object. This object contains the names of all packages and classes and their assertion status.
366 \subsection{src/vm/Makefile.am}
367 Added (optional) building of the assertion module (assertion.c/assertion.h). Will only be built if ENABLE\_ASSERTION is defined (--enable-assertions=yes).
369 \subsection{src/vm/assertion.c}
371 This file handles the various assertion commandline options (-ea/-da/-esa/-dsa).
373 \subsection{src/vm/assertion.h}
375 Defines the following global variables:
376 \begin{lstlisting}[language=C,firstnumber=46]
377 extern list\_t *list\_assertion\_names;
379 This variable stores class/package names and their assertion status.
380 \begin{lstlisting}[language=C,firstnumber=47]
381 extern int32\_t assertion\_class\_count;
383 This variable stores the amount of classnames specified on the commandline.
384 \begin{lstlisting}[language=C,firstnumber=48]
385 extern int32\_t assertion\_package\_count;
387 This variable stores the amount of packagenames specified on the commandline.
388 \begin{lstlisting}[language=C,firstnumber=49]
389 extern bool assertion\_user\_enabled;
391 This variable stores the systemwide user default assertion status.
392 \begin{lstlisting}[language=C,firstnumber=50]
393 extern bool assertion_system_enabled;
395 This variable stores the systemwide default assertion status.
397 Defines the following functions:
398 \begin{lstlisting}[language=C,firstnumber=54]
399 void assertion\_ea\_da(const char *name, bool enabled);
401 This function is used to initialize the variables described aboved.
403 \subsection{src/vm/vm.c}
404 Handling of assertion commandline options was added/changed. Package and classname parsing is handled by src/vm/assertion.c (assertion\_ea\_da function).
406 \subsection{src/vmcore/class.c}
407 Added class\_java\_util\_HashMap
409 \subsection{src/vmcore/class.h}
410 Added class\_java\_util\_HashMap.
412 \subsection{src/vmcore/linker.c}
413 Added linking of class\_java\_util\_HashMap.
415 \subsection{src/vmcore/loader.c}
416 Added loading of class\_java\_util\_HashMap.