Design Criteria
The design of µCode was inspired by the following criteria:
- Place emphasis on (fine-grained) code mobility rather than mobile agents.
-
The vast majority of current mobile agent systems
provide
a single abstraction: the mobile agent. A mobile agent represent a unit of
mobility that coincides with the unit of
execution, and that is able to
autonomously determine its own migration. Although this very
concept is intriguing, and at the core of a whole area of research, relocating
the whole unit of execution is not always necessary nor desirable. Very often, a
finer grain of mobility, like a single class or object, is
preferable.
Some forms of code mobility, like code on
demand, or remote evaluation,
do not require the movement of a whole unit of execution. Only code is
transferred, and such code is used to instantiate a new unit at destination, or
to link it into an already running one.
These latter forms of mobility lack the autonomy that characterize mobile
agents, but they are often extremely useful in practice, as witnessed for
instance by the use of a simple code on demand scheme in Java/RMI. Although it
is possible to implement these mobile code paradigms with a mobile agent, this
leads to inefficiency, because some state is shipped although this is not
necessary. Moreover, it forces the programmer to use the mobile agent
abstraction in an counter-intuitive way, e.g., by sending an agent with the
sole purpose of carrying a class to the target node. In many ways, the semantic richness of the agent concept
backfires on the programmer, who is forced to express lower level concepts in a
higher level framework.
In µCode, the reverse approach is taken. The emphasis is on how to
relocate the smallest units of mobility, i.e., classes and objects. The
primitives provided by µCode enable the creation of any mobile code
paradigm. Mobile agents are just one of the many mobility concepts that can be
built using such primitives.
- Focus on mobility: target additional features through modularity, composability, extendibility.
- I really believe that toolkits conceived for mobile code (and mobile agents,
for that matter) should complement rather than substitute
existing middleware. Instead, current
mobile agent systems insist on providing heavyweight systems that aim at
providing the greater common denominator of features, often replicating
features already provided (often better) by existing systems.
Here is a graphical representation of what I mean.

On the left, you can see the high-level architecture of a typical mobile agent
system. These systems are usually very rich in features, but they typically come as a single, monolithic piece of software. It is an "all or
nothing" scheme. There is often no way one can use only the features that
are needed (e.g., a lean run-time support with no security and no persistence)
or, even better, use different implementations of the same feature (e.g., a
better implementation of security, or different communication primitives).
Furthermore, often a piece of non-Java run-time support is needed (thus,
compromising portability and adding to the overhead of the JVM).
On the right, you can see the architecture that underlies µCode. No
additional run-time support is needed. Moreover, the features that are glossed
into the mobile agent system in the left-hand side picture, are instead built
on top of µCode. Notably, even the mobile agent concept itself is built
using the core µCode primitives.
µCode aims at providing a thin veneer on top of the JVM, providing just
code mobility. Higher-level features and services will be built on top of this
veneer. Under this respect, µCode shares similar goals to the M0
system, in that it aims at providing a minimal set of primitives that can be
used to implement higher level mobility services, including mobile
agents.
Flexibility was also another yardstick against which measure design tradeoffs.
Clearly, flexibility is affected by many facets of a system.
However, there was one specific issue where I wanted a degree of flexibility absolutely higher
than what the other systems provided:
- Allow to specify dynamically and individually the relocation strategy for
classes.
- Mobile agents are typically made of several classes, which in principle may
and should be relocated differently. For instance, classes
belonging to
java.* are never moved (because they are assumed to
be everywhere), while the classes of a migrating agent are needed at
destination, and must be somehow relocated there. In current
mobile agent systems, however, the
strategies that rule class relocation are not completely under the control of
the programmer.
- First of all, whether a class is fixed or relocatable is usually determined with static
criteria, e.g., with environment variables like the
AGLET_EXPORT_PATH environment variable in IBM's
Aglets, and thus cannot be easily changed dynamically.
-
Moreover, the policy used for the actual relocation is usually hard-wired in
the system, and typically exploits code on demand, i.e., missing classes are retrieved remotely and linked dynamically
using the class loader mechanism. As a consequence, there are often no means to relocate all the classes needed by an
agent in a
single operation.
It is interesting to note that this latter approach (followed among the others by
IBM Aglets and JumpingBeans) prevents completely the autonomy of mobile
agents. For instance, mobile agents can no longer be used to support
disconnected operations, because the agent must retain an umbilical cord to
some code repository. In other words, one of the most important novel aspects
of mobile agents is hampered by design.
- The capability to determine at run-time which classes must be relocated and
how can be useful (and has proven such in my experience). For instance, on a GSM connection at
9,600 bps it might be meaningful to send in one shot
all the classes needed by an agent, to avoid keeping up the expensive wireless
connection, and thus leveraging off of the ability to support disconnected
operations provided by mobile agents. On the other hand, if the same agent is now traversing a
LAN, it can be also meaningful
to send only the root class of the agent and download the others on demand,
thus minimizing the computational overload upon startup at the target node by exploiting the fast link for remote dynamic linking.
- Summing up, the strategy adopted for the relocation of code is not a
property of the code being relocated; instead, it is determined
by the environment where the code is used. The impossibility to choose dynamically
which classes must be relocated and how, hampers a full exploitation
of the mobile agent paradigm.
Thus, in µCode the set of classes may change every time: all the
strategies for code relocation are supported, ranging from relying completely
on remote dynamic linking to shipping the full class closure (including
classes declared only into methods) at destination.
Other design criteria had to do with more pragmatic issues:
- Small footprint and lightweight execution.
- There is a lot of interest in bringing mobile code and mobile agent systems on Java-enabled PDAs and cellular phones. These environments are typically
resource-constrained, thus it is desirable to have a small code base, and use
as little threads and processes as possible.
Current mobile agent systems
are usually not amenable to this kind of environment. As mentioned earlier,
they often try to provide a wealth of features, thus becoming very
heavyweight. At a minimum, they typically force you to
spawn a process containing the run-time support, which is necessary even if you
need only to send out code and never need to listen for incoming code. For instance, your cellular phone is
unlikely to ever host mobile agents; nevertheless, if you want to use one of
these systems, usually you still need to run the whole run-time support, and
thus (if you ever can fit the whole thing on the phone) you are wasting cycles
listening for agents.
Instead, µCode emphasis on minimality and on decoupling the core
mobility features from everything else allows programmers to customize the
size of the run-time support according to their needs. In principle,
everything could be done with the core µCode package, mucode.jar,
which is just 18Kbytes. Moreover, µCode does not require the startup of any separate
run-time process, and is entirely built on top of plain Java (no need for RMI or other
specialized libraries). The listening for incoming code is performed by a single
thread, and the programmer can dynamically switch on and off this support
according to the needs of the application and the environment.
Finally, the GZIP compression is supported. This way, users may trade
computational overhead for bandwidth consumption. The ability to compress the
migrated code and state makes the difference when mobile code is used to save
bandwidth. Incredibly, to my knowledge µCode is the only system
supporting this feature.
- Non-invasiveness.
- The inspiring approach for µCode is that code mobility is just another option for the programmer, for whom the effort to deal with mobility must be minimized and design freedom maximized.
Many design decisions were affected by this simple principle. As an example, the programmer
should not not be forced to subclass from any particular class in order to use
ship a thread object elsewhere. Mobility should be applicable directly to Java threads, thus fostering exploitation of mobile code even in applications that were not initially designed for it.
© 2000, Gian Pietro Picco - Last modification: 07/09/00