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.
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.
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  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.