We introduce a dashed arrow with a filled arrowhead to indicate a return ... We extend the notation in the sequence diagram as UML does not define a ... Firstly, a synchronised method is drawn from the calling object to the receiving object.
JACOT: A UML-Based Tool for the Run-Time Inspection of Concurrent Java Programs Hugo Leroux, Christine Mingins and Annya Réquilé-Romanczuk School of Computer Science and Software Engineering Monash University 900 Dandenong Road Caulfield East, Victoria, Australia Telephone: +61 3 9903 1965
{hleroux ,cmingins, arequile} @csse.monash.edu.au
1. Introduction Many software systems nowadays rely on concurrency to achieve greater processing power, to improve human-computer interaction and build real-time applications. However, despite their numerous advantages, concurrent programs are difficult to comprehend, debug and maintain. This is mostly due to their complexity. In a multi-threaded program, there can be multiple flows of control and indeed the same program may result in different output each time that it is executed due to the inherent non-determinism of threads. Run-time inspection allows programmers to analyse and inspect the inner workings of a program during execution. We present Jacot, a tool for run-time inspection whose main objective is to address the challenges associated with understanding the execution of concurrent Java programs. It takes a Java program as input and dynamically visualises its execution. It uses the UML Sequence, Statechart and Activity diagram paradigms, which it extends, as visualisation platform, to inspect the program. We chose UML because it is the de facto standard for modelling object-oriented systems. It is also widely accepted in industry and academia and provides suitable extension mechanisms. This paper is organised as follows. In the next section, we give a brief overview of concurrency concepts in Java. This is followed by a discussion of the UML notations and extensions that we use for our tool, Jacot and how it addresses the concurrency issues. We then discuss the architecture of Jacot and present related work in the field. Finally, we summarise and conclude the paper.
2. Concurrency and Java A program is termed concurrent if the activities performed therein are permitted to overlap in time [1]. Java [2] inherently supports concurrency in the language by defining thread objects. Several threads may execute concurrently within a program at any one time. The integrity (safety) of a concurrent program can be protected by locking the interacting objects therein. However, locking the objects may prevent the program from executing (liveness). Each object in Java possesses a wait queue [1], which contains the wait, notify and notifyAll methods. These methods can be used to synchronise access to objects to improve safety but this is often detrimental to Liveness. Liveness in a concurrent program involves ensuring that resources within the program never fail to execute or become “live”. One common definition of Liveness asserts: “something eventually happens”[3]. The four inter-related cases that may cause liveness failures are contention, dormancy, deadlock and premature termination. A description of these four issues can be found at [4]. Jacot focuses on Liveness concepts in Java and cannot, as currently modelled, depict Safety issues. This is discussed further in [4].
3. The UML Model Jacot is modelled on the UML Sequence, Statechart and Activity diagrams paradigm. We draw on the syntax and semantics of the three abovementioned models to formulate our model. We also extend the notation, particularly the sequence and statechart diagrams, to suit our needs for the run-time inspection of concurrent Java programs. A discussion of the design decisions concerning the model can be found at [4, 5]. In this section, we briefly present the standard notation of the UML models for completeness. We then introduce the extensions to be made to these models. A more detailed discussion of the notation and the constraints of the model can be seen at [6]. Table 1 outlines the functionalities of Jacot in terms of concurrency concepts. We use “STD” to indicate the use of the standard concepts and notations of UML and “EXT”, to indicate extensions made to the language.
3.1 Sequence Diagram We choose the Sequence diagram as it has an explicit time axis and is powerful at demonstrating the interaction between the objects by illustrating the invocations of messages. The combination of the time dimension and message-passing capabilities allow for the interleaving of events to be clearly depicted. Figure 1 depicts the execution of the Callback program in the sequence diagram.
Table 1: Concurrency concepts supported by Jacot UML MODELS
CONCURRENCY CONCEPTS Synchronisation Mutual Exclusion Deadlock Starvation Dormancy Exception
Sequence STD
3 3 3 3 3
Statechart EXT
3 3 3
Activity
STD
EXT
3 3 3 3
3 3
STD
3
3.1.1 Objects The depiction of ordinary (passive) and active objects and their interactions are exactly as prescribed by the UML language [7]. We extend the concept of active and passive objects by introducing a locked object. It refers to an object that has been locked by a thread for the purpose of mutual exclusion on the object. It is depicted similarly to an active object. However it is drawn in the colour of the thread locking the object and it also contains the thread reference drawn in the bottom right corner. Objects are arranged in order of instantiation at the top of the model from left to right. We also depict the object’s “lifeline”; “activation” and destruction (large “X”), exactly as prescribed by UML [7].
3.1.2 Methods Method invocations are also depicted exactly as prescribed by UML [7]. We support the synchronised method call (filled arrowhead), unsynchronised method call (stick arrowhead), self-call (curved arrow) and return from method calls (dashed arrow with stick arrowhead). We introduce a dashed arrow with a filled arrowhead to indicate a return from a synchronised method. We show the exact location of an object creation on the Sequence diagram by using the create stereotype with a message.
3.1.3 Threads We extend the notation in the sequence diagram as UML does not define a rich notation for thread depiction. We depict the creation of threads by adding a wavy symbol to the method creating the thread. Each thread is depicted in a unique colour [4, 6]. We depict thread termination by adding an “9” symbol to the method handling the destruction of the thread. We depict nesting of flow of control in the program as stated by UML [7] and similar to the approach in [8]. However, we do not shade the activation diagram; we highlight (increase brightness) the portion that holds the focus of control [6]. To illustrate mutual exclusion, we follow the approach in [8] and adapt the UML notation to depict the locking sequence of the object by the thread [6]. Firstly, a synchronised method is drawn from the calling object to the receiving object. Secondly, the portion of the activation diagram pertaining to the lock is shaded in the colour of the thread executing. Thirdly, a synchronised return from method call is drawn from the locked object back to the calling object. In addition to the three steps above, the object experiencing the mutual exclusion will be portrayed as a locked object.
3.1.4 Exceptions Exceptions are modelled as signals in UML [7, 9]. However, there is no mention as to what an exception should be in the Sequence diagram. We depict the raising of an exception in the program by drawing a star “Ê” next to the method invocation that raised the exception.
3.2 Thread State Diagram Our Thread State Diagram is adapted from the UML Statechart diagram [7]. It depicts the state of the threads during execution. The Thread State Diagram consists of six states, namely waiting, running, sleeping, waiting on a monitor, terminated and unknown together with an initial pseudo state and a final transition [4]. All the states are interconnected using directed edges drawn in black. Edges are bidirectional between all states except for the terminated state. Edges to the terminated state are unidirectional towards the terminated state because a thread cannot execute further once it is terminated. Threads are depicted as filled circles in the thread colour and include a number inside to indicate the priority of the thread. Each thread also contains such information as the thread reference, the [optional] thread name, the bound object and the relative time spent in that state. This can be accessed by right-clicking on the thread icon. Threads migrate between states as a result of a change in their internal state. When a thread migrates from one state to another, the edge connecting the two is briefly painted in the colour of the thread. Figure 2 depicts the Thread State diagram.
Figure 1: Sequence Diagram
Figure 3: Exception Flow Diagram Figure 2: Thread State Diagram
3.3 Exception Flow Diagram The Exception Flow Diagram is an adapted version of the UML Activity Diagram that depicts the flow of caught and uncaught exceptions during the execution of the program. The main characteristic of exceptions in a multithreaded environment is that the exception progresses up the stack of messages of the thread until it reaches a method to handle it. If none is found, the thread is abandoned and execution continues normally for other threads. This condition alone suggests that exception flow should be depicted separately from the main program flow. We provide some rationale for the choice of Activity diagrams to visualise exceptions in [6]. The exception flow diagram depicts the progression of the exception from the time it is raised until it is either handled by one of the methods in the call stack of its thread or the point of termination of the thread. We depict the start of the exception by a “start state” (a filled circle). Actions performed during the exception flow are shown as action states. These are represented as a lozenge shape [9]. Messages are shown as transitions. Invocations spanning across multiple objects are shown by using swimlanes. These are depicted in the activity diagram as partitions drawn as dashed lines separating columns of the activity
diagrams. We do not use the branching, fork and join concepts of activity diagrams, as described in [9] in our model. The diagram is able to depict the flow of exception but does not yet provide depiction of the type of exception. This will be addressed in future versions although, we believe that the user is more interested with the occurrence of an exception and its cause, than its type. An example of the Exception Flow diagram is shown in Figure 3.
3.4 Visualising Concurrency Concepts Figure 2 shows an example of thread interleaving and mutual exclusion. We can see the interleaving of the threads executing within the “bob” and “sue” objects. Furthermore, the “update” method executing within the “sue” object is an example of a thread being granted exclusive access to an object. We discuss the four liveness issues below.
3.4.1 Dormancy Dormancy is illustrated by monitoring the invocation of synchronisation primitives in the Sequence Diagram together with the activity of the threads executing. This allows the developer to identify the simple case of a wait command not followed by a notification. However, it is also useful in elucidating the more complex synchronisation problem whereby a thread is notified before the wait process has even started. The thread state diagram assists by showing the waiting threads and providing information regarding the time spent in that state.
3.4.2 Starvation The user may conclude that a thread is starved of CPU time by observing long periods of inactivity by the contended thread in the Sequence Diagram. However, Contention is better illustrated in the Thread State Diagram. In the case of contention due to priority, glancing at the pool of waiting and monitor threads should indicate whether the contended thread has a lower priority than other running threads. In the case of a fairness problem causing starvation, we provide useful statistics whereby the user can query the thread and obtain an estimate of the time spent in the above two states.
3.4.3 Deadlock Deadlock is more accurately depicted in the executing program by observing the interleaving of thread invocation, for which the Sequence Diagram is particularly powerful. The occurrence of deadlock can be portrayed in the Sequence Diagram by following the offending threads along the crime trail while observing the locking sequence of objects by threads at differing times during the execution. The order of the locks sequences, the frequency of the locks, the duration of the locks and the activities performed while the locks are in place provide crucial information in analysing the deadlock. The thread state diagram can shed light on the order of transition of the thread state. It can also provide clues about the time spent in different states.
3.4.4 Premature Termination We depict the occurrence of the exception in the Sequence Diagram by drawing a star, next to the offending method. This gives rise to the Exception Flow Diagram. In this diagram, the entire flow of the exception in terms of the objects and methods invocation, the branching and the conditional statements are outlined to the user. The Thread State Diagram will ultimately show the offending thread as terminated.
4. Architecture of JACOT Jacot is based on a four-layer model built on top of the three-layer Java Platform Debugger Architecture (JPDA) [10] architecture as shown in Figure 4. It is modular allowing it to be extensible and accommodate for more views to be added in the future. A detailed discussion of the architecture can be found in [4, 5].
Figure 4: Jacot Architecture
4.1 Platform Java was chosen as the implementation platform for many reasons. Firstly Java offers platform independence. Secondly, Java uses a virtual machine. More specifically the three layers comprising the JPDA architecture provides mechanism to significantly assist in the gathering of events from the program under study. Jacot uses the JDI to obtain traces from the program under study. Thirdly, Java offers a rich graphical interface inbuilt in the language. Finally, our aim is to visualise concurrent Java programs and it seems rather logical to implement the visualisation tool using the same platform. A paper
discussing the implementation can be seen at [5]. Our decision to build from scratch rather than rely on a UML Case Tool was motivated by the fact that Jacot is a prototype and following findings by Mehner who stated: “doing it again, we would probably build our own visualization” [11]. The JPDA suits our basic needs for run-time inspection, albeit some non-trivial dereferencing for representing method invocation parameters and an inelegant and probably inefficient way to obtain owned and contended monitors. We await the release of the Java SDK version 1.4.2 to take advantage of new features from the JPDA for the latter.
4.2 Event Gathering Layer The Event Gathering layer is responsible for requesting and collecting events from the “debuggee” VM. The events are gathered in a “polling” fashion. The tool waits for the “debuggee” VM to place events on the Event Queue. Once an event is generated, it is removed from the queue. Jacot then iterates through the set of events wrapping each event in a message and forwards it to the next layer for processing. These steps are repeated indefinitely until either an event notifying that the debuggee VM has been terminated or the program exits.
4.3 Event Processing Layer The Event Processing layer gathers detailed information about each event. The main function of this layer is to determine the type of the event received and query the JDI for information about the event. We are interested in many types of events [4, 5] and the type of the event further determines what additional information can be gathered. The interested reader is referred to [5] for more information about these events. We identify the objects associated with an event by pairing the object’s name and object’s ID together [5]. We then obtain details of the objects involved in a method invocation by traversing the stack of method calls made by this thread [5].
4.4 View Formatting Layer The “View Formatting” layer is mainly concerned with arranging the information passed on from the previous layer in a coherent manner on the screen. Decisions such as placement location, shape, size, colour, shade are dealt with here. The three diagrams within Jacot handle the formatting of their respective views independently and differently.
4.5 Display Layer The Display layer comprises a dozen classes each responsible for drawing a graphical component on the screen.
5. Related Work JaVis [8, 11, 12] is a tool for visualising and debugging concurrent Java programs using the UML Sequence and Collaboration diagrams paradigms and implemented using the UML Case Tool Together. The main objective and strength of the tool is in the discovery and notification of deadlocks. JaVis shares many of its functionalities with Jacot. Mehner et al [8] extend the Collaboration diagram model to show the dependencies among objects executing within the program. Whilst we agree with their aim, we do not see the need to introduce collaboration diagrams into Jacot. This is because both interaction diagrams are semantically similar, and, in our view, sequence diagrams are more visual, more readable and better able to visualise interactions. Javavis [13] is an educational visualisation tool to support the teaching of object-oriented concepts in Java to novices. The tool is quite similar to Jacot and JaVis with the exception that it does not yet support concurrency concepts. Javavis also uses UML Sequence diagrams as medium for the visualisation. Despite not supporting concurrency, it shows good promise by displaying an object diagram for each active method on the call stack of threads, with interesting navigational features. Jinsight [14] can be regarded as a visual debugger for visualising the run-time performance of Java programs. It does not aim directly at addressing concurrency issues. Instead it is mainly powerful at uncovering memory leaks. One of its views, the Call Tree view, can be used to demonstrate the interleaving of events during the execution. The Histogram view depicts the usage of basic resources such as CPU and memory within the system and could potentially be used to address safety issues, such as data integrity. The Pattern reference view is particularly interesting as it provides some mechanisms for abstraction of the system. Jitan [15] is a text and graphical based environment for concurrent Java programs. Jitan interprets Java programs directly at the source, not at the byte-code level. It depicts object creation, destruction and activity in a flow-chart diagram. It also shows the dynamic locking and synchronisation of threads as well as the status of threads during execution through this flow-chart diagram. We provide a survey of existing UML models that offer mechanisms to model or visualise concurrency in [4].
6. Summary and Conclusion This paper has presented research in a UML-based tool for run-time inspection of concurrent Java programs, called Jacot. Its main objective is to assist the user in understanding challenging new concurrency concepts such as synchronisation, deadlock, dormancy, starvation, mutual exclusion and premature termination. It is based on extended versions of the UML Sequence, Statechart and Activity diagrams paradigm.
We have presented our model based on existing and extended UML notations and commented on its use for inspecting concurrent Java programs at run-time. We also discussed the architecture of Jacot in terms of the platform and the layers comprising it. The first version of Jacot is complete. The next version will support filtering and logging of events. The former should allow us to scale Jacot better, especially within the sequence diagram. The latter should allow us to play, rewind and forward the execution of the program in true post-mortem fashion. Along with the filtering of events, logging is one feature that we believe should be very useful to novice concurrent Java programmers. It could help the programmer extract out some unnecessary details of the execution providing them with the ability to locate which event triggered a change in the state of the objects and threads. We also aim to improve the colour scheme for the thread depiction. We are however aware that the disparity of tones of colours at the lower and upper end of the spectrum is not as distinct as those around the middle. One of our chief longterm objectives, however, is the automated notification of errors as we believe that this will be of tremendous assistance to novice concurrent Java programmers. We believe that Jacot is modular enough to allow the algorithm to be plugged-in the future.
7. Acknowledgements We would like to thank Dr. Christopher Exton for his help, support and invaluable comments during the early stage of the project.
8. References 1.
J. Magee, J. Kramer. (1999), Concurrency : State Models & Java Programs. John Wiley, ISBN: 0471987107, Chichester.
2.
Sun Microsystems. (2001), "JavaTM Standard Development Kit", http://java.sun.com/j2se/1.4.1/
3.
D. Lea. (2000), Concurrent Programming in Java: Design Principles and Patterns. Addison-Wesley, MIT, ISBN: 0-20131009-0.
4.
H. Leroux, A. Requile-Romanczuk, C. Mingins. (2003) "A Conceptual Model for Visualising Concurrent Java Programs Using UML." Technical Report, Report No.: TR2003/140, Monash University, Caulfield East, Australia.
5.
H. Leroux, A. Requile-Romanczuk, C. Mingins. (2003), "JACOT: A Tool to Dynamically Visualise the Execution of Concurrent Java Programs", in J. F. Power et al. (ed.), Proceedings of the Second International Conference on the Principles and Practice of Programming in Java, Kilkenny City, Ireland, Computer Science Press, ISBN: 0954414519, pp. 201-207.
6.
H. Leroux, A. Requile-Romanczuk, C. Mingins. (2003), "A UML Model for Visualising the Execution of Concurrent Java Programs", in Sixth International Conference on the Unified Modeling Language, San Francisco, California.
7.
OMG. (2001), "Unified Modeling Language Specification v.1.4", www.omg.org.
8.
K. Mehner, A. Wagner. (2000), "Visualizing the Synchronization of Java-Threads with UML", in IEEE Symposium of Visual Languages, Seattle, IEEE Computer Society, pp. 199-206.
9.
G. Booch, J. Rumbaugh, I. Jacobson. (1998), The Unified Modeling Language User Guide. Addison-Wesley, 0201571684, Reading Ma, USA.
10.
Sun Microsystems. (2001), "JavaTM Platform Debugger Architecture", http://java.sun.com/products/jpda/.
11.
K. Mehner. (2002), "JaVis: A UML-Based Visualization and Debugging Environment for Concurrent Java Programs", in S. Diehl (ed.), Lecture Notes in Computer Science, vol. 2269, Software Visualization: International Seminar, SpringerVerlag, Berlin, p. 163-175.
12.
K. Mehner, B. Weymann. (2001), "Visualization and Debugging of Concurrent Java Programs with UML", in W. d. Pauw et al. (ed.), International Conference on Software Engineering, Toronto, Proceedings of the Workshop on Software Visualization.
13.
R. Oechsle, T. Schmitt. (2002), "JAVAVIS: Automatic Program Visualization with Object and Sequence Diagrams Using the Java Debug Interface (JDI)", in S. Diehl (ed.), Lecture Notes in Computer Science, vol. 2269, Software Visualization: International Seminar, Springer-Verlag, Berlin, p. 176-190.
14.
W. D. Pauw, E. Jensen, N. Mitchell, G. Sevitsky, J. Vlissides, J. Yang. (2002), "Visualizing the Execution of Java Programs", in S. Diehl (ed.), Lecture Notes in Computer Science, vol. 2269, Software Visualization: International Seminar, Springer-Verlag, Berlin, p. 151-162.
15.
I. Attali, D. Caromel, M. Russo. (2001), "Graphical Visualization of Java Objects, Threads, and Locks", IEEE Distributed Systems online, vol. 2, no. 1.