Elucidate : A Tool to Aid Comprehension of Concurrent Object Oriented Execution Dr Chris Exton Monash University School of Network Computing Melbourne, Australia
[email protected] The aim of the Elucidate project is to design and develop an interactive tracing system to expedite the students' comprehension and understanding of concurrent object oriented program execution. This paper examines Elucidate, its application, and its value as a pedagogical aid. An extended example is provided which details a specific scenario that utilises Elucidate. Also included is a summary of how Elucidate addresses difficult areas of comprehension such as non-determinism, livelock, deadlock and Inheritance in concurrency [7].
•A b s t r a c t
The adoption of concurrent programming techniques into mainstream system development has brought with it a problem in software comprehension. Stepping through the code is no longer adequate to ensure a student's understanding of how a concurrent program will execute. Elucidate attempts to rectify this inadequacy by giving the student the ability to dynamically explore the various threads of execution and event order of an executing concurrent program. The student can gain an understanding of the threads of control and how they relate to classes, object instantiation, destruction and method invocation. Elucidate adds a layer of abstraction that is capable of clearly exhibiting to the student many of the underlying problems associated with concurrent programming. 1
2
Concurrency and Object Orientation
The object oriented paradigm is well suited to concurrency, with its dual focus on modularity and encapsulation. However, the need for concurrency has increased the level of awareness required from students; aside from understanding the non-concurrent aspects of object oriented programming, the complex nature of inter-object relationships during concurrent execution must also be understood. Developing programs to function in a concurrent object oriented environment is complex and so prone to error. There is a lack of effective tools that aid student comprehension of how parallel execution relates to classes, objects, methods, and the semantics of normal nonparallel execution.
Introduction
Concurrent programming is emerging as an important area in the development of software for application systems. For many computer science degrees concurrent programming is increasingly becoming an essential part of the undergraduate curriculum [4]. This movement was supported by the Association for Computing Machinery (ACM) as part of its Curriculum 91 recommendations in which it advocated introducing distributed and parallel programming constructs into the undergraduate study curriculum. As part of implementing a subject on concurrency it was observed that there was a lack of support for students in this area during the comprehension and analysis steps of cognitive learning, as described by Bloom [2], as many of the mechanisms students had established for non-concurrent programming techniques did not migrate well to the concurrent equivalent.
Dijkstra stated in 1968 in his famous letter to the ACM [3] that "our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed". This is of particular importance when considering concurrent programming, as for a student to understand concurrent object oriented software, it is essential that he or she must develop a competent cognitive model of how an executing process evolves in relation to time. Developing such a temporal model of understanding is not easy.
Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page, To copy otherwise, to republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. ITiCSE 2000 7/00 Helsinki, Finland © 2000 ACM 1-58113-207-7100/0007_. $5.00
For non-concurrent environments such a model is often developed by extracting an understanding directly from the source code, or by using various static diagrammatic representations such as UML and Petri Nets.
33
3
Design Criteria
output. The generated output had to encompass the required information, to both highlight the concurrent and dynamic aspects o f concurrency while also retaining an appropriate level of abstraction.
Ben-Ari [1] states that "when teaching concurrent and distributed programming, it is extremely important that you demonstrate to students the strange behaviour that such programs can show". Elucidate was designed to address this requirement. /~D:~java Elucidate RunDualCounter Executing RunDualCounter A=I B=I A=2 A=3 A=4 B=2 B=3 B=4
The level of abstraction was an important design consideration; too much could see the student losing the ability to easily relate the generated output to their program whilst not enough would result in an information overload with the student getting lost in detail. After much consideration the following events were considered to provide the best balance between abstraction and detail: method entry; method exit; both caught and uncaught exception generation; object construction; object destruction, thread creation and thread termination.
"~
-~-~
Target Program
Essentially Elucidate was developed to dynamically represent an executing multi-threaded program to aid student comprehension and understanding of concurrent object oriented concepts and behaviour, with which students are known to have difficulty. Operation of the user
Program Output J~ Figure 3. The Elucidate implementation architecture
class DualCounter extends Thread { String name; int count = 0;
It was also considered important that the observed code would not require any special modification as a prerequisite to its observation using Elucidate. This meant the student was not required to add any extra method invocations or display statements to their existing code. It was felt that any such modification to the observed code may add complexity to an already complex program. In addition to this unwanted complexity, the extra effort involved in attaching and understanding a new set of interfaces on top of the already feature rich development environments would increase the student's workload and discourage usage of the Elucidate system.
D ualCounter(Std ng i nName) { name = inName;
}
public void run() { for (int i =1; i < 5;i++) System.out.prinUn(name+" = "+ inc0);
}
int inc0 { return ++count;}
Static design representation, program compilation, development environments and source code editors were all considered outside the scope of reference for the Elucidate project and are handled elegantly by tools such as BlueJ [6], Sun's JDK and XEmacs.
class RunDualCounter { public static void main (Stri ng args[]) { DualCounter A = new D ualCounter("A"); DualCounter B = new DualCounter("B");
A.start0; }
}
Elucidate 1 Output
II
Figure 1. Example output
}
Elucidate
B.start0;
It was decided that passive dynamic tracing satisfied the majority of the design criteria and so Elucidate was designed to be a passive dynamic tracing tool. In this sense, passive referred to the fact that it tried to have a minimal (or no) effect on the observed program execution output (see Figure 1) and required no modification to the observed program's source code (see Figure 2).
Figure 2. Source of observed program interface needed to be intuitive and effortless so as not to hinder or obscure the students' access to the generated
34
Issues such as flexibility, extensibility and portability took clear precedence over speed. Speed was not considered important as in most cases the programs that the students wished to observe were relatively small.
4
easily bring the concept to life. It is a simple matter of the student observing an ordered list of interleaved events generated from multiple threads. This can easily be observed using Elucidate as it provides line number and thread names for every generated event. With the traced output displayed, the student may re-execnte the program and compare the different interleaving o f two separate executions of the same program. This enables the student to start making conjectures as to possible causes. Once the concept of interleaving has been clarified, several assertions can be unequivocally made.
Implementation Considerations
Elucidate uses the Java Platforra Debugger Architecture (JPDA) [5] to monitor byte-code execution. This is accomplished by the Elucidate system creating a separate Java Virtual Machine (JVM) for the execution of the observed program (see Figure 3).
5.2 Deadlock and Livelock Deadlock and livelock are notoriously difficult errors to locate as they are often moving targets. Thus a student may place a series of display statements to narrow down the problem area but the deadlock may occur at another location on the next execution of the program. Elucidate can shed light on where deadlock or livelock occurred by keeping a trace of the events that lead up to the scene of the crime. Once the sequence of events that occurred prior to deadlock or livelock has been clarified, the student can then appreciate many of the reasons for structure and a more formal approach to concurrent system development. In fact, the generated output may be presented as a puzzle without first defining the problem.
I.:.'~'.!: ...................................im'!'~ ......... ~inlt~ imaln RunDualCounter DualCounter
imaln • irun
imaln j iThread-O
IDualCounter
irun !Thread-1 1.................................................i......................
DualCounter
i lnc
iThread-1
[14
iinc , DualCounter [inc .............................................i........ DtlalCounter ilnc
i'Tl~read-0
t14
DualCounter
Thread-1
,DualCounter
ilnc
Thread-1 IThrea¢l-0
i14 14
DualCounter Iin¢ !Thread-0 ................................................................................................ m............................................... '1........ DualCounter Thread-1 tinc
14
OualCounter i inc ~Thread-O ................................................ L,................................. DualCounter i lnc ~Thread-1 ...............................................I ..............................................................................................
14
5.3 Exception Handling Migrating themes, procedures, or patterns from the sequential world to the parallel and distributed worlds of software construction have often been problematic; exception handling is no different. In a sequential program, the semantics of exception propagation and handling are clearly defined and simple: an exception will propagate by winding back the stack until a handler is found to catch the exception; if no handler is found, then the process is terminated. Although the implementation of exceptions may be well understood in a non-concurrent language environment, the understanding of exception handling behaviour is often not considered when dealing with a multi-threaded scenario. Concurrent programming introduces some complications over the traditional implementation of exception handling.
14
14
Figure 4. Elucidate output fi'ame Once the program to be observed is executed under Elucidate, it behaves as normal, creating the same windows and frames as it would outside the Elucidate environment with the exception of an additional Elucidate frame for each execution trace (see Figure 4). The additional Elucidate frames contain an inventory of events such as method entry, method exit, exception generation, object construction and object destruction. The line number, thread name and a graphic depiction is included for each of these events. It was felt that such a graphic depiction of events would facilitate the students' ability to identify particular event types easily.
5
In many parallel environments, when an exception is raised during the execution of a thread and the thread fails to handle the exception, the thread is abandoned without further effect. The process continues execution and any notification of the lost exception is left up to the prograrmner to implement explicitly, as is the case with C++, Ada 95 and Java. Elucidate chronicles the generation of the exception and follows its progression recording the line number and thread name until the the exception is caught, or the eventual death of the thread. This provides
Extended Examples
5.1 Interleaving Interleaving is a difficult concept for many students to grasp. This concept is one of the keys to understanding concurrent execution. Dynamic tracing can be used to quite
35
students with an understanding of exception behaviour in a multi-threaded environment.
[3] Edsger W. Dijkstra, GO TO statement considered harmful, Communications of the ACM, (March 1968), Vol. 11, No. 3, 147-148.
5.4 The Concurrency and Inheritance To many uninitiated, the combination of concurrency and inheritance could almost seem natural. However, there exist subtle and yet important semantic conflicts between the two. It has been shown that the inheritance of concurrency constructs can result in the need for non-trivial class redefinition [8]. This means that the programmer will quite often need to investigate the implementation details of various superclasses in order to incorporate the necessary redefinitions into a subclass.
[4] Feldrnan, M.B., Bachus, B.D, Concurrent Programming CAN be introduced into the LowerLevel Undergraduate Curriculum, SIGCSE Bulletin, (September 1997), Vo129, No 3. [5] Java Platform Debugger Architecture. Online. Internet. [November 19, 1999]. Available WWW: http://j ava.sun.com/products/jpda/ [6] Ktilling, M. The Design of an Object-Oriented Environment and Language for Teaching, PhD thesis, (April 1999), Basser Department of Computer Science, University of Sydney.
If the synchronisation code is inconsistent with the constraints then a semantic error such as deadlock may arise at run-time. Elucidate facilitates a means to observe this error as it provides the method name, class name and line numbers that were executed directly before the associated deadlock occured.
6
[7] Lee, D. Concurrent Programming in Java: Design principles and patterns, (November 1999), 2nd. Edition, Addison-Wesley. [8] Matsuoka, S. and Yonezawa, A. Analysis of Inheritance Anomaly. Object-Oriented Concurrent Programming Languages in Research Directions in Object-Based Concurrency, (1993), MIT Press.
Conclusions and FutureWork
This paper described research on the design and implementation of a program tracing and visualisation system, called Elucidate, for concurrent object oriented program comprehension. The major goal of the Elucidate project is to provide more expressive and flexible facilities for teaching the structures and patterns of concurrent object oriented behaviours such as deadlock, livelock, synchronisation, non-determinism and exception handling as much as possible in a language implementation independent manner. There is still much work to be done to dynamically represent all aspects of an executing multithreaded program using Elucidate. Issues such as flexibility, extensibility and portability took clear precedence over speed, however speed may become a central consideration for the observation of larger systems if this is required in the future. Scalabilty is also an issue as large systems may contain thousands of threads and classes whilst generating millons of events, Work is under way to introduce both exclusion and inclusion filtering for threads, event types and classes. This will allow Elucidate to faciliate extremely large existing systems whilst providing a means to remove unnecessary detail.
References [1] Ben-Ari, M. Distributed algorithms in Java, 2nd SIGCSE/SIGCUE Conference on Integrating Technology into Computer Science Education, (1997), Uppsala, Sweden, 62-64. [2] Bloom, B. S. (Ed.). Taxonomy of educational objectives : The classification of educational goals, Handbook 1: Cognitive domain. (1959). New York: David McKay Company.
36