Dominic Cooney [HREF1], Centre for Information Technology Innovation [HREF2], Queensland University of Technology [HREF3], 128 Margaret St., Brisbane, Queensland, 4000. d.cooney@qut.edu.au
Paul Roe [HREF4], Centre for Information Technology Innovation, Queensland University of Technology. p.roe@qut.edu.au
The occasional connectivity and limited bandwidth of mobile computing scenarios make remote execution schemes such as Java RMI or remote data manipulation schemes such as Linda brittle and infeasible. Mobile agents can overcome these problems by moving computations to the data they require, however most mobile agent middlewares do not provide programmers good abstraction from the migration mechanism. We present a new framework for writing mobile software applications with stateful mobile processes. Stateful process mobility is induced by preprocessing byte-code, with little need for programmer intervention. The framework has been reused in delivering location-based services; in mobile applications that can be beamed between handled devices via infrared; in distributed, parallel Web service implementations; and in grid computing. In this paper we describe a new application, mobile stateful applets, as an illustrative use of the framework. In this application scenario, running applets can be moved between Web sites, browsers and handheld devices in a stateful way without placing any extra security demands beyond ordinary applets.
Encapsulating a distributed computing discipline in middleware enables reuse and frees practitioners to focus on their problem domain. Two typical middleware abstractions are complete location transparency, as in distributed object middleware like Java RMI [12], and data shared via a common pool, as in Linda. Mobile, distributed computing creates new challenges: Physically mobile devices often do not have the stable network end points synchronous remote execution schemes such as Java RMI require; nor do mobile devices have the network capacity to do data manipulation via a centralised repository such as a Linda tuple space.
Mobile agents address bandwidth and connectivity problems by moving a computation to the data it requires. Many mobile agent middleware systems such as Voyager [10] and Aglets [7] provide a broad range of services such as security, communication, life-cycle management and events. However few truly deliver mobile computations. Instead, these middleware systems require the programmer to stop any running threads before the computation can be moved to a different host. Some middleware systems, such as Jini [13], unabashedly embrace this 'mobile code plus data' approach. The limitation of this approach is that typical programming devices such as function calls and loops become tedious to use, because all of these constructs must be torn down when a computation needs to move, and manually reconstituted when the computation resumes.
We have designed a framework that explicitly supports process migration. This relieves practitioners from having to split the implementation of functionality across multiple methods. Instead, loops, recursion and structured exception handling can be used normally. This paper describes the design and implementation of the process migration framework; how the framework can be specialised to particular network transports to create process-orientated middleware; and how such middleware can be used in mobile computing scenarios. The framework has been successfully bound to a variety of network transports, including HTTP, SOAP Web services, IrDA and TCP. As a result, the framework has found use in a number of mobile applications such as distributed, concurrent Web service implementations [3]; location-sensitive service delivery [14]; and shareable, stateful applets (described in Section 2). We focus the discussion around the latter application, which we call the Pinboard.
The Pinboard hosts mobile applications: software applications that are not tied to a particular host during execution, but instead can be moved around by the user or move autonomously because of the application logic. Execution is transferred to the new host in a stateful way. Mobile applications may or may not be physically mobile, in the sense that they run on handheld devices or mobile phones. Our current contribution supports mobile applications that run on desktop PCs, handheld devices, or both. We envisage usage scenarios for mobile applications such as moving unfinished work in a text editor from a desktop PC to a laptop that is subsequently taken on the road.
Mobile applications delivered via the Pinboard using our framework run on the client with the same level of trust as an ordinary applet. These mobile applications are not tamper-proof but tamper-agnostic because the downside risk of malicious mobile applications is limited by the fundamental security guarantees of the platform. Since all code is untrusted, mobile applications require no complex trust relationships that could be obstacles to adoption.
The Pinboard supports distributing and sharing mobile applications between desktop PCs and handheld devices. How desktop PC users interact with the Pinboard is described in Section 2. Mobile application middleware such as the Pinboard reuse and extend the mobile application framework. The middleware developer must mediate between mobile applications and the network to transfer running applications to their desired host. The mobile application framework provides process and data persistence services to support this. The implementation of process and data persistence is discussed in Section 3.
Independent mobile application developers consume some elements of the framework during application development. The mobile application framework lets developers view mobility as a 'black box,' and can move a running application to a new host with a single method call. How the framework surfaces mobility as a library is described in Section 4.
Lastly, middleware must provide a host program to start mobile applications and service requests. Section 5 describes how middleware such as the Pinboard provide a host program. We conclude with some evaluative remarks, related work and future work in Section 6.
The Pinboard is a Web application that supports distributing and sharing simple mobile applications. One such application, Sketch, is illustrated in Figure 1. Sketch lets the user scrawl on the client area of a form using the mouse. The Pinboard hosts a number of applications, including Sketch, a simple text editor, a survey application called Pull Polling, and a visualisation of the Towers of Hanoi.
The Towers of Hanoi is a particularly good demonstration of the benefits of our framework, for two reasons: Firstly, the Towers of Hanoi application is multithreaded, with one thread computing the solution to the puzzle, and another thread rendering the intermediate results to the user. With typical mobile object middleware, the programmer would be required to explicitly manage the threads. In our framework, the programmer is completely alleviated of this duty. Secondly, the natural method of computing the solution to the puzzle involves deeply recursive function calls. With typical mobile object middleware the programmer would be required to explicitly simulate the call stack in order to persist and restore the state of the computation. In our framework, the programmer can use ordinary loops and recursion.
Some applications support both desktop PCs and handheld devices. Figure 2 shows Pull Polling running on the handheld Pocket PC.
To use the Pinboard from a desktop PC, a user opens the Pinboard Web site with a browser. The user can choose one of these applications by clicking on a link. When the user clicks on the link to an application, the application is downloaded to the user's computer via the browser. The application opens and runs like a desktop application, with some security restrictions. (Security is discussed in Section 5.1.)
When the user has finished interacting with a mobile application, they can close the application to terminate it. Or they can 'put it away' by uploading the running process to the Pinboard Web site. There it is 'pinned' and it can later be retrieved and used by the same user or a different user. When the program resides on the Web server it does not run, but instead lies dormant until it is downloaded again; see Figure 3.
The user can retrieve a pinned program by clicking on the link to it. Again, the application is downloaded to the user's computer via the browser. The program resumes executing at the same point as before it was pinned. It may have even previously been executing on a different user's computer.
The Pinboard handles programs and the data for a particular instantiation separately; the two are only combined when requested by a user. The details of this mechanism is described in Section 5. When a user pins a mobile application to the Pinboard, only the data describing the application's state is transferred to the Pinboard (transferring the code back to the Pinboard would be redundant, anyway: the code was originally retrieved from the Pinboard.) The implication of this is that a malicious user willing to forge the state of an application can only influence the behaviour of the application to the extent that the static code of the application supports such a behaviour.
The mobile applications hosted by the Pinboard are similar in some respects to Java applets. However the key difference is that applets can not update themselves on the server [16]. The mobile applications are more akin to mobile agents: they are uniquely identifiable, continuously executing processes that can autonomously move between hosts in a stateful way. Unlike mobile agents, the mobile applications' 'hops' are predetermined to either be to or from a specific pinboard, however other uses of the framework employ peer-to-peer hops between mobile devices via infrared, and another between federated Web servers via SOAP [3].
The mobile application framework provides two core services: process persistence and data persistence. This section examines how these services are implemented.
The mobile application framework provides a process persistence service. Threads started within the framework can be 'unwound' at the request of one of the threads. As threads unwind, their state is externalised. Each thread can be restarted later.
The middleware developer uses the process persistence service in concert with the data persistence service to implement process mobility: by persisting the data describing the state of each thread and sending it across the network, processes can effectively be moved from one computer to another.
Mobile applications must cooperate with the process persistence service at runtime. The mobile application framework provides a program, Mobilize, that mobile application developers can use to automatically insert the code necessary to cooperate with the process persistence service. Mobilize disassembles programs using Reflection, and accesses byte code using a third-party library [11]. Code to save and restore the state of a method call is woven into the method body. A method call's actual parameters, local variables, evaluation stack and point of execution constitute the method call's 'state'. Mobilize implements a simple discipline of inserting code to save or restore the state at method calls, method returns, and backwards-branching instructions.
For example, here is a C# method that computes factorial:
static int Fact(int n)
{
return n == 0 ? 1 : (n * Fact(n-1));
}
This is compiled to the following Common Intermediate Language (CIL) [4] code:
ldarg n
brzero One
ldarg n
ldarg n
ldc.i4 1
sub
call int32 Fact(int32)
mul
br Fin
One: ldc.14 1
Fin: ret
The preprocessor would insert code at the following points:
// Preamble: if unpacking,
// restore state and continue
ldarg n
brzero One
ldarg n
ldarg n
ldc.i4 1
sub
// If should pack up, save
// state and return prematurely
call int32 Fact(int32)
// If packing up, save state
// and return prematurely
mul
br Fin
One: ldc.14 1
Fin: // If should pack up, save
// state and return prematurely
ret
This code is inserted automatically, however the programmer must be aware that location-sensitive resources such as files could apparently 'disappear' in the middle of a method body as the result of migration. Anything that is not able to be persisted robustly (see the next section) is liable to be unstable.
The programmer can delimit critical sections of code by programatically 'locking' the thread's location. In this situation the thread state will not be saved until control exits the critical section. Any migration requests made within the critical section will be delayed until the critical section is exited. Critical sections extend over the dynamic call stack: Polling code in called methods see a 'shadowed' result so that the methods do not return prematurely.
Because the effect of arbitrary critical sections can complicate mobility, most critical sections are limited to small methods that manipulate local resources. For programmer convenience, the framework also supports declarative attributes to delimit these methods. For example, the C# method to slurp the contents of a text file into memory is (assuming reading the file is allowed):
[Atomic]
string SlurpFile(string name)
{
using (TextReader r = File.OpenText(name))
{
string s = r.ReadToEnd();
r.Close();
return s;
}
}
Note the Atomic metadata attribute on the method declaration. This metadata is consumed by the preprocessor and replaced with the equivalent imperative code to lock and unlock the thread's location.
For data persistence, the mobile application framework provides a library called Pickle. The 'pickling' process walks an object reference graph, converting objects to a binary representation, and writes them to a buffer. An object reference graph can be recreated by 'unpickling' the binary representation. Pickling and unpickling preserves object identity within a reference graph.
Pickle provides the same functionality as the .NET Framework's serialisation facility, which is not available on handheld devices. Pickle is not as sophisticated as .NET Framework serialisation and requires more work on the part of the mobile application developer. These limitations are because the .NET Framework's serialisation facility is afforded special status with the Common Language Infrastructure (CLI) which allows instances of types to be created without being initialised by their constructors. In contrast, Pickle runs as ordinary code, so the programmer must provide a constructor that the Pickle library can call, such as:
public MyType(PickleToken token) { }
Because objects may contain ultimately circular references, the constructor can't initialise the instance at this point, so typically these constructors will not contain any initialisation code. To ensure that using Pickle does not interfere with a type's no-argument constructor, these constructors take a PickleToken argument. PickleTokens contain no data, but serve to differentiate the static signatures of constructors.
For actually persisting and restoring instances, programmers must implement the IPickleable interface on their types. This interface implies two methods, GetObjectData and SetObjectData, which are used to persist and restore the internal state of an object. The implementation of these methods is quite straightforward. For example, a persistable LinkedList class is:
public class LinkedList : IPickleable
{
object head;
LinkedList tail;
public LinkedList(object head,
LinkedList tail)
{
this.head = head;
this.tail = tail;
}
public LinkedList(PickleToken t) {}
public void GetObjectData(PickleWriter w)
{
w.Write(head);
w.Write(tail);
}
public void SetObjectData(PickleReader r)
{
head = r.Read();
tail = (LinkedList) r.Read();
}
// other LinkedList operations
}
The Pickle library has built-in support for persisting and restoring basic types (such as strings, arrays and numbers). Pickle readers and writers can be augmented with surrogates to persist and restore other types that do not implement IPickleable (such as collections and forms).
This section examines the framework from the perspective of a mobile application developer, and considers how the functionality the framework provides is consumed.
The mobile application framework allows mobile application developers to view mobility as a 'black box.' Mobile applications can be developed in mainstream programming languages. We use C# and VB.NET because our prototype implementation targets the .NET Framework, however our design is equally applicable to Java. The mobile application framework also levers the .NET Framework's support for events, and the extensible metadata system, in surfacing mobility as a library developers can interact with.
The library is chiefly organised around mobile contexts. At runtime, a mobile context wraps and augments a thread. The information a mobile context associates with a thread is mostly significant to other elements internal to the library. Importantly, a mobile context is transparent to the mobile application developer.
The developer can, however, query the mobile context to get access to framework functionality supporting mobility. This functionality allows the program to:
Mobile applications can request execution be transferred to a new host by invoking the Migrate method on the mobile context. This request is observed by the state saving and restoring code in every thread. Interpreting the parameter to Migrate to realise the request is up to the mobile application's host program, which is some code related to the Pinboard in our case. Host programs are described in Section 5.
The final piece of functionality a mobile context provides is to lock and unlock the mobility features (see Section 3.1.) A thread can lock the mobile context, which delays any requests to transfer execution until the context is unlocked again. A thread may want to lock the mobile context when it is dealing with a resource that can not be transferred to a new host.
Mobile application developers use the Mobilize program, described in Section 3.1, to allow their applications to cooperate with the mobile application at runtime. The stages in preparing a mobile application with Mobilize are outlined in Figure 4. First, the programmer writes the mobile application in their chosen language. The program is compiled. As a final preparatory step, the executable is processed with Mobilize. Mobilize inserts code into the program executable to interact with the runtime support library. We call the preprocessed executable the migration-sympathetic program. How middleware supplies a mobile context to a migration-sympathetic program is discussed in the next section.
This section considers reusing the framework from the point of view of the mobile application middleware developer. Middleware must provide a host program to wrap mobile applications. This section closely examines the Pinboard's host program. The mobile application framework has also been used in a host for Pocket PCs that sends and receives applications via a SOAP Web service; a host that transfers mobile applications between desktop PCs via TCP; a host for peer-to-peer application sharing on Pocket PCs via infrared; and a Web service that transfers mobile agents via Web services, to implement Web services.
In general, a host program is responsible for wrapping the runtime part of the mobile application framework, and providing the means by which a mobile application is started. When starting a mobile application, the host program:
These steps are illustrated in Figure 5.
When the mobile program stops executing, whatever the mobile program specified in its call to Migrate (see Section 4) is returned to the host program, along with some data describing the state of each thread at the point at which execution of the program stopped. The onus is on the host program to transfer this data to the next host. Typically, the parameter supplied to Migrate is a URL pointing to the next desired host.
The framework supplies the runtime support library, but cannot supply a generic host program because how the host program loads a mobile application, and transfers its state between hosts, varies depending on the application. For example, the Pinboard's host program must:
The Pinboard dynamically generates a small bootstrap host program for each pinned program that performs these tasks.
Once the bootstrap program starts executing on the client, it reconnects to the Pinboard via a Web service and downloads the data describing the state of the mobile application. It then transfers control to the mobile application. When the mobile application stops executing and control returns to the host, it posts the data describing the application's updated state back to the Pinboard Web service.
Since using the Pinboard involves loading code over the Internet, security is of utmost importance. The bootstrap program and mobile application framework are designed to require very few permissions. This principle of designing for relatively little trust extends from the overarching pinboard metaphor to particular implementation details.
The pinboard metaphor effectively prevents applications from being directly transferable from one desktop PC to another; such direct communication is usually only permitted in trusted environments. At the implementation level, our Pickle object persistence library is a replacement for the .NET Framework's serialisation facility. Pickle provides the same essential functionality as .NET Framework serialisation, however it does not require the SerializationFormatter permission that .NET Framework serialisation requires. The SerializationFormatter permission usually isn't available to untrusted code. Likewise, the programmer must supply explicit data reading and writing methods for pickleable types, because a generic solution relying on reflection would require the Reflection permission.
Because the bootstrap program and mobile application framework require few permissions, mobile applications deployed via the Pinboard can be downloaded and run securely with the .NET Framework's default permissions for untrusted code from the Internet. To demonstrate this, we have implemented an application called Misbehave that attempts to write to the local file system. The default permissions for untrusted code from the Internet cause Misbehave to fail when it attempts to write to the file system.
By requiring few permissions, the Pinboard frees administrators to implement an appropriate level of trust in their security policy. For example, an administrators may configure client computers to be more permissive of code downloaded from the Intranet. In this environment, an Intranet Pinboard can be used to deploy and share rich applications amongst the Intranet users with a high degree of confidence because the security policy is implemented and enforced at the .NET Framework level.
The mobile application framework has supported practical experimentation with some simple mobile applications. The discipline that emerged for implementing mobile applications was very similar to that of ordinary desktop or handheld applications: A 'main' method displays a form, and many small methods respond to events such as button clicks. Supporting mobility in applications is a relatively simple matter of providing the user a button or menu item to 'pin' the application.
The process-persistence preprocessor described in Section 3.1 supports the Common Language Infrastructure's (CLI) [4] metadata validity rules. It performs static analysis on programs to determine what guarantees the verifier would make of the program at each instruction, and preserves those guarantees when inserting the state saving and restoring code.
This means the preprocessor only works on verifiable .NET executables, however the executables produced are also verifiable. Verifiability is required by most security policies. Maintaining verifiability also gave us some confidence in the correctness of our transformations as we were implementing the preprocessor.
On the other hand, lacking a declarative way of specifying the program transformations makes the implementation of thread persistence opaque at best; using F# and the AbsIL toolkit [15] instead of C# may make the implementation clearer.
Our mobile applications are directly inspired by the migratory applications of Bharat and Cardelli [1], who implemented mobile programs in a LAN setting. Like migratory applications, our mobile applications are non-distributed (that is, they only execute on a single host at a time) and may move between hosts during their lifetime.
The important differences between our mobile applications and migratory applications is that we place relatively few demands on the programming language and relatively more on the programmer. The migratory applications are written in the specialised language Obliq [2]; our examples are written in the mainstream languages C# and VB.NET. The programmer can optionally cooperate with the migration mechanism by applying metadata to methods.
The superficial similarity to Java applets is because our current implementation is very Web-server centric, with the Pinboard being the focus of application sharing and dissemination. The Pinboard could be extended to use multiple Web servers, allow users to pin mobile applications to their desktop PCs, and allow users to move mobile applications directly from one computer to another. In contrast, the stateless nature of Java applets means that there is no difference to the user if an applet is received from another user or downloaded directly from the original provider.
Our mobile application framework is not particularly specific to user-interactive applications. The process persistence service has been used in a mobile agent system for implementing Web services [3], and for checkpointing long-running jobs in an adaptively parallel cycle-stealing system [6].
The process persistence mechanism is similar to intermediate-language instrumenting schemes implemented on the Java Virtual Machine (JVM) [17]. It is also possible to implement process persistence by preprocessing source code [5] or actively monitoring a process via the debugger interface [8]. The rationale for working at the intermediate language level, instead of the source code level, is stronger on .NET because .NET explicitly supports multiple languages. Using the debugger has negative security implications, and is not portable (our process persistence service has been used on the .NET Framework, the .NET Compact Framework, and Rotor [9]).
This section briefly outlines two areas for improvement and further research.
There is good potential for performing a kind of dynamic dead-code elimination on mobile applications. By computing code-reachability during preprocessing and storing this in assembly metadata, and storing the saved thread call stacks in a more accessible format, the Web server could prune unreachable code for each client.
Dead-code elimination could also facilitate a singleuse scheme for application instances: The application vendor starts a mobile application running, and makes the instance available to users by pinning it to a Web server. When the instance is transferred to the Web server, the application's initialisation code has gone out of scope and is removed.
Mobile applications could detect when they are running different situations and provide different operational modes for these. For example, a mobile application may display a different user interface when it is running on a handheld device to when it is running on a desktop PC. A more sophisticated application may farm out work to a server when it is in a limited resources situation.
When an application is running in a noninteractive setting (for example, on a Web server), it might provide access to its data via a Web service. Thus we can view mobile applications as also being software components: behavioural wrappers encapsulating some data.
This work was supported by a grant from Microsoft Research.
[1] Bharat, K., Cardelli, L. (1995). "Migratory Applications" in Vitek, J., Tschudin, C. Mobile Object Systems. Lecture Notes in Computer Science Vol. 1222. p.131-148 Springer-Verlag, Heidelberg.
[2] Cardelli, L. (1995). "A Language with Distributed Scope" in Conference Record of POPL '95: 22nd Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, p.286-297, San Francisco.
[3] Cooney, D. and Roe, P. (2003). "Mobile agents make for flexible Web services" in Proceedings of The Ninth Australian World Wide Web Conference, Gold Coast, Australia. Available online [HREF5].
[4] ECMA (2002). Common Language Infrastructure (CLI). ECMA Standard 335, Geneva.
[5] Funfrocken, S. (1998) "Transparent Migration of Java-based Mobile Agents" in MA'98 Mobile Agents. Lecture Notes in Computer Science Vol. 1477. p.26-37. Springer-Verlag, Heidelberg.
[6] Sumitomo, J. and Cooney, D. (2004). "Checkpointing in the G2 Cycle Stealing System" (Unpublished paper.)
[7] Lange, D. (1997). Java Aglet Application Programming Interface (J-AAPI) White Paper. IBM Tokyo Research Laboratory. Available online [HREF6].
[8] Ma, R., Wang, C.-L., Lau, F. (2002). "M-JavaMPI: A Java-MPI Binding with Process Migration Support" in Second IEEE/ACM International Symposium on Cluster Computing and the Grid (CCGrid 2002), Berlin.
[9] Microsoft Corp. (2003). The Shared Source CLI. Available online [HREF7].
[10] Recursion Software (2003). Voyager ORB. Available online [HREF8].
[11] Roeder, L. (2002). ILReader. Available online [HREF9].
[12] Sun Microsystems (2003). Java Remote Method Invocation. Available online [HREF10].
[13] Sun Microsystems (2003). Jini Architecture Specification. Available online [HREF11].
[14] Syukur, E., Cooney, D., Loke, S.-W. and Stanski, P. (2004). "Hanging Services: An Investigation of Context-Sensitivity and Mobile Code for Localised Services" in Proceedings of the IEEE International Conference on Mobile Data Management. Berkeley, California.
[15] Syme, D. (2002). Abstract IL. Available online [HREF12].
[16] Szyperski, C. (2002). Component Software (2nd ed.). p.411. Addison-Wesley, London.
[17] Truyen, E., et al. (2000). "Portable Support for Transparent Thread Migration in Java" in Proceedings of International Symposium on Agent Systems and Applications/Mobile Agents p.29-43. Zurich.
[18] Wong, D., et al. (1997). "Concordia: An Infrastructure for Collaborating Mobile Agents" in First International Workshop on Mobile Agents (MA'97). Berlin.
Dominic Cooney and Paul Roe, © 2004. The authors assign to Southern Cross University and other educational and non-profit institutions a non-exclusive licence to use this document for personal use and in courses of instruction provided that the article is used in full and this copyright statement is reproduced. The authors also grant a non-exclusive licence to Southern Cross University to publish this document in full on the World Wide Web and on CD-ROM and in printed form with the conference papers and for the document to be published on mirrors on the World Wide Web.