JiST simulation programs are written in plain Java, an object-oriented
language. As in any object-oriented language the entire simulation program
comprises numerous classes that collectively implement the logic of the
simulation model. During its execution, the state of the program is contained
entirely within individual objects. These objects communicate by passing
messages, which are represented as object method invocations in the language.

In order to facilitate the design of simulations, JiST extends this
traditional programming model with the notion of simulation entities. In
the program code, entities are defined as instances of classes that implement
the JistAPI.Entity interface. Although entities are regular objects to
the JVM, they serve to logically encapsulate application objects, as shown in
Figure 3 and demarcate independent simulation components. Thus,
every object should be logically contained within an entity. Conversely, the
state of an entity is the combined state of all the objects reachable from it.

To enforce this strict partitioning of a simulation into entities and to prevent
object communication across entity boundaries, each (mutable) object in the
system must belong to a single entity and must be entirely encapsulated within
it. In Java, this merely means that all references to an object must originate
either directly or indirectly from a single entity. This condition suffices to
ensure simulation partitioning, since Java is a safe language.

Figure 3:
Simulation programs are partitioned into entities along object
boundaries. Thus, entities do not share any application state and can
independently progress through simulation time between interactions.

The JiST kernel manages a simulation at the granularity of its entities.
Instructions and method invocations within an entity follow the regular
Java control flow and semantics, entirely opaque to the JiST infrastructure.
The vast majority of this code is involved with encoding the logic of the
simulation model and is entirely unrelated to the notion of simulation time.
All the standard Java class libraries are available and behave as expected. In
addition, the simulation developer has access to a few basic JiST primitives,
including functions such as getTime and sleep, which allow for
interactions with the simulation kernel.

In contrast, invocations on entities (as opposed to regular objects)
represent simulation events. The execution semantics are that method
invocations on entities are non-blocking. They are merely queued at their
point of invocation, not invoked. The invocation is actually performed on the
callee (or target) entity only when it reaches the same simulation time as the
calling (or source) entity. In other words, cross-entity method invocations
act as synchronization points in simulation time. Or, from a language-oriented
perspective, an entity method is like a coroutine, albeit scheduled in
simulation time. This is a convenient abstraction in that it eliminates the
need for an explicit simulation event queue. It is the JiST kernel that
actually runs the event loop, which processes the simulation events, invoking
the appropriate method for each event dequeued in its simulation time order
and executing the event to completion without continuation.

A complete separation of entities, as discussed above, is not possible without
an additional consideration. That is, in order to invoke a method on another
entity - to send it an event - the caller entity must hold some kind
of reference to the target entity, as depicted in Figure 4.
We, therefore, distinguish between object references and entity references,
and expand on the constraints stated above. All references to a given
(mutable) object must originate from within the same entity. However,
references to entities are free to originate from any entity. The rationale is
that object references imply inclusion within the state of an entity, whereas
entity references represent channels along which simulation events are
transmitted. As a direct consequence, entities do not nest, just as regular
Java objects do not.

We reintroduce the separation of entities at runtime, by transparently
replacing all entity references within the simulation bytecode with special
objects, called separators, as shown on the right of
Figure 4. The separator object identifies a particular
entity, but without referencing it directly. Rather, separators store a unique
entity identifier that is generated by the kernel for each entity during its
initialization. Separators can be held in local variables, stored in fields or
objects or passed as method parameters, just like the regular object
references that they replace. Since the replacement occurs across the entire
simulation bytecode, it remains type-safe.

Figure 4:
At runtime, entity references are transparently replaced with
separators. This both preserves the separation of entity state and also
serves as a convenient point to insert additional functionality. For
example, separators can provide the abstraction of a single system by
tracking the location of remote entities and relaying events to them.

Due to this imposed separation, we guarantee that interactions among entities
can only occur via the JiST kernel. Furthermore, since entities do not
share any application state, each entity may actually progress through
simulation time independently between interactions. The separators, in effect,
represent an application state-time boundary around each entity, similar to a
TimeWarp [10] process, but at finer granularity. Thus, by
tracking the simulation time of each individual entity, these separators allow
for concurrent execution. By adding the ability to checkpoint entities, via
Java serialization, for example, the system can support speculative execution
as well. Finally, separators also provide a convenient point for the
distribution of entities across multiple machines. In a distributed
simulation, the separators function also as remote stubs and transparently
maintain a convenient abstraction of a single system image. Separators
transparently store and track the location of entities as they migrate among
machines in response to fluctuating processor, memory and network loads.

The role of the simulation developer, then, is to codify the simulation model
in regular Java and to partition the state of the simulation not only into
objects, but also into a set of independent entities along reasonable
application boundaries. The JiST infrastructure will transparently execute
the program efficiently, while retaining the simulation time semantics.