From: Vaibhav Sharma Date: Tue, 16 Jan 2018 20:33:21 +0000 (-0600) Subject: Renaming /doc to /docs for use with GitHub Pages X-Git-Url: http://plrg.eecs.uci.edu/git/?p=jpf-core.git;a=commitdiff_plain;h=617c4bf5004a1a258bd32a212f52252b90800d97;ds=sidebyside Renaming /doc to /docs for use with GitHub Pages --- diff --git a/doc/devel/attributes.md b/doc/devel/attributes.md deleted file mode 100644 index 69c7f83..0000000 --- a/doc/devel/attributes.md +++ /dev/null @@ -1,18 +0,0 @@ -# The Attribute System # - -While JPF stores values for operands, local variables and fields very similar to a normal VM, it also features a storage extension mechanism that lets you associate arbitrary objects with stack slots (operands and locals), fields, and whole objects (ElementInfos). The attribute objects can be set/used in [native peers](mji) or [listeners](listener) to add state stored/restored information that automatically follows the data flow. - -Note that JPF does not restore attribute object values upon backtracking per default, only attribute references. If you need to make sure attribute values are restored, you have to use copy-on-write and then store back when accessing and modifying such attributes. - -![Figure: JPF Attribute System](../graphics/attributes.svg){align=center width=650} - -JPF provides an API to set/access these attributes, which is located in `gov.nasa.jpf.vm.Fields` (for field attributes) and `gov.nasa.jpf.vm.StackFrame` (for local variables and operands). Once set, the VM copies the attributes each time it reads/writes the associated field or stackframe slot. - -## Usage ## - -For example, such attributes can be used to represent symbolic values or numeric error bounds. It should be noted though that attributes impose additional runtime costs, which is also why we don't treat normal, concrete values just as a special kind of attribute (normal values are still stored separately as builtin types like `int`). The upside of this is that your attributes coexist with normal, concrete values, which for instance allows things like mixed symbolic and concrete execution. - -> **Note:** JPF now can associate attributes not only with fields of an object, but with the object as a whole. See the `gov.nasa.jpf.vm.ElementInfo` API for details. - -> **Note:** while there is an API to set/retrieve attributes based on type, there is no implementation -yet that allows multiple attributes to be stored. \ No newline at end of file diff --git a/doc/devel/bytecode_factory.md b/doc/devel/bytecode_factory.md deleted file mode 100644 index 6fb8c2c..0000000 --- a/doc/devel/bytecode_factory.md +++ /dev/null @@ -1,70 +0,0 @@ -# Bytecode Factories # -Normally, a VM defines the semantics of it's programming language. In case of Java, the corresponding instruction set represents a multi-threaded stack machine, where values are kept on the heap, or inside of local and/or operand slots within stack frames. The effect of Java bytecode instructions with respect to heap, locals and operands are described in [Sun's Java virtual machine specifications](http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html/). -JPF is different. The VM of JPF and its associated constructs like `ThreadInfo`, `ClassInfo`, `ElementInfo` etc. provide all the necessary means to implement a normal Java interpreter. However, JPF delegates the use of these means to the instructions. Every bytecode that gets executed by JPF is represented by a corresponding `Instruction` object, which normally gets instantiated during class load time. The `Instruction` classes of the standard execution mode can be found in package `gov.nasa.jpf.jvm.bytecode`. - -When it comes to executing a bytecode, the VM simply calls the `execute()` method of this `Instruction` instance. The implementation of this method defines the execution semantics. - -The trick is now that JPF uses a configurable [abstract factory](http://en.wikipedia.org/wiki/Abstract_factory_pattern) to choose and instantiate the `Instruction` classes. By providing your own concrete `InstructionFactory`, together with a set of related `Instruction` classes, you can change the execution semantics of Java. - -![Figure: Bytecode Factories](../graphics/bc-factory.svg){align=center width=850} - -## Usages ## - -Why would it be useful to change the standard semantics? One reason is to extend normal semantics with additional checks. For example, this is performed by the JPF extension jpf-numeric which overrides numeric bytecode classes with versions that check for over-/underflow and silent NaN propagation (among other things). A much more involved example is the JPF extension jpf-symbc, which implements a symbolic execution mode for Java, e.g. to automatically generate test cases based on the program structure of an application. It does so by overriding branch instructions, turning them into state space branches represented by their own [ChoiceGenerators](choicegenerator), collecting the path conditions on the way, and feeding them to an external SAT solver. - -## Implementation ## - -Since there is a large number of Java bytecode instructions, it would be tedious having to implement all 250+ Instruction classes in order to override just a couple of them. You can reduce the effort in three ways: - - -### GenericInstructionFactory ### - - -Using the `GenericInstructionFactory` as a base class for your `InstructionFactory`. This only requires you to specify an alternative package where your bytecode classes reside, together with the set of bytecodes that should be overridden. The resulting code can be quite short, as can be seen in the *numeric* extension example: - -~~~~~~~~ {.java} -public class NumericInstructionFactory extends GenericInstructionFactory { - - // which bytecodes do we replace - static final String[] BC_NAMES = { - "DCMPG", "DCMPL", "DADD", "DSUB", "DMUL", "DDIV", - "FCMPG", "FCMPL", "FADD", "FSUB", "FMUL", "FDIV", - "IADD", "ISUB", "IMUL", "IDIV", "IINC", - "LADD", "LSUB", "LMUL", "LDIV" - }; - - // where do they reside - protected static final String BC_PREFIX = "gov.nasa.jpf.numeric.bytecode."; - - // what classes should use them - protected static final String[] DEFAULT_EXCLUDES = { "java.*", "javax.*" }; - - public NumericInstructionFactory (Config conf){ - super(conf, BC_PREFIX, BC_NAMES, null, DEFAULT_EXCLUDES); - - NumericUtils.init(conf); - } -} -~~~~~~~~ - - -### Super Delegation ### - -You can derive your overriding bytecode classes from the ones in `gov.nasa.jpf.jvm.bytecode`. If you just want to add some checks before or after performing the "normal" operation, you can use the standard `Instruction` classes as base classes, and call `super.execute(..)` from within your derived classes. - - -### Attributes ### - -As your execution semantics get more complex, you probably need to store and restore additional information that is associated with variables. JPF provides an automatically managed [attribute system](attributes) for this purpose. You can attach objects to locals, operands and fields, and JPF takes care of propagating these attribute objects whenever it manipulates stackframes or heap objects. - - -## Configuration ## - - -Configuring your bytecode factory just requires one JPF property, e.g. - -~~~~~~~~ {.bash} -vm.insn_factory.class = gov.nasa.jpf.numeric.NumericInstructionFactory -~~~~~~~~ - -which can be either done from the command line or from within a *.jpf property file diff --git a/doc/devel/choicegenerator.md b/doc/devel/choicegenerator.md deleted file mode 100644 index e8272eb..0000000 --- a/doc/devel/choicegenerator.md +++ /dev/null @@ -1,212 +0,0 @@ -# ChoiceGenerators # - -The goal of every model checker is to check if certain properties hold in states of the system under test. The way that choices are computed is a fundamental part of model checking, since they determine which states are checked. We refer to the mechanism used by JPF to capture choices as ChoiceGenerators. - -ChoiceGenerators can be approached from an application perspective, or from the JPF implementation perspective. In this section, we cover both perspectives. - -## Motivation ## - -Whenever the model checker reaches non-determinism in code, it needs to compute choices. Non-determinism can be due to thread scheduling or non-deterministic data acquisitions. Here, we present an example including data non-determinism to justify our implementation approach. JPF provides support for "random" data acquisition, using the interface `gov.nasa.jpf.jvm.Verify`. - -~~~~~~~~ {.java} -... -boolean b = Verify.getBoolean(); // evaluated by JPF for both `true` and `false` -... -~~~~~~~~ - -This worked nicely for small sets of choice values (such as `{true,false}` for boolean), but the mechanism for enumerating all choices from a type specific interval becomes already questionable for large intervals (e.g. `Verify.getInt(0,10000)`), and fails completely if the data type does not allow finite choice sets at all (such as floating point types): - -![Figure 1: Motivation behind ChoiceGenerator](../graphics/cg-motivation.svg){align=center width=750} - -To handle this case, we have to leave the ideal world of model checking (that considers all possible choices), and make use of what we know about the real world - we have to use heuristics to make the set of choices finite and manageable. However, heuristics are application and domain specific, and it would be a bad idea to hardcode them into the test drivers we give JPF to analyze. This leads to a number of requirements for the JPF choice mechanism: - - * choice mechanisms have to be decoupled (i.e. thread choices should be independent of data choices, double choices from int choices etc.) - * choice sets and enumeration should be encapsulated in dedicated, type specific objects. The VM should only know about the most basic types, and otherwise use a generic interface to obtain choices - * selection of classes representing (domain specific) heuristics, and parametrization of ChoiceGenerator instances should be possible at runtime, i.e. via JPF's configuration mechanism (properties) - -The diagram shown above depicts this with an example that uses a "randomly" chosen velocity value of type double. As an example heuristic we use a threshold model, i.e. we want to know how the system reacts below, at, and above a certain application specific value (threshold). We reduce an infinite set of choices to only three "interesting" ones. Of course, "interesting" is quite subjective, and we probably want to play with the values (delta, threshold, or even used heuristic) efficiently, without having to rebuild the application each time we run JPF. - -The code example does not mention the used `ChoiceGenerator` class (`DoubleThresholdGenerator`) at all, it just specifies a symbolic name `"velocity"`, which JPF uses to look up an associated class name from its configuration data (initialized via property files or the command line - see Configuring JPF Runtime Options). But it doesn't stop there. Most heuristics need further parameterization (e.g. threshold, delta), and we provide that by passing the JPF configuration data into the `ChoiceGenerator` constructors (e.g. the `velocity.threshold` property). Each `ChoiceGenerator` instance knows its symbolic name (e.g. `"velocity"`), and can use this name to look up whatever parameters it needs. - -## The JPF Perspective ## - -Having such a mechanism is nice to avoid test driver modification. But it would be much nicer to consistently use the same mechanism not just for data acquisition choices, but also scheduling choices (i.e. functionality that is not controlled by the test application). JPF's ChoiceGenerator mechanism does just this, but in order to understand it from an implementation perspective we have to take one step back and look at some JPF terminology: - -![Figure 2: States, Transitions and Choices](../graphics/cg-ontology.svg){align=center width=650} - - -*State* is a snapshot of the current execution status of the application (mostly thread and heap states), plus the execution history (path) that lead to this state. Every state has a unique id number. State is encapsulated in the `SystemState` instance (almost, there is some execution history which is just kept by the JVM object). This includes three components: - - * KernelState - the application snapshot (threads, heap) - * trail - the last Transition (execution history) - * current and next ChoiceGenerator - the objects encapsulating the choice enumeration that produces different transitions (but not necessarily new states) - -*Transition* is the sequence of instructions that leads from one state to the next. There is no context switch within a transition, it's all in the same thread. There can be multiple transitions leading out of one state (but not necessarily to a new state). - -*Choice* is what starts a new transition. This can be a different thread (i.e. scheduling choice), or different "random" data value. - -In other words, possible existence of choices is what terminates the last transition, and selection of a choice value precludes the next transition. The first condition corresponds to creating a new `ChoiceGenerator`, and letting the `SystemState` know about it. The second condition means to query the next choice value from this `ChoiceGenerator` (either internally within the VM, or in an instruction or native method). - -## How it comes to Life ## -With this terminology, we are ready to have a look at how it all works. Let's assume we are in a transition that executes a `getfield` bytecode instruction (remember, JPF executes Java bytecode), and the corresponding object that owns this field is shared between threads. For simplicity's sake, let's further assume there is no synchronization when accessing this object, (or we have turned off the property `vm.sync_detection`). Let's also assume there are other runnable threads at this point. Then we have a choice - the outcome of the execution might depend on the order in which we schedule threads, and hence access this field. There might be a data race. - -![Figure 3: ChoiceGenerator Sequence](../graphics/cg-sequence.svg){align=center width=550} - -Consequently, when JPF executes this `getfield` instruction, the `gov.nasa.jpf.jvm.bytecode.GETFIELD.execute()` method does three things: - - 1. create a new `ChoiceGenerator` (`ThreadChoiceGenerator` in this case), that has all runnable threads at this point as possible choices - 2. registers this `ChoiceGenerator` via calling `SystemState.setNextChoiceGenerator()` - 3. schedules itself for re-execution (just returns itself as the next instruction to execute within the currently running thread) - -At this point, JPF ends this transition (which is basically a loop inside `ThreadInfo.executeStep()`), stores a snapshot of the current State, and then starts the next transition (let's ignore the search and possible backtracks for a moment). The `ChoiceGenerator` created and registered at the end of the previous transition becomes the new current `ChoiceGenerator`. Every state has exactly one current `ChoiceGenerator` object that is associated with it, and every transition has exactly one choice value of this `ChoiceGenerator` that kicks it off. Every transition ends in an instruction that produces the next `ChoiceGenerator`. - -The new transition is started by the `SystemState` by setting the previously registered `ChoiceGenerator` as the current one, and calling its `ChoiceGenerator.advance()` method to position it on its next choice. Then the `SystemState` checks if the current `ChoiceGenerator` is a scheduling point (just a `ThreadChoiceGenerator` used to encapsulate threads scheduling), and if so, it gets the next thread to execute from it (i.e. the `SystemState` itself consumes the choice). Then it starts the next transition by calling `ThreadInfo.executeStep()` on it. - -The `ThreadInfo.executeStep()` basically loops until an Instruction.execute() returns itself, i.e. has scheduled itself for re-execution with a new `ChoiceGenerator`. When a subsequent `ThreadInfo.executeStep()` re-executes this instruction (e.g. `GETFIELD.execute()`), the instruction notices that it is the first instruction in a new transition, and hence does not have to create a `ChoiceGenerator` but proceeds with it's normal operations. - -If there is no next instruction, or the Search determines that the state has been seen before, the VM backtracks. The `SystemState` is restored to the old state, and checks for not-yet-explored choices of its associated ChoiceGenerator by calling `ChoiceGenerator.hasMoreChoices()`. If there are more choices, it positions the `ChoiceGenerator` on the next one by calling `ChoiceGenerator.advance()`. If all choices have been processed, the system backtracks again (until it's first `ChoiceGenerator` is done, at which point we terminate the search). - -![Figure 4: ChoiceGenerator Implementation](../graphics/cg-impl.svg){align=center width=850} - -The methods that create `ChoiceGenerators` have a particular structure, dividing their bodies into two parts: - - 1. *top half* - (potentially) creates and registers a new `ChoiceGenerator`. This marks the end of a transition - 2. *bottom half* - which does the real work, and might depend on acquiring a new choice value. This is executed at the beginning of the next transition - -To determine which branch you are in, you can call `ThreadInfo.isFirstStepInsn()`. This will return `true` if the currently executed instruction is the first one in the transition, which corresponds to the *bottom half* mentioned above. - -The only difference between scheduling choices and data acquisition choices is that the first ones are handled internally by the VM (more specifically: used by the `SystemState` to determine the next thread to execute), and the data acquisition is handled in the bottom half of `Instruction.execute()`, native method, or listener callback method (in which case it has to acquire the current `ChoiceGenerator` from the `SystemState`, and then explicitly call `ChoiceGenerator.getNextChoice()` to obtain the choice value). For a real example, look at the `JPF.gov_nasa_jpf_jvm_Verify.getBoolean()` implementation. - -As an implementation detail, creation of scheduling points are delegated to a `Scheduler` instance, which encapsulates a scheduling policy by providing a consistent set of `ThreadChoiceGenerators` for the fixed number of instructions that are scheduling relevant (`monitor_enter`, synchronized method calls, `Object.wait()` etc.). Clients of this `Scheduler` therefore have to be aware of that the policy object might not return a new `ChoiceGenerator`, in which case the client directly proceeds with the bottom half execution, and does not break the current transition. - -The standard classes and interfaces for the ChoiceGenerator mechanism can be found in package `gov.nasa.jpf.vm`, and include: - - * `ChoiceGenerator` - * `BooleanChoiceGenerator` - * `IntChoiceGenerator` - * `DoublechoiceGenerator` - * `ThreadChoiceGenerator` - * `SchedulingPoint` - * `SchedulerFactory` - * `DefaultSchedulerFactory` - -Concrete implementations can be found in package `gov.nasa.jpf.vm.choice`, and include classes like: - - * `IntIntervalGenerator` - * `IntChoiceFromSet` - * `DoubleChoiceFromSet` - * `DoubleThresholdGenerator` - * `ThreadChoiceFromSet` - -As the number of useful generic heuristics increases, we expect this package to be expanded. - - -## Cascaded ChoiceGenerators ## -There can be more than one `ChoiceGenerator` object associated with a transition. Such ChoiceGenerators are referred to as *cascaded*, since they give us a set of choice combinations for such transitions. - -For example, assume that we want to create a listener that perturbs certain field values, i.e. it replaces the result operand that is pushed by a `getfield` instruction. This is easy to do from a listener, but the VM (more specifically our on-the-fly [partial order reduction](partial_order_reduction)) might already create a `ThreadChoiceGenerator` (scheduling point) for this `getfield` if it refers to a shared object, and the instruction might cause a data race. Without cascaded `ChoiceGenerators` we could only have the perturbation listener **or** the race detection, but not both. This is clearly a limitation we want to overcome, since you might not even know when JPF - or some of the other [listeners](listener) or [bytecode_factories](bytecode_factory) - create `ChoiceGenerators` that would collide with the ones you want to create in your listener. - -Using cascaded ChoiceGenerators requires little more than what we have already seen above. It only involves changes to two steps: - - 1. ChoiceGenerator creation - you need to identify `ChoiceGenerators` with a `String` id. We can't use the type of the `ChoiceGenerator` - or it's associated choice type - to identify a particular instance, since different listeners might use different `ChoiceGenerator` instances of same types for different purposes. Resolving through unique types would throw us back to where we would have to know about all the other `ChoiceGenerators` created by all the other JPF components. We can't use the associated instruction either, because the whole point is that we can have more than one `ChoiceGenerator` for each of them. So we have to give our `ChoiceGenerator` instances names when we create them, as in - -~~~~~~~~ {.java} -... -IntChoiceFromSet cg = new IntChoiceFromSet("fieldPerturbator", 42, 43); -~~~~~~~~ - -The name should be reasonably unique, describing the context in which this choice is used. Don't go with "generic" names like "myChoice". In case of doubt, use the method name that creates the `ChoiceGenerator`. The reason why we need the *id* in the first place is that we later-on want to be able to retrieve a specific instance. Which brings us to: - - 2. ChoiceGenerator retrieval - at some point we want to process the choice (usually within the *bottom half* of the method that created the `ChoiceGenerator`), so we need to tell JPF all we know about the `ChoiceGenerator` instance, namely id and type. The simple `SystemState.getChoiceGenerator()` we used above will only give us the last registered one, which might or might not be the one we registered ourselves. Retrieval is done with a new method `SystemState.getCurrentChoiceGenerator(id,cgType)`, which in the above case would look like: - -~~~~~~~~ {.java} -... -IntChoiceFromSet cg = systemState.getCurrentChoiceGenerator("fieldPerturbator", IntChoiceFromSet.class); -assert cg != null : "required IntChoiceGenerator not found"; -... -~~~~~~~~ - -This method returns `null` if there is no `ChoiceGenerator` of the specified id and type associated with the currently executed instruction. If this is the bottom half of a method that created the instance, this is most likely an error condition that should be checked with an assertion. If the retrieval is in another method, existence of such a `ChoiceGenerator` instance could be optional and you therefore have it checked in an `if (cg != null) {..}' expression. - -This is all there is to it in case you don't refer to a particular execution state of an instruction. As an example, assume that you want to add some int choices on top of each `Verify.getInt(..)` call. Your listener would look like this: - -~~~~~~~~ {.java} - @Override - public void instructionExecuted(VM vm, ThreadInfo ti, Instruction nextInsn, Instruction executedInsn) { - SystemState ss = vm.getSystemState(); - - if (executedInsn instanceof EXECUTENATIVE) { // break on method call - EXECUTENATIVE exec = (EXECUTENATIVE) executedInsn; - - if (exec.getExecutedMethodName().equals("getInt")){ // Verify.getInt(..) - this insn did create a CG on its own - if (!ti.isFirstStepInsn()){ // top half - first execution - IntIntervalGenerator cg = new IntIntervalGenerator("instrumentVerifyGetInt", 3,4); - ss.setNextChoiceGenerator(cg); - ... - - } else { // bottom half - re-execution at the beginning of the next transition - IntIntervalGenerator cg = ss.getCurrentChoiceGenerator("instrumentVerifyGetInt", IntIntervalGenerator.class); - assert cg != null : "no 'instrumentVerifyGetInt' IntIntervalGenerator found"; - int myChoice = cg.getNextChoice(); - ... // process choice - } - } - } - } -~~~~~~~~ - - -Sometimes what you do with your choice depends on the execution state of the instruction this `ChoiceGenerator` was created for, and you have to be aware of that the instruction might get re-executed (e.g. after processing the top half of another `ChoiceGenerator` creating method) before it has done what you depend on for your local choice processing. Consider our previous example of the field perturbation. Simply speaking, all we want to do in our listener is just swap operand stack values after a certain `getfield`. However, the partial order reduction of the VM might get in our way because it reschedules the instruction *before* it pushes the value if execution of this instruction might constitute a data race, and therefore required creation of a `ThreadChoiceGenerator` instance. What is worse is that the VM might do this conditionally - if there is only one runnable thread, there is no need for a scheduling point since there can't be a data race. Our own perturbator listener has to account for all that. Luckily, we can use `SystemState.getCurrentChoiceGenerator(id,type)` to unify all these cases, and we just have to restore execution state in case we want to re-execute the instruction ourselves. Here is an example: - -~~~~~~~~ {.java} - @Override - public void instructionExecuted(VM vm, ThreadInfo ti, Instruction nextInsn, Instruction executedInsn) { - SystemState ss = vm.getSystemState(); - - if (executedInsn instanceof GETFIELD){ - GETFIELD getInsn = (GETFIELD) executedInsn; - FieldInfo fi = getInsn.getFieldInfo(); - if (fi.getName().equals("perturbedFieldName")){ - - IntChoiceFromSet cg = ss.getCurrentChoiceGenerator("fieldReplace", IntChoiceFromSet.class); - StackFrame frame = ti.getModifiableTopFrame(); - if (cg == null){ - - // we might get here after a preceding rescheduling exec, i.e. - // partial execution (with successive re-execution), or after - // non-rescheduling exec has been completed (only one runnable thread). - // In the first case we have to restore the operand stack so that - // we can re-execute - if (!ti.willReExecuteInstruction()){ - // restore old operand stack contents - frame.pop(); - frame.push(getInsn.getLastThis()); - } - - cg = new IntChoiceFromSet("fieldReplace", 42, 43); - ss.setNextChoiceGenerator(cg); - ti.reExecuteInstruction(); - - } else { - int v = cg.getNextChoice(); - int n = frame.pop(); - frame.push(v); - } - } - } - } -~~~~~~~~ - -These examples show you that at the beginning of each transition, there is a choice value for all the cascaded `ChoiceGenerators` associated with it. If you would add `choiceGeneratorAdvanced()` notifications to your listener, you would also see that JPF processes all related choice combinations. - -If you really want to see the context, there are a number of additional methods in `SystemState` that might help you: - - * `getChoiceGenerator()` - returns only the last registered one - * `getChoiceGenerators()` - returns an array of all `ChoiceGenerators` in the current execution path - * `getLastChoiceGeneratorOfType(cgType)` - returns the last registered `ChoiceGenerator` in the path that is of the specified type - * `getCurrentChoiceGenerators()` - returns array of all cascaded `ChoiceGenerators` associated with the current transition - * `getCurrentChoiceGenerator(id)` - returns last registered `ChoiceGenerator` of cascade with specified *id* - * `getCurrentChoiceGenerator(id,cgType)` - our workhorse: last registered `ChoiceGenerator` of cascade with specified *id* and *cgType* (which can be a supertype of the actual one) - * etc. - -How does the system detect if a `ChoiceGenerator` is cascaded or not? Very simple - within `SystemState.setNextChoiceGenerator(cg)`, we just check if `SystemState` already had a registered next `ChoiceGenerator`, and if so, we set a cascaded attribute for this one. Other than that, we just maintain normal linear `ChoiceGenerator` linkage, which is accessible through `ChoiceGenerator.getPreviousChoiceGenerator()`. If you want to iterate through a cascade yourself, use the `ChoiceGenerator.getCascadedParent()` method, which returns `null` if there is none. Just be aware of that the last registered `ChoiceGenerator` (i.e. what `SystemState.getChoiceGenerator()` returns) does *not* have the cascaded attribute set (i.e. `ChoiceGenerator.isCascaded()` returns `false`). \ No newline at end of file diff --git a/doc/devel/coding_conventions.md b/doc/devel/coding_conventions.md deleted file mode 100644 index fe629e9..0000000 --- a/doc/devel/coding_conventions.md +++ /dev/null @@ -1,41 +0,0 @@ -# Coding Conventions # -JPF is an open system. In order to keep the source format reasonably consistent, we strive to keep the following minimal set of conventions - - * Two space indentation (no tabs) - * Opening brackets in same line (class declaration, method declaration, control statements) - * No spaces after opening '(', or before closing ')' - * Method declaration parameters indent on column - * All files start with copyright and license information - * All public class and method declarations have preceding Javadoc comments - * We use *camelCase* instead of *underscore_names* for identifiers - * Type names are upper case - -The following code snippet illustrates these rules. - -~~~~~~~~ {.java} -/* - * - */ - -/** - * this is my class declaration example - */ - -public class MyClass { - - /** - * this is my public method example - */ - public void foo (int arg1, int arg2, - int arg3) { - if (bar) { - .. - } else { - .. - } - } - .. -} -~~~~~~~~ - -We consider modularity to be of greater importance than source format. With its new configuration scheme, there is no need to introduce dependencies of core classes towards optional extensions anymore. If you add something that is optional, and does not seamlessly fit into an existing directory, keep it separate by adding new directories. The core JPF classes should not contain any additional dependencies to external code. diff --git a/doc/devel/create_project.md b/doc/devel/create_project.md deleted file mode 100644 index 1eeb9b0..0000000 --- a/doc/devel/create_project.md +++ /dev/null @@ -1,91 +0,0 @@ -# Creating a New JPF Module # - -So what do you have to do to create a new JPF module? For a quick shortcut to setting up *most* things, use the `create_project` script of the [jpf-template module](wiki:projects/jpf-template). - -However, jpf-template cannot do everything for you, so see below for more information on how to finish setting up your new project. - -Several steps are involved: - -### 1. get familiar with the JPF configuration ### -You need to understand how your project will be looked up and initialized during JPF startup, and the place to learn that is the [JPF configuration](../user/config) page. Once you know what *[site properties](../install/site-properties)* and *project properties* are, you can proceed. - -### 2. get familiar with the standard JPF project layout ### -Although this is mostly convention, and you can deviate if you really need to, please try hard not to. - -You can get the details from the [JPF Runtime Modules](modules) page, but the essence is that each project has two (possible) major build artifacts: - - * `jpf-.jar` - executed by the host (platform) VM (contains main classes and peers) - * `jpf--classes.jar` - executed by JPF (contains modeled classes) - -Consequently, your sources are kept in `src/main`, `src/peers`, `src/classes`, `src/annotations`, `src/tests` and `src/examples`. You might only have some of these, but please provide regression tests so that people can check if your project works as expected. - -All 3rd party code that is required at runtime goes into a `lib` directory. - -We keep potential annotations separate (and provide additional `jpf--annotations.jar`) so that external projects (systems under test) can use them without relying on all JPF classes to be in their `classpath`. The idea is that this jar does not contain any code which could alter the system under test behavior if you execute it outside of JPF. - - - -### 3. create a jpf.properties file ### -Within the root directory of each JPF module a project properties file is needed which is named `jpf.properties`. It contains the path settings the host VM and JPF need to know about at runtime. It looks like this: - -~~~~~~~~ {.bash} -# standard header - = ${config_path} - -# classpath elements for the host VM (java) -.native_classpath = build/.jar;lib/... - -# classpath elements for JPF -.classpath = build/-classes.jar;... - -# sources JPF should know about when creating traces etc. -.sourcepath = src/classes;... -~~~~~~~~ - -You can add other JPF properties, but be aware of that this is always processed during JPF startup if you add your module to the `extensions` list in your [site.properties](../install/site-properties), and might conflict with other JPF modules. For this reason you should only add your module to `extensions` if you know it will always be used. - - -### 4. create your build.xml ### -Our build process is [Ant](http://ant.apache.org/) based, hence we need a `build.xml` file. The standard targets are - - * `clean` - * `compile` - * `build` (the default, creates the jars and hence depends on compile) - * `test` (run JUnit regression tests, depends on build) - * `dist` (creates a binary-only distribution) - -If you stick to the general layout, you can use a template like the one attached to this page (of course you need to replace ``). - -Please note how `site.properties` and `jpf.properties` can be used from within the `build.xml` (Ant understands a subset of the JPF property syntax), which means you don't have to explicitly add the jars of other JPF components you depend on (at least jpf-core). You can reference them symbolically like this: - -~~~~~~~~ {.xml} - - - .. - - - - - - ... - - - - - - - - ... -~~~~~~~~ - -### 5. add your module to your site.properties ### -This is optional, you only need to do this if you want to be able to run your JPF module outside its own directory. If so, add an entry to your [site properties file](../install/site-properties) that looks like this: - -~~~~~~~~ {.bash} -... - = -... -~~~~~~~~ - -### 6. publish your repository ### -You can publish this wherever you want ([sourceforge](http://sourceforge.net), [bitbucket](http://bitbucket.org), [google code](http://code.google.com), or [github](http://github.com) are suitable free site supporting Mercurial), or ask us to host it on the JPF server. If you decide to use a 3rd party hosting service, please let us/the JPF community know about it (e.g. by posting to the mailing list at [java-pathfinder@googlegroups.com](https://groups.google.com/forum/#!forum/java-pathfinder). \ No newline at end of file diff --git a/doc/devel/design.md b/doc/devel/design.md deleted file mode 100644 index 60e0fd3..0000000 --- a/doc/devel/design.md +++ /dev/null @@ -1,52 +0,0 @@ -# JPF Top-level Design # - -JPF was designed around two major abstractions: (1) the *VM*, and (2) the *Search* component. - -## Virtual Machine (VM) ## - -The VM is the state generator. By executing bytecode instructions, the VM generates state representations that can be - - * checked for equality (if a state has been visited before) - * queried (thread states, data values etc.) - * stored - * restored - -The main VM parameterizations are classes that implement the state management (matching, storing, backtracking). Most of the execution scheme is delegated to `SystemState`, which in turn uses `Scheduler` to generate scheduling sequences of interest. - -There are three key methods of the VM employed by the Search component: - - * `forward` - generate the next state, report if the generated state has a successor. If yes, store on a backtrack stack for efficient restoration. - * `backtrack` - restore the last state on the backtrack stack - * `restoreState` - restore an arbitrary state (not necessarily on the backtrack stack) - -![Figure: JPF top-level design](../graphics/jpf-abstractions.svg){align=center width=720} - -## Search Strategy ## - -At any state, the Search component is responsible for selecting the next state from which the VM should proceed, either by directing the VM to generate the next state (`forward`), or by telling it to backtrack to a previously generated one (`backtrack`). The Search component works as a driver for the VM. - -The Search component can be configured to check for certain properties by evaluating property objects (e.g. `NotDeadlockedProperty`, `NoAssertionsViolatedProperty`). - -The object encapsulating this component includes a search method which implements a strategy used to traverse the state space. The state space exploration continues until it is completely explored, or a property violation is found. - The Search component can be configured to use different strategies, such as depth-first search (`DFSearch`), and priority-queue based search that can be parameterized to do various search types based on selecting the most interesting state out of the set of all successors of a given state (`HeuristicSearch`). - -## Package Structure ## - -The implementation of the JPF core is partitioned into the following packages: - -### `gov.nasa.jpf` ### -The main responsibility of this package is configuration and instantiation of the core JPF objects, namely the Search and VM. The configuration itself is encapsulated by the `Config` class, which contains various methods to create objects or read values from a hierarchy of property files and command line options (see Configuring JPF Runtime Options). Beyond the configuration, the JPF object has little own functionality. It is mainly a convenience construct to start JPF from inside a Java application without having to bother with its complex configuration. - -### `gov.nasa.jpf.vm` ### -This package constitutes the main body of the core code, including the various constructs that implement the Java state generator. Conceptually, the major class is VM, but again this class delegates most of the work to a set of second level classes that together implement the major functionality of JPF. These classes can be roughly divided into three categories: - -(1) class management - classes are encapsulated by `ClassInfo` which mostly includes invariant information about fields and methods captured by `FieldInfo` and `MethodInfo`, respectively. - -(2) object model - all object data in JPF is stored as integer arrays encapsulated by `Fields` objects. The execution specific lock state of objects is captured by `Monitor` instances. `Fields` and `Monitor` instances together form the objects, which are stored as `ElementInfo`. The heap contains a dynamic array of `ElementInfo` objects where the array indices being used as object reference values - -(3) bytecode execution - the execution of bytecode instructions is performed through a collaboration of `SystemState` and `ThreadInfo`, which is also delegated to policy objects implementing the partial order reduction (POR). It starts with the `VM` object calling `SystemState.nextSuccessor()`, which descends into `ThreadInfo.executeStep()` (together, these two methods encapsulate the on-the-fly POR), which in turn calls `ThreadInfo.executeInstruction()` to perform the bytecode execution. -The actual execution is again delegated to bytecode specific Instruction instances that per default reside in a sub-package `gov.nasa.jpf.vm.bytecode` (the set of bytecode classes to use can be configured via a `InstructionFactory` class which allows the user to define a different execution semantics) - -### `gov.nasa.jpf.search` ### -This package is relatively small and mainly contains the `Search` class, which is an abstract base for search policies. The major method that encapsulates the policy is `Search.search()`, which is the VM driver (that calls the methods`forward`, `backtrack` and `restore`). This package also contains the plain-vanilla depth-first search policy `DFSearch`. -More policies can be found in the sub-package `gov.nasa.jpf.search.heuristic`, which uses a `HeuristicSearch` class in conjunction with configurable heuristic objects to prioritize a queue of potential successor states. diff --git a/doc/devel/eclipse_plugin_update.md b/doc/devel/eclipse_plugin_update.md deleted file mode 100644 index 35f663f..0000000 --- a/doc/devel/eclipse_plugin_update.md +++ /dev/null @@ -1,36 +0,0 @@ -## Hosting an Eclipse plugin update site ## - -The first step is to create the local version of the update site. For example, chapter 18, section 3 of "Eclipse Plug-ins, 3rd edition" will explain how to do this. - -> **Tip:** do not attempt to put the update site in the code repository. - -The plugin and feature files are treated like binaries and bad things will happen. Here is a sample update site for the mango plugin. - -![Local Site](../graphics/localsite.jpg){align=center width=430} - -Now you will re-create this directory structure within the wiki. For the purpose of this discussion, let's pin down the jpf site: - -~~~~~~~~ {.bash} -JPFHOME=http://babelfish.arc.nasa.gov/trac/jpf -~~~~~~~~ - -Now chose a home directory, say `HOME`. For the mango plugin, - -~~~~~~~~ {.bash} -HOME=wiki/projects/jpf-mango -~~~~~~~~ - -Whatever choice of `HOME` you make, the update site you advertise to the world will be `JPFHOME/raw-attachment/HOME/update/`. - - -The `raw-attachment` segment is the *trick* that makes everything work out. The next step is to create the directory structure for the mirrored update site. Within `JPFHOME/HOME`, create a link to `JPFHOME/HOME/update`. Now go to the update page and add the attachments artifacts.jar, content.jar, and site.xml from your local update site. Create links within `JPFHOME/HOME/update` to `JPFHOME/HOME/update/features` and `JPFHOME/HOME/update/plugins`. - -Attach your feature jar to the features page, and your plugin jar to the plugins page. That's all there is to it. - -> **Tip:** when updating your update site, be sure to sync your plugin and feature with new, higher, revision numbers. Now rebuild the local site. Delete all the corresponding attachments in the wiki, and repopulate with the updated versions. - -> **Bonus tip:** Once everything is working, you can delete the link to the update site. This will prevent your visitors from accidentally going to an uninteresting page. You can always access this page directly from the browser by entering `JPFHOME/HOME/update`. - - - - diff --git a/doc/devel/embedded.md b/doc/devel/embedded.md deleted file mode 100644 index 0ddd1c3..0000000 --- a/doc/devel/embedded.md +++ /dev/null @@ -1,27 +0,0 @@ -# Embedded JPF # -JPF can also be used embedded, i.e. called from another Java application. A basic code sequence to start JPF looks like this: - -~~~~~~~~ {.java} -import gov.nasa.jpf.JPF; -import gov.nasa.jpf.Config; - -void runJPF (String[] args) { - .. - MyListener listener = new MyListener(..); - - // [optionally] if you pass through command line args, - // 'null' any consumed args not to be JPF-processed - listener.filterArgs( args); - .. - - Config config = JPF.createConfig( args); - // set special config key/value pairs here.. - - JPF jpf = new JPF( config); - jpf.addListener( listener); - jpf.run(); - .. -} -~~~~~~~~ - -Of course, you can also call `gov.nasa.jpf.JPF.main(args)` from within your application, if you don't need to control JPF's configuration or process it's output. diff --git a/doc/devel/index.md b/doc/devel/index.md deleted file mode 100644 index 8394c9c..0000000 --- a/doc/devel/index.md +++ /dev/null @@ -1,23 +0,0 @@ -# JPF Developer Guide # - -From the previous two sections, you have learned that JPF has one recurring, major theme: it is not a monolithic system, but rather a configured collection of components that implement different functions like state space search strategies, report generation and much more. Being adaptive is JPF's answer to the scalability problem of software model checking. - -This not only makes JPF a suitable system for research, but chances are that if are you serious enough about JPF application, you sooner or later end up extending it. This section includes the following topics which describe the different mechanisms that can be used to extend JPF. - - * [Top-level design](design) - * Key mechanisms, such as - - [ChoiceGenerators](choicegenerator) - - [Partial order reduction](partial_order_reduction) - - [Slot and field attributes](attributes) - * Extension mechanisms, such as - - [Listeners](listener) - - [Search Strategies](design) - - [Model Java Interface (MJI)](mji) - - [Bytecode Factories](bytecode_factory) - * Common utility infrastructures, such as - - [Logging system](loggin) - - [Reporting system](report) - * [Running JPF from within your application](embedded) - * [Writing JPF tests](jpf_tests) - * [Coding conventions](coding_conventions) - * [Hosting an Eclipse plugin update site](eclipse_plugin_update) \ No newline at end of file diff --git a/doc/devel/jpf_tests.md b/doc/devel/jpf_tests.md deleted file mode 100644 index a445c5a..0000000 --- a/doc/devel/jpf_tests.md +++ /dev/null @@ -1,148 +0,0 @@ -# Writing JPF Tests # - -As a complex runtime system for (almost) arbitrary Java programs, it goes without saying that JPF needs a lot of regression tests. You can find these under the `src/tests` directories in (hopefully) all JPF projects. All tests follow the same scheme, which is motivated by the need to run tests in a number of different ways: - - 1. as part of the Ant-based build system, i.e. from build.xml - 1. as explicitly invoked JUnit tests - 1. by directly running JPF on the test application (i.e. without JUnit, either as a JPF `shell` or via RunTest.jar) - 1. by running the test application on a normal JVM - -The rationale for this is to support various levels of inspection and debugging. - -Each test conceptually consists of a test driver (e.g. executed under JUnit) which starts JPF from within its `@Test` annotated methods, and a class that is executed by JPF in order to check the verification goals. For convenience reasons, jpf-core provides infrastructure that enables you to implement both parts in the same class. This can be confusing at first - **the test class is used to start JPF on itself**. - -![Figure: Unit Testing in JPF](../graphics/new-testing.svg){align=center width=870} - -The `main()` method of `TestJPF` derived classes always look the same and can be safely copied between tests: - -~~~~~~~~ {.java} -public static void main(String[] testMethods){ - runTestsOfThisClass(testMethods); -} -~~~~~~~~ - -This method serves two purposes. First, it is used to start the test outside JUnit, either on all `@Test` annotated instance methods, or just on the ones which names are provided as arguments. Second, it serves as the entry point for JPF when it executes the class. In this case, `TestJPF` takes care of invoking JPF on the test class and providing the name of the test method this was executed from. - -Other than that, test classes just consist of (almost) normal `@Test` annotated JUnit test methods, which all share the same structure - -~~~~~~~~ {.java} -import org.junit.Test; - -@Test public void testX () { - if (verifyNoPropertyViolation(JPF_ARGS){ - .. code to verify by JPF - } -} -~~~~~~~~ - -The trick is the call to `verifyNoPropertyViolation()`, or any of the other `verifyXX()` methods of `TestJPF`. If executed by the host VM, i.e. from JUnit, it starts JPF on the same class and the containing method, and returns `false`. This means the corresponding `if` block is **not** executed by the host VM. - -When JPF is invoked, the argument to the main() method is set to the method name from which JPF got invoked, which causes `runTestsOfThisMethod()` to execute exactly this method again, but this time under JPF. Instead of re-executing the same `TestJPF.verifyX()` method again (and becoming infinitely recursive), we use a native peer `JPF_gov_nasa_jpf_util_test_TestJPF` which intercepts the `verifyX()` call and simply returns true, i.e. this time *only* the `if` block gets executed. - -The rest of the host VM executed `TestJPF.verifyX()` checks the results of the JPF run, and accordingly throws an `AssertionError` in case it does not correspond to the expected result. The most common goals are - - * `verifyNoPropertyViolation` - JPF is not supposed to find an error - * `verifyPropertyViolation` - JPF is supposed to find the specified property violation - * `verifyUnhandledException` - JPF is supposed to detect an unhandled exception of the specified type - * `verifyAssertionError` - same for AssertionErrors - * `verifyDeadlock` - JPF is supposed to find a deadlock - -Each of these methods actually delegate running JPF to a corresponding method whose name does not start with 'verify..'. These workhorse methods expect explicit specification of the JPF arguments (including SUT main class name and method names), but they return JPF objects, and therefore can be used for more sophisticated JPF inspection (e.g. to find out about the number of states). - -`TestJPF` also provides some convenience methods that can be used within test methods to find out which environment the code is executed from: - - * `isJPFRun()` - returns true if the code is executed under JPF - * `isJUnitRun()` - returns true if the code is executed under JUnit by the host VM - * `isRunTestRun()` - returns true if the code is executed by RunTest.jar - -Here is an example of a typical test method that uses some of these features: - -~~~~~~~~ {.java} - @Test public void testIntFieldPerturbation() { - - if (!isJPFRun()){ // run this outside of JPF - Verify.resetCounter(0); - } - - if (verifyNoPropertyViolation("+listener=.listener.Perturbator", - "+perturb.fields=data", - "+perturb.data.class=.perturb.IntOverUnder",... - "+perturb.data.delta=1")){ - // run this under JPF - System.out.println("instance field perturbation test"); - - int d = data; // this should be perturbated - System.out.println("d = " + d); - - Verify.incrementCounter(0); - - } else { // run this outside of JPF - assert Verify.getCounter(0) == 3; - } - } -~~~~~~~~ - -## Running JPF tests from command line ## -To run JPF tests from the command line, use the RunTest.jar either from `jpf-core/build`, or the one that is distributed with your project containing the tests (`tools/RunTest.jar` for JPF projects). This is an executable jar that expects the test class and (optional) method test names as arguments. If no method names are provided, all `@Test` annotated methods are executed. Most projects have a convenience script `bin/test` to execute RunTest.jar. - -~~~~~~~~ {.bash} -> bin/test gov.nasa.jpf.test.mc.data.PerturbatorTest testIntFieldPerturbation - -......................................... testing testIntFieldPerturbation - running jpf with args: +listener=.listener.Perturbator +perturb.fields=data +perturb.data.class=.perturb.IntOverUnder +perturb.data.field=gov.nasa.jpf.test.mc.data.PerturbatorTest.data +perturb.data.delta=1 gov.nasa.jpf.test.mc.data.PerturbatorTest testIntFieldPerturbation -JavaPathfinder v5.x - (C) RIACS/NASA Ames Research Center - - -====================================================== system under test -application: gov/nasa/jpf/test/mc/data/PerturbatorTest.java -arguments: testIntFieldPerturbation - -====================================================== search started: 9/10/10 7:03 PM -instance field perturbation test -d = 43 -d = 42 -... -====================================================== search finished: 9/10/10 7:03 PM -......................................... testIntFieldPerturbation: Ok - -......................................... execution of testsuite: gov.nasa.jpf.test.mc.data.PerturbatorTest SUCCEEDED -.... [1] testIntFieldPerturbation: Ok -......................................... tests: 1, failures: 0, errors: 0 -~~~~~~~~ - -## Running JPF tests under JUnit ## - -This is the preferred way to execute JPF regression tests, which is usually done from an Ant build.xml script containing a standard target such as - -~~~~~~~~ {.xml} - ... - - ... - - - - - ... - - - - - - - - - -~~~~~~~~ - -Most JPF projects have build.xml files you can use as examples. - -Please note this means that you should not have any inner classes, interfaces, annotation types etc. with a name ending with `"Test"` since JUnit would interpret these as test cases and most likely complain about missing constructors and `main()` methods. - -## Debugging tests ## - -Typically, JPF tests are only executed from within an IDE if they fail and need to be debugged. - -Under NetBeans, this can be done by selecting the test class, and then executing the *Debug File* command from the context menu. This will pop up a dialog that lets you enter a specific test method to debug. This method requires a properly set up ide-file-target.xml, which comes with most JPF projects. - -Under Eclipse, you can select the test class and then execute **Debug As..** -> **Java Application**. diff --git a/doc/devel/listener.md b/doc/devel/listener.md deleted file mode 100644 index 98af48c..0000000 --- a/doc/devel/listener.md +++ /dev/null @@ -1,332 +0,0 @@ -# Listeners # -Listeners are perhaps the most important extension mechanism of JPF. They provide a way to observe, interact with and extend JPF execution with your own classes. Since listeners are dynamically configured at runtime, they do not require any modification to the JPF core. Listeners are executed at the same level like JPF, so there is hardly any limit of what you can do with them. - -![Figure 1: JPF Listeners](../graphics/listener-overview.svg){align=center width=800} - -The general principle is simple: JPF provides an observer pattern implementation that notifies registered observer instances about certain events at the search level and the VM level. These notifications cover a broad spectrum of JPF operations, from low level events like `instructionExecuted` to high level events like `searchFinished`. Each notification is parameterized with the corresponding source (either the `Search` or the `VM` instance), which can be then used by the notified listener to obtain more information about the event and the JPF's internal state. - -Configuration is usually done with the `listener` property, either from the command line, or a .jpf property file. Listeners can also be associated with annotations, to be automatically loaded whenever JPF encounters such an annotation. Applications can use the `@JPFConfig` annotation to explicitly specify JPF listeners. Lastly, if JPF is used in an embedded mode, listeners can be registered with an API. - - -## Listener Types ## - - -There are two basic listener interfaces, depending on corresponding event sources: `SearchListeners` and `VMListeners`. Since these interfaces are quite large, and listeners often need to implement both, we also provide "adapter" classes, i.e. implementors that contain all required method definitions with empty method bodies. Concrete listeners that extend these adapters therefore only have to override the notification methods they are interested in. - -The adapter classes are used for the majority of listener implementations, especially since they also support two other interfaces/extension mechanisms that are often used in conjunction with `Search` and `VMListeners`: - - 1. `Property` - to define program properties - 2. `PublisherExtension` - to produce output within [the JPF reporting system](report) - -`ListenerAdapter` is the bare adapter implementation for `SearchListener`, `VMListener` and `PublisherExtension`. This is what is mostly used to collect information during JPF execution (e.g. `CoverageAnalyzer` and `DeadlockAnalyzer`). - -`PropertyListenerAdapter` is used in case the listener implements a program property, i.e. it can terminate the search process. A prominent example of this category is `PreciseRaceDetector`. - -![Figure 2: Listener Types](../graphics/listeners.svg){align=center width=800} - -Choosing the right type for your listener is important, since JPF automatically registers listeners (and properties) based on this type. You can bypass and directly implement single listener interfaces, but then you also have to do the proper registrations. - -Usually, the notification alone is not enough, and the listener needs to acquire more information from JPF. For this purpose, we provide either the `Search` or the `VM` instance as notification arguments, and the listener has to use these as "Facades" to query or interact JPF. It therefore matters to implement the listener within the right package. - - -## SearchListener ## - - -`SearchListener` instances are used to monitor the state space search process, e.g. to create graphical representations of the state-graph. They provide notification methods for all major Search actions. - -~~~~~~~~ {.java} -package gov.nasa.jpf.search; -public interface SearchListener extends JPFListener { - void searchStarted (Search search); - void stateAdvanced (Search search); // got next state - void stateProcessed (Search search); // state is fully explored - void stateBacktracked (Search search); // state was backtracked one step (same path) - void stateStored (Search search); // somebody stored the state - void stateRestored (Search search); // previously generated state was restored (any path) - void propertyViolated (Search search); // JPF encountered a property violation - void searchConstraintHit (Search search); // e.g. max search depth - void searchFinished (Search search); -}} -~~~~~~~~ - - -For the standard depth first search (`gov.nasa.jpf.search.DFSearch`), listener implementations can assume the following notification model: - - -![Figure 3: Depth first listener notifications](../graphics/DFSListener.svg){align=center width=500} - -The most frequently used notifications are: - -`stateAdvanced` - to store additional, backtrackable state information in an associative array - -`stateBacktracked` - to restore additional state information - -`searchFinished` - to process listener results - - -## VMListener ## - - -This is a fat interface, reflecting various VM operations - -~~~~~~~~ {.java} -package gov.nasa.jpf.jvm; -public interface VMListener extends JPFListener { - //--- basic bytecode execution - void executeInstruction (JVM vm); // JVM is about to execute the next instruction - void instructionExecuted (JVM vm); // JVM has executed an instruction - - //--- thread operations (scheduling) - void threadStarted (JVM vm); // new Thread entered run() - void threadBlocked (JVM vm); // thread waits to acquire a lock - void threadWaiting (JVM vm); // thread is waiting for signal - void threadNotified (JVM vm); // thread got notified - void threadInterrupted (JVM vm); // thread got interrupted - void threadTerminated (JVM vm); // Thread exited run() - void threadScheduled (JVM vm); // new thread was scheduled by JVM - - //--- class management - void classLoaded (JVM vm); // new class was loaded - - //--- object operations - void objectCreated (JVM vm); // new object was created - void objectReleased (JVM vm); // object was garbage collected - void objectLocked (JVM vm); // object lock acquired - void objectUnlocked (JVM vm); // object lock released - void objectWait (JVM vm); // somebody waits for object lock - void objectNotify (JVM vm); // notify single waiter for object lock - void objectNotifyAll (JVM vm); // notify all waiters for object lock - - void gcBegin (JVM vm); // start garbage collection - void gcEnd (JVM vm); // garbage collection finished - - void exceptionThrown (JVM vm); // exception was thrown - - //--- ChoiceGenerator operations - void choiceGeneratorSet (JVM vm); // new ChoiceGenerator registered - void choiceGeneratorAdvanced (JVM vm); // new choice from current ChoiceGenerator - void choiceGeneratorProcessed (JVM vm); // current ChoiceGenerator processed all choices -} -~~~~~~~~ - - -The most commonly used methods are the instruction notifications: - -`executeInstruction` - is called before a bytecode instruction gets executed by the VM. The listener can even use this to skip and/or replace this instruction, which is useful for non-invasive instrumentation. - -`instructionExecuted` - is the post-execution notification, which is suitable to keep track of execution results (method invocations, assigned field values, branch results etc.) - - -## Example ## - -The following example is a slightly abbreviated form our race detector. The basic idea is simple: every time we encounter a new scheduling point (i.e. new `ThreadChoiceGenerator` object) that is due to a field access on a shared object, we check if any of the other runnable threads is currently accessing the same field on the same object. If at least one operation is a `putfield`, we have a potential race. - -The example shows three aspects that are quite typical: - - 1. listeners often use only a small number of notification methods - - 2. they often do not require a huge amount of code (most expensive operations are performed by the `VM` and the `Search` objects) - - 3. sometimes you have to dig deep into JPF internal constructs, to extract things like `ThreadInfo`, `FieldInfo` and `ChoiceGenerator` instances - -~~~~~~~~ {.java} -public class PreciseRaceDetector extends PropertyListenerAdapter { - FieldInfo raceField; - ... - //--- the Property part - public boolean check(Search search, JVM vm) { - return (raceField == null); - } - - //--- the VMListener part - public void choiceGeneratorSet(JVM vm) { - ChoiceGenerator cg = vm.getLastChoiceGenerator(); - - if (cg instanceof ThreadChoiceFromSet) { - ThreadInfo[] threads = ((ThreadChoiceFromSet)cg).getAllThreadChoices(); - ElementInfo[eiCandidates = new ElementInfo[threads.length](]); - FieldInfo[fiCandidates = new FieldInfo[threads.length](]); - - for (int i=0; i= 0){ // yes, we have multiple accesses on the same object/field - Instruction otherInsn = threads[idx].getPC(); - if (isPutInsn(otherInsn) || isPutInsn(insn)) { - raceField = ((FieldInstruction)insn).getFieldInfo(); - .. - return; - } - } else { - eiCandidates[i] = ei; - fiCandidates[i] = fi; - } - } - } - } - } - } - - public void executeInstruction (JVM jvm) { - if (raceField != null) { // we're done, report as quickly as possible - ThreadInfo ti = jvm.getLastThreadInfo(); - ti.breakTransition(); - } - } -} -~~~~~~~~ - -## Instantiation ## - -Explicit instantiation of a listener (e.g. from a JPF shell) can be done in any way. If the listener is specified as a JPF property, it's class either needs to have a default constructor, or a constructor that takes a single `gov.nasa.jpf.Config` argument. The `Config` object that is passed into this constructor by JPF is the same that was used for the initialization of JPF itself. This is the preferred method if the listener has to be parameterized. In case of the `PreciseRaceDetector` example, this can be used to filter relevant fields with regular expressions: - -~~~~~~~~ {.java} -public class PreciseRaceDetector extends PropertyListenerAdapter { - ... - StringSetMatcher includes = null; - StringSetMatcher excludes = null; - - public PreciseRaceDetector (Config conf) { - includes = StringSetMatcher.getNonEmpty(conf.getStringArray("race.include")); - excludes = StringSetMatcher.getNonEmpty(conf.getStringArray("race.exclude")); - } - ... - public void choiceGeneratorSet(JVM vm) { - ... - FieldInfo fi =.. - if (StringSetMatcher.isMatch(fi.getFullName(), includes, excludes)) - ... - } -~~~~~~~~ - - -## Configuration ## - -Listener configuration can be done in a number of ways: via JPF properties from the command line or a .jpf file, via JPF APIs from a JPF shell (a program invoking JPF), or from the system under test by using Java annotations (i.e. without code modification). - -Since listeners are executed by the host VM, they have to be in the `CLASSPATH` (`jpf-core.native_classpath` property). - - -### command line ### - - -the *listener* property can be used to specify a colon separated list of listener class names: - -~~~~~~~~ {.bash} -bin/jpf ... +listener=x.y.MyFirstListener,x.z.MySecondListener ... -~~~~~~~~ - - -### .jpf property file ### - - -If you have several listeners and/or a number of other JPF options, it is more convenient to add the `listener` property to a .jpf file: - -~~~~~~~~ {.bash} -# Racer-listener.jpf - JPF mode property file to detect data races in jpftest.Racer -target = jpftest.Racer -listener=gov.nasa.jpf.tools.PreciseRaceDetector -~~~~~~~~ - - -### Autoload Annotations ### - - -Consider your system under test is marked up with a Java annotation that represent properties. For example, you can use the `@NonNull` annotation to express that a method is not allowed to return a `null` value: - -~~~~~~~~ {.java} -import gov.nasa.jpf.NonNull; - ... - @NonNull X computeX (..) { - //.. some complex computation - } - ... -~~~~~~~~ - -You can use .jpf property files (or the command line, if you love to type) to tell JPF that it should automatically load and register a corresponding listener (e.g. `NonNullChecker`) if it encounters such a `@NonNull` annotation during class loading: - -~~~~~~~~ {.bash} -.. -listener.autoload = gov.nasa.jpf.NonNull,... -listener.gov.nasa.jpf.NonNull = gov.nasa.jpf.tools.NonNullChecker -... -~~~~~~~~ - - -### @JPFConfig annotation (SuT) ### - - -You can also explicitly direct JPF to load the listener from within your application by using the `@JPFConfig` annotation: - -~~~~~~~~ {.java} -import gov.nasa.jpf.JPFConfig; -.. -// set JPF properties via properties at class load time -@JPFConfig ({"listener+=.tools.SharedChecker", ..}) -public class TestNonShared implements Runnable { - ... -} -~~~~~~~~ - -However, this is not recommended outside JPF tests - the application would run, but not compile without JPF. - - -### Verify API (SuT) ### - - -A less often used method is to set listeners is to use the `gov.nasa.jpf.vm.Verify` API from within your application. With this, you can control the exact load time of the listener (but be aware of backtracking). With this, the above example would become - -~~~~~~~~ {.java} -import gov.nasa.jpf.vm.Verify; -.. -public class TestNonShared implements Runnable { - ... - public static void main (String[] args){ - - // set JPF properties programmatically - Verify.setProperties("listener+=.tools.SharedChecker", ...); - .. - } -} -~~~~~~~~ - -This method should only be used in special cases (models written explicitly for JPF verification), since it does not run outside JPF. - - -### JPF API (embedded mode) ### - - -If JPF is explicitly started from within another application, listeners can be instantiated at will and configured via the `JPF.addListener(..)` API: - -~~~~~~~~ {.java} -MyListener listener=new MyListener(..); -.. -Config config = JPF.createConfig( args); -JPF jpf = new JPF( config); -jpf.addListener(listener); -jpf.run(); -.. -~~~~~~~~ - -Most listeners tend to fall into three major categories: - -1. system class (e.g. for logging) - is usually configured via the default.properties. -2. complex properties - is configured with an application specific mode property file. -3. JPF debugging - is specified via the command line (`+key=value` overrides). diff --git a/doc/devel/logging.md b/doc/devel/logging.md deleted file mode 100644 index 3993fdf..0000000 --- a/doc/devel/logging.md +++ /dev/null @@ -1,31 +0,0 @@ -# The JPF Logging API # -There is one simple rule: do not use `System.out` or `System.err` for any permanent logging - - -Of course we all do this temporarily during debugging, but it really shouldn't stay in the code. The logging infrastructure is quite easy to use. Just declare a static `Logger` instance with an appropriate id (either package or logging topic) at the top of your class, and then use the `Logger` API to create output: - -~~~~~~~~ {.java} -... -import java.util.logging.Level; -import java.util.logging.Logger; - -package x.y.z; - -class MyClass .. { - static Logger log = JPF.getLogger("x.y.z"); - ... - log.severe("there was an error"); - ... - log.warning("there was a problem"); - ... - log.info("something FYI"); - ... - if (log.isLoggable(Level.FINE)){ // (1) don't create garbage - log.fine("this is some detailed info about: " + something); - } - ... -} -~~~~~~~~ - -Note that there is only one instance for each `Logger` ID, i.e. you can have a corresponding static field in all your relevant classes, and don't have to share the fields. Another aspect that is mostly important for the lower log levels (e.g. `FINE`) is that you should't concatenate log messages in operations that occur frequently, since the corresponding `StringBuilder` instances can cause performance degradations even if the log level is not set (the arguments still get evaluated). In this case, encapsulate the logging in `log.isLoggable(level){..}` blocks. - diff --git a/doc/devel/mercurial.md b/doc/devel/mercurial.md deleted file mode 100644 index b1b3051..0000000 --- a/doc/devel/mercurial.md +++ /dev/null @@ -1,56 +0,0 @@ -# Mercurial in 5 Minutes # - -[Mercurial](http://www.selenic.com/mercurial) is a *distributed version control system* (DVCS) of the same category such as the likes of [Git](http://git-scm.com/) or [Bazaar](http://bazaar.canonical.com/en/). If you know nothing else about DVCS, this means mostly one thing - **all repositories are created equal**. There is no such thing as a different repository format for public and private repositories. All repositories (that are synchronized) have the same, stored history information. - -Yes, this means you can finally synchronize your working repos with more than one "master" repository, e.g. with several local ones, closed workgroup repos, and a public master repo (that just happens to be designated as such). - -Each Mercurial repository consists of an (optional) working copy of your files, and a `.hg` directory in your repo root dir that holds all the version control info. Be careful not to delete the `.hg` dir, otherwise your repo is reduced to just a snapshot of your current working files. - -A central concept of DVCS is the *change set* - think of it as the diff of all files that have been changed when you do a commit. This is what DVCS store (e.g. Mercurial in the `.hg` dir) and compare between different repositories. One implication of this is that you can't do partial commits like in CVS or SVN (e.g. by just committing changes within a certain subdirectory). You always have to execute the Mercurial commands in the top dir of the repository you are working in. - -If you have previously worked with CVS or SVN, another difference you have to wrap your head around is that there are commands that work locally, and commands that interact with the remote repo. __The `commit` and `update` commands are only local__. The `push` and `pull` commands synchronize your local repo with an external one (like commit and update did in CVS/SVN). - -Here are the main commands to interact with Mercurial: - -![](mercurial.png) - -**hg clone ** - this is the first command that clones an external repository (either from `file:///...` or `http://...` URLs). It creates both a working copy and the `.hg` directory (with contents) - -**hg init** - is what you do if you create a local repository for which there is no external one yet. Just create your files, `cd` into the top directory, and execute the command (which will create the `.hg` for you) - -**hg pull [-u] ** - updates the repo you are currently in from the provided URL. Note that your working copy is only updated if you use the `-u` option - -**hg incoming ** - is the little brother of `pull`. It just tells you if there are changesets in the remote repository you would pull - -**hg status** - tells you if there are uncommitted changes in your working copy that have to be committed to the local `.hg` directory before you can `push` or `pull` - -**hg diff** - does a bit more, it also shows you a diff file with the uncommitted changes - -**hg add ** - adds a file to the repo - -**hg remove ** - removes a file from the repo - -**hg addremove** - adds all new files of the working copy that are not in the repository yet, and removes all which are not in the working copy anymore - -**hg commit** - saves changes in your working copy to your local `.hg`. Do this early and often, this is now just a local operation that doesn't change anything outside the repo you are working with - -**hg update** - would update your working copy from your local `.hg`. It is rarely used if you pull with the `-u` option - -**hg push ** - pushes the relevant changesets of your local `.hg` back to the external repo with the provided URL. Make sure you have no uncommitted changes (Mercurial would refuse to push), and - in case the external repo is shared - that you pulled/merged all changesets of the external repo before you push - -**hg outgoing ** - is the dry run version of a push, it tells you if there are changesets that would have to be pushed - -**hg revert** - reverts your working copy to a previous version stored in your local `.hg` - -**hg heads** - tells you if there are branches in your repo, which usually happens if you pull from a changed external repo while having un-pushed local changes that are committed - -**hg merge** - gets rid of multiple heads. Make sure to get rid of these by merging as soon as you detect them, it only gets more difficult with more external and local changes. Once there are collisions, you are back to the CVS/SVN merge mess - -You can always obtain more information by executing -~~~~~~~~ -#!sh -> hg help [command] -~~~~~~~~ -If you don't list a command, all available ones will be displayed. - -Commands that refer to external repos take URLs such as `http://babelfish.arc.nasa.gov/hg/jpf/jpf-core` as arguments. diff --git a/doc/devel/mji.md b/doc/devel/mji.md deleted file mode 100644 index 817cdd1..0000000 --- a/doc/devel/mji.md +++ /dev/null @@ -1,214 +0,0 @@ -# Model Java Interface (MJI) # -## Purpose ## - -Even if it is just a Java application (i.e. solely consists of Java classes), JPF can be viewed as a Java Virtual Machine (JVM) in itself. The consequence is that (*.class) class files, and even the same files at times, are processed in two different ways in a JVM running JPF - - * as ordinary Java classes managed and executed by the host JVM (standard Java library classes, JPF implementation classes) - * as "modeled" classes managed and processed (verified) by JPF - -Class lookup in both layers is based on the CLASSPATH environment variable / command line parameter, but this should not obfuscate the fact that we have to clearly distinguish between these two modes. In particular, JPF (i.e. the "Model" layer) has its own class and object model, which is completely different and incompatible to the (hidden) class and object models of the underlying host JVM executing JPF - -![Figure 1: JPF Layers](../graphics/jpf-layers.svg){align=center width=560} - -Each standard JVM supports a so called Java Native Interface (JNI), that is used to delegate execution from the Java level (i.e. JVM controlled bytecode) down into the (platform dependent) native layer (machine code). This is normally used to interface certain functionalities to the platform OS / architecture (e.g. I/O or graphics). - -Interestingly enough, there exists a analogous need to lower the "execution" level in JPF, from JPF controlled bytecode into JVM controlled bytecode. According to this analogy, the JPF specific interface is called Model Java interface (MJI). - -Even though MJI offers a wide range of applications, there are three major usages for delegating bytecode execution into the host JVM: - - 1. Interception of native methods - without a abstraction lowering mechanism, JPF would be forced to completely ignore native methods, i.e. would fail on applications relying on the side effects of such methods, which is not acceptable (even if many native methods indeed can be ignored if we restrict the set of verification targets) - - 2. Interfacing of JPF system level functionality - some system level functions of standard library classes (esp. java.lang.Class, java.lang.Thread) have to be intercepted even if they are not native because they have to affect the JPF internal class, object and thread model (etc. loading classes, creating / starting threads). It should be noted that MJI can also be used to extend the functionality of JPF without changing its implementation. - -3. State space reduction - by delegating bytecode execution into the non-state-tracked host JVM, we can cut off large parts of the state space, provided that we know the corresponding method side effects are not relevant for property verification (e.g. `System.out.println(..)`) - -Besides these standard usages, there exist more exotic applications like collecting information about JPF state space exploration and making it available both to JPF and the verification target. - - -## MJI Components ## - - -The basic functionality of MJI consists of a mechanism to intercept method invocations, and delegate them by means of Java reflection calls to dedicated classes. There are two types of classes involved, residing at different layers: - - * Model Classes - these classes execute by the VM of JPF, which might be completely unknown to the host JVM - * Native Peers - these classes, implemented by `NativePeer` subclasses, contain the implementations of the methods to intercept, and to execute by the host JVM - -As part of the JPF implementation, MJI automatically takes care of determining which method invocations have to be intercepted by looking up the corresponding native peer methods - -![Figure 2: MJI Functions](../graphics/mji-functions.svg){align=center width=600} - -This would not be very useful without being able to access the JPF object model (or other JPF intrinsics), from inside the native peer methods. Instead of requiring all native peers implementation to reside in a JPF internal package, there exists an interface class `MJIEnv` that provide access to the JPF internal structure in a controlled way. `NativePeer` classes residing in `gov.nasa.jpf.vm` (i.e. the same package as `MJIEnv`) can reach all internal JPF features. Outside this package, the available API in `MJIEnv` is mostly restricted to the access JPF object (getting and setting values). - -![Figure 3: MJI Call Sequence](../graphics/mji-call.svg){align=center width=580} - -Before a native peer method can be used, JPF has to establish the correspondence between the model class and the native peer. This takes place at load time of the model class. MJI uses a special name mangling scheme to lookup native peers, using the model class package name and class name to deduce the native peer class name. - -![Figure 3: MJI name mangling](../graphics/mji-mangling.svg){align=center width=560} - -Since the model class package is encoded in the native peer name, the package of the native peer can be chosen freely. In analogy to JNI, native peers methods names include the signature of the model method by encoding its parameter types. If there is no potential ambiguity, i.e. mapping from native peer methods to model class methods is unique, signature encoding is not required. - -Each native peer, which is an instance of a `NativePeer` subclass, is associated with exactly one `ClassInfo` instance. -All the native peer methods to be intercepted have to be `public` and annotated with `gov.nasa.jpf.annotation.MJI`. -Moreover, MJI requires them to have two parameters: - - * An instance of `MJIEnv` which can be used to access JPF internal constructs - * An integer which is a handle for the corresponding JPF `this` object (or the `java.lang.Class` object in case of a static method) including the method to be intercepted - -See [Mangling for MJI](mji/mangling) for more details and examples of mangling. - -Going beyond the JNI analogy, MJI can also be used to intercept - - * non-native methods (i.e. the lookup process is driven by the methods found in the native peer, not the `native` attributes in the model class. This can be particularly useful in case the class is used from both as a model class and a JVM class (e.g. `gov.nasa.jpf.vm.Verify`), using a method body that directly refers to the native peer - * class initialization (the corresponding native peer method has to be named `$clinit(MJIEnv env, int clsRef)`) - * constructors (the corresponding native peer method has to be named `$init__(MJIEnv env,int objRef, )` and the normal signature mangling rules apply) - - -It is important to note that type correspondence does NOT include references. All references (object types) on the JPF side are transformed in handles (int values) on the JVM side. The passed in `MJIEnv` parameter has to be used to convert/analyze the JPF object. Since MJI per default uses the standard Java reflection call mechanism, there is a significant speed penalty (lookup, parameter conversion etc.), which again is a analogy to JNI. - -Even if it is not directly related to MJI, it should be mentioned that some JPF specific model classes cannot be loaded via the CLASSPATH (e.g. `java.lang.Class`), since they contain JPF based code that is not compatible with the host JVM (e.g. relying on native methods that refer to JPF functionality). Such classes should be kept in separate directories / jars that are specified with the JPF command line option `-jpf-bootclasspath` or `-jpf-classpath`. This is mostly the case for system classes. On the other hand, model classes don't have to be JPF specific. It is perfectly fine to provide a native peer for a standard Java class (e.g. `java.lang.Character`), if only certain methods from that standard class needs to be intercepted. Native peers can contain any number of non-"native" methods and fields, but those should not be annotated with `@MJI` to avoid lookup problems. - -## Tools ## - -To ease the tedious process of manually mangle method names, MJI includes a tool to automatically create skeletons of native peers from a given Model class, called `GenPeer`. The translation process uses Java reflection, i.e. the model class needs to be in the CLASSPATH and is specified in normal dot notation (i.e. not as a file). - -![Figure 4: The GenPeer tool](../graphics/genpeer.svg){align=center width=470} - -There exist a number of command line options that can be displayed by calling `GenPeer` without arguments. `GenPeer` per default writes to stdout, i.e. the output has to be redirected into a file. - -Since method invocation by reflection used to be a slow operation, we previously also had a tool called `GenPeerDispatcher`, which used method signature hash-codes to explicitly dispatch native peer methods. With recent improvements in JVM performance, this tool became obsolete. - - -## Example ## - - -The following example is an excerpt of a JPF regression test, showing how to intercept various different method types, and using `MJIEnv` to access JPF objects. - - -### Model class (JPF side) ### - - -This is executed by JPF, which means it needs to be in JPF's `vm.classpath` setting. - -~~~~~~~~ {.java} -public class TestNativePeer { - static int sdata; - - static { - // only here to be intercepted - } - - int idata; - - TestNativePeer (int data) { - // only here to be intercepted - - } - - public void testClInit () { - if (sdata != 42) { - throw new RuntimeException("native 'clinit' failed"); - } - } - - public void testInit () { - TestNativePeer t = new TestNativePeer(42); - - if (t.idata != 42) { - throw new RuntimeException("native 'init' failed"); - } - } - - native int nativeInstanceMethod (double d, char c, boolean b, int i); - - public void testNativeInstanceMethod () { - - int res = nativeInstanceMethod(2.0, '?', true, 40); - if (res != 42) { - throw new RuntimeException("native instance method failed"); - } - } - - native long nativeStaticMethod (long l, String s); - - public void testNativeStaticMethod () { - long res = nativeStaticMethod(40, "Blah"); - - if (res != 42) { - throw new RuntimeException("native instance method failed"); - - } - } - - native void nativeException (); - - public void testNativeException () { - try { - nativeException(); - } catch (UnsupportedOperationException ux) { - String details = ux.getMessage(); - - if ("caught me".equals(details)) { - return; - } else { - throw new RuntimeException("wrong native exception details: " + - details); - } - } catch (Throwable t) { - throw new RuntimeException("wrong native exception type: " + - t.getClass()); - } - - throw new RuntimeException("no native exception thrown"); - } - } -~~~~~~~~ - - -### Native Peer class (host VM side) ### - - -This is executed by the host VM (i.e. at the same level like JPF itself), so make sure it is in your CLASSPATH. - -~~~~~~~~ {.java} -public class JPF_gov_nasa_jpf_vm_TestNativePeer { - - @MJI - public static void $clinit (MJIEnv env, int rcls) { - env.setStaticIntField(rcls, "sdata", 42); - } - - @MJI - public static void $init__I (MJIEnv env, int robj, int i) { - env.setIntField(robj, "idata", i); - } - - // preferably use full signature mangling - @MJI - public static int nativeInstanceMethod__DCZI__I (MJIEnv env, int robj, - double d, char c, - boolean b, int i) { - if ((d ## 2.0) && (c ## '?') && b) { - return i + 2; - } - return 0; - } - - //..but it also works without, if there is no overloading (don't be lazy!) - @MJI - public static long nativeStaticMethod (MJIEnv env, int rcls, - long l, int stringRef) { - String s = env.getStringObject(stringRef); - if ("Blah".equals(s)) { - return l + 2; - } - return 0; - } - - @MJI - public static void nativeException____V (MJIEnv env, int robj) { - env.throwException("java.lang.UnsupportedOperationException", - "caught me"); - } - } -~~~~~~~~ - diff --git a/doc/devel/mji/mangling.md b/doc/devel/mji/mangling.md deleted file mode 100644 index 5e2847a..0000000 --- a/doc/devel/mji/mangling.md +++ /dev/null @@ -1,200 +0,0 @@ -# Mangling for MJI # -## Mangling Methods ## -Suppose your method looks like - -~~~~~~~~ {.java} -T1 foo(T2 x, T3 y, ...) -~~~~~~~~ - -where the `Ti` are Java types. - -If `T1` is a primitive type or `void`, then the mangled MJI method looks -like - -~~~~~~~~ {.java} -public static T1 foo__MT2MT3...__MT1(...) -~~~~~~~~ - -where the `MTi` are the mangled versions of the `Ti`. -Mangling of types is described in the Mangling Types section below. -Note that `T1` appears twice, once not mangled (`T1`) and once mangled -(`MT1`). The `__` is two consecutive underscores: `_` followed by -`_`. - -As a not-so-special case, if `foo` has no arguments, then the mangled method -will have four consecutive underscores: - -~~~~~~~~ {.java} - `T1 foo()`[[br]] -~~~~~~~~ - -goes to - -~~~~~~~~ {.java} - `public static T1 foo____MT1(...)` -~~~~~~~~ - -If `T1` is not a primitive type, then the mangled `MJI` method looks like - -~~~~~~~~ {.java} - `public static int foo__MT2MT3...__MT1` -~~~~~~~~ - -where the `MTi` are as above. Note that `T1` only appears once in this -case. The method's return type is `int`. As before, a method with no -arguments gets mangled to something with four consecutive underscores. - -Also, the use of generics is ignored when mangling names. - - -## Mangling Constructors ## -Constructors are treated as methods named `$init` with return type `void`. - - -## Mangling Static Initializers ## -Static initializers are treated as methods named `$clinit` with no -arguments and return type `void`. Thus, their MJI versions always -have the mangled signature: - -~~~~~~~~ {.java} -public static void $clinit____V (MJIEnv env, int clsObjRef) -~~~~~~~~ - -or the equivalent unmangled signature: - -~~~~~~~~ {.java} -public static void $clinit (MJIEnv env, int clsObjRef) -~~~~~~~~ - - -## Mangling Types ## - - Convert primitives and `void` as follows - - |Java Type|Mangled Type| - | ------- |:---:| - |`boolean`|`Z`| - |`byte` |`B`| - |`char` |`C`| - |`short` |`S`| - |`int` |`I`| - |`long` |`J`| - |`float` |`F`| - |`double` |`D`| - |`void` |`V`| - - - Convert a non-array reference type `T` in package `x.y` - (e.g. `java.lang.String`) as follows - - `x.y.T` --> `Lx_y_T_2` - - Example: `java.lang.String` --> `Ljava_lang_String_2` - - - Convert an array of primitive type `T` - (e.g. `byte[]`) as follows: - - `T[]` --> `_3MT` where `MT` is the mangled version of `T` - (e.g. for `T=byte`, `MT=B`) - - Example: `byte[]` --> `_3B` - - - Convert an array of reference type `T` in package `x.y` - (e.g. `java.lang.String[]`) as follows: - - `x.y.T[]` --> `_3Lx_y_T_2` - - Example: `java.lang.String[]` --> `_3Ljava_lang_String_2` - - -## Method Examples ## - - `void` return type, single primitive argument: - -~~~~~~~~ {.java} - public static void resetCounter(int id) ---> - public static final void resetCounter__I__V(MJIEnv env, int objref, int id) -~~~~~~~~ - - Primitive return type, no arguments: - -~~~~~~~~ {.java} - public native boolean isArray() ---> - public static boolean isArray____Z(MJIEnv env, int objref) -~~~~~~~~ - - Primitive return type, single primitive argument: - -~~~~~~~~ {.java} - public static double abs(double a) ---> - public static double abs__D__D(MJIEnv env, int clsObjRef, double a) -~~~~~~~~ - - Primitive return type, two primitive arguments: - -~~~~~~~~ {.java} - public static long min(long a, long b) ---> - public static long min__JJ__J(MJIEnv env, int clsObjRef, long a, long b) -~~~~~~~~ - - - `void` return type, arguments include an array of a primitive type: - -~~~~~~~~ {.java} - public native void write (byte[] buf, int off, int len); ---> - public static void write___3BII__V(MJIEnv env, int objref, - int bufRef, int off, int len) -~~~~~~~~ - - - `void` return type, argument is an array of a reference type: - -~~~~~~~~ {.java} - public static void print(String s) ---> - public static void print___3Ljava_lang_String_2__V(MJIEnv env, int clsRef, int argsRef) -~~~~~~~~ - - Array of reference types returned, no arguments: - -~~~~~~~~ {.java} - public native Annotation[] getAnnotations() ---> - public static int getAnnotations_____3Ljava_lang_annotation_Annotation_2(MJIEnv env, int robj) -~~~~~~~~ - Notice there are 5 underscores before the `3L`: two marking the - arguments, two marking the return type, and one from the `_3` - signalling an array. - - Array of reference types using generics returned, no arguments: - -~~~~~~~~ {.java} - public native Class[] getParameterTypes() ---> - public static int getParameterTypes_____3Ljava_lang_Class_2(MJIEnv env, int objref) -~~~~~~~~ - -Note: the use of generics is ignored in the mangling. - - - -## Constructor Examples ## - -Constructors are treated as though they were methods named `$init` -returning `void`, so the method examples above should also be helpful -for constructors. Here are a few more examples. - -In the class `ConsoleOutputStream`: - -~~~~~~~~ {.java} - public ConsoleOutputStream() ---> - public static void $init____V(MJIEnv env, int objref) -~~~~~~~~ - -In the class `AtomicLongFieldUpdater`: - -~~~~~~~~ {.java} - protected AtomicLongFieldUpdater(Class objClass, String fieldName) ---> - public static void $init__Ljava_lang_Class_2Ljava_lang_String_2__V - (MJIEnv env, int objRef, - int tClsObjRef, int fNameRef) -~~~~~~~~ diff --git a/doc/devel/modules.md b/doc/devel/modules.md deleted file mode 100644 index 45e84d7..0000000 --- a/doc/devel/modules.md +++ /dev/null @@ -1,21 +0,0 @@ -# JPF Runtime Modules # - -JPF is partitioned into separate projects that all follow the same directory layout and build process. Modules can be distributed as source or binary distributions. Binary distributions are just slices through the directory tree of a source distribution that preserve the permanent build artifact, i.e. both distribution forms are runtime-compatible. - -![Figure: JPF Modules](../graphics/jpf-project.svg){align=center width=750} - -The main artifacts are the *.jar files created and stored in the `build` directory. We can divide this into classes that are executed by the host VM (i.e. have to be in JPF's `native_classpath` setting), and classes that are executed by JPF itself (i.e. have to be in JPF's `classpath` setting). The first category includes [listeners](listener) and [native peers](mji), the second one model classes (compiled from `src/classes`) and annotations, i.e. the system under test code. - -The build process is [Ant](http://ant.apache.org/) based, which means every source distribution comes with a build.xml script that implements the basic build targets `clean`, `compile`, `build` and `test`. - -We do not include required 3rd party runtime and build libraries in the project distributions. -The `compile` Ant target uses the standard `javac` command which requires a full JDK installation. `test` generally executes a JUnit based regression test suite. Both JUnit and Ant libraries are also need to be installed. - - - - - - - -For convenience reasons, JPF modules come with corresponding NetBeans and Eclipse configurations, i.e. can be directly opened as projects within these IDEs. - diff --git a/doc/devel/partial_order_reduction.md b/doc/devel/partial_order_reduction.md deleted file mode 100644 index 7077a48..0000000 --- a/doc/devel/partial_order_reduction.md +++ /dev/null @@ -1,67 +0,0 @@ -# On-the-fly Partial Order Reduction # - -The number of different scheduling combinations is the prevalent factor for the state space size of concurrent programs. Fortunately, for most practical purposes it is not necessary to explore all possible instruction interleavings for all threads. The number of scheduling induced states can be significantly reduced by grouping all instruction sequences in a thread that cannot have effects outside this thread itself, collapsing them into a single transition. This technique is called partial order reduction (POR), and typically results in more than 70% reduction of state spaces. - -JPF employs an on-the-fly POR that does not rely on user instrumentation or static analysis. JPF automatically determines at runtime which instructions have to be treated as state transition boundaries. If POR is enabled (configured via `vm.por` property), a forward request to the VM executes all instructions in the current thread until one of the following conditions is met: - - - the next instruction is scheduling relevant - - the next instruction yields a "nondeterministic" result (i.e. simulates random value data acquisition) - -Detection of both conditions are delegated to the instruction object itself (`Instruction.execute()`), passing down information about the current VM execution state and threading context. If the instruction is a transition breaker, it creates a ChoiceGenerator and schedules itself for re-execution. - -~~~~~~~~ {.java} -executeStep () { - .. - do { - if ((nextPc # executeInstruction()) #= pc) { - break; - } else { - pc = nextPc; - } - .. - } while (pc != null); - .. -} -~~~~~~~~ - -Each bytecode instruction type corresponds to a concrete gov.nasa.jpf.Instruction subclass that determines scheduling relevance based on the following factors: - - * **Instruction Type** - due to the stack based nature of the JVM, only about 10% of the Java bytecode instructions are scheduling relevant, i.e. can have effects across thread boundaries. The interesting instructions include direct synchronization (`monitorEnter`, `monitorexit`, `invokeX` on synchronized methods), field access (`putX`, `getX`), array element access (`Xaload`, `Xastore`), and invoke calls of certain Thread (`start()`, `sleep()`, `yield()`, `join()`) and Object methods (`wait()`, `notify()`). - * **Object Reachability** - besides direct synchronization instructions, field access is the major type of interaction between threads. However, not all putX / getX instructions have to be considered, only the ones referring to objects that are reachable by at least two threads can cause data races. While reachability analysis is an expensive operation, the VM already performs a similar task during garbage collection, which is extended to support POR. - * **Thread and Lock Information** - even if the instruction type and the object reachability suggest scheduling relevance, there is no need to break the current transition in case there is no other runnable thread. In addition, lock acquisition and release (`monitorenter`, `monitorexit`) do not have to be considered as transition boundaries if there they happen recursively - only the first and the last lock operation can lead to rescheduling. - -![Figure 1: Scheduling Relevance Filters](../graphics/por-scheduling-relevance.svg){align=center width=650} - -While JPF uses these informations to automatically deduce scheduling relevance, there exist three mechanisms to explicitly control transition boundaries (i.e. potential thread interleavings) - - 1. `Attributor` - a configurable concrete class of this type is used by JPF during class loading to determine object, method and field attributes of selected classes and class sets. The most important attributes with respect to POR are method atomicity and scheduling relevance levels: (a) never relevant, (b) always scheduling relevant, (c) only relevant in the context of other runnables. (d) only relevant of top-level lock. The default Attributor executes all java code atomically, which is can be too aggressive (i.e. can cause `BlockedAtomicExceptions`). - - 2. `VMListener` - a listener can explicitly request a reschedule by calling `ThreadInfo.yield()` in response of a instruction execution notification. - - 3. `Verify` - a class that serves as an API to communicate between the test application and JPF, and contains `beginAtomic()`, `endAtomic()` functions to control thread interleaving - -The main effort of JPFs POR support relates to extending its precise mark and sweep collector. POR reachability is a subset of collector reachability, hence the mechanism piggybacks on the mark phase object traversal. It is complicated by the fact that certain reference chains exist only in the (hidden) VM implementation layer. For instance, every thread has a reference to its ThreadGroup, and the ThreadGroup objects in turn have references to all included threads, hence - from a garbage collection perspective - all threads within a group are mutually reachable. If the application under test does not use Java reflection and runtime queries like thread enumeration, POR reachability should follow accessibility rules as closely as possible. While JPF's POR does not yet support protected and private access modifiers, it includes a mechanism to specify that certain fields should not be used to promote POR reachability. This attribute is set via the configured Attributor at class load time. - -![Figure 2: Mark Phase of Reachability Analysis](../graphics/por-mark.svg){align=center width=460} - -With this mechanism, calculating POR reachability becomes a straight forward approach that is divided into two phases. Phase 1 non-recursively marks all objects of the root set (mostly static fields and thread stacks), recording the id of the referencing thread. In case an object is reachable from a static field, or from two threads, it's status is set to shared. Phase 2 recursively traverses all heap objects, propagating either a set shared status or the referencing thread id through all reference fields that are not marked as reachability firewalls. Again, if the traversal hits an object that is already marked as referenced by another thread, it promotes the object status to shared, and from there propagates the shared status instead of the thread id. - -To further reduce irrelevant context switches, JPF can check for lock protection to determine if a field access is scheduling relevant. If the property `vm.por.sync_detection` is set to true, JPF looks for potential lock candidates when analyzing `GET_x/SET_x` instructions. The policy of detecting lock candidates is configurable with the property `vm.por.fieldlockinfo.class`, the default `gov.nasa.jpf.jvm.StatisticFieldLockInfo` just defers the decision by recording the set of locks held when executing the field instruction, computing the set intersection at subsequent accesses. If the set does not get empty for a configurable number of field accesses, the field is marked as lock protected, and henceforth not treated as transition boundary. If however the set should afterwards become empty, a warning like - -~~~~~~~~ {.bash} -Warning: unprotected field access of: Event@70.count in thread: "Thread-1" oldclassic.java:107 - sync-detection assumed to be protected by: Event@70 - found to be protected by: {} - >>> re-run with 'vm.por.sync_detection=false' or exclude field from checks <<< -~~~~~~~~ - -is issued, and the field access is again treated as transition breaker. - -The set of fields to be analyzed can be specified with the properties `vm.por.include_fields` and `vm.por.exclude_fields`. Per default, fields of system library classes are not analyzed (this is esp. useful to avoid context switches for global objects like `System.out`). - -Even with all these optimizations, some unwanted transition breakers are likely to remain. This is mostly due to two constraints: - - * JPF only considers reachability, not accessibility - * write once, read multiple conditions cannot be detected a priori for fields that are not final, or inside immutable objects (like `java.lang.String`) - -Especially the last issue might be subject to further enhancements diff --git a/doc/devel/report.md b/doc/devel/report.md deleted file mode 100644 index aecfd6b..0000000 --- a/doc/devel/report.md +++ /dev/null @@ -1,70 +0,0 @@ -# The JPF Report API # -The JPF report system consists of three major components: - - - the `Reporter` - - any number of format specific `Publisher` objects - - any number of tool-, property-, Publisher-specific `PublisherExtension` objects - -Here is the blueprint: - -![Figure: JPF Report System](../graphics/report.svg){align=center width=800} - -The `Reporter` is the data collector. It also manages and notifies `Publisher` extensions when a certain output phase is reached. The `Publishers` are the format (e.g. text, XML) specific output producers, the most prominent one being the `ConsolePublisher` (for normal, readable text output on consoles). `PublisherExtensions` can be registered for specific `Publishers` at startup time, e.g. from Listeners implementing properties or analysis modes such as `DeadlockAnalyzer`. This is so common that the `ListenerAdapter` actually implements all the required interface methods so that you just have to override the ones you are interested in. - -Configuration is quite easy, and involves only a handful of JPF properties that are all in the report category. The first property specifies the Reporter class itself, but is not likely to be redefined unless you have to implement different data collection modes. - -~~~~~~~~ {.bash} -report.class=gov.nasa.jpf.report.Reporter -~~~~~~~~ - -The next setting specifies a list of Publisher instances to use, using symbolic names: - -~~~~~~~~ {.bash} -report.publisher=console,xml -~~~~~~~~ - -Each of these symbolic names has to have a corresponding class name defined: - -~~~~~~~~ {.bash} -report.console.class=gov.nasa.jpf.report.ConsolePublisher -~~~~~~~~ - -Finally, we have to specify for each symbolic publisher name and output phase what topics should be processed in which order, e.g. - -~~~~~~~~ {.bash} -report.console.property_violation=error,trace,snapshot -~~~~~~~~ - -Again, the order of these topics matters, and gives you complete control over the report format. As usual, please refer to `defaults.properties` for default values. - -Publisher classes can have their own, additional properties. For instance, the `ConsolePublisher` implementation can be further configured with respect to the information that is included in traces (bytecodes, method names etc.), and to redirect output (file, socket). Please refer to the constructor of this class for further details. - -~~~~~~~~ {.bash} -# save report to file -report.console.file=My_JPF_report -~~~~~~~~ - -All of the involved core classes and interfaces reside in the `gov.nasa.jpf.report` package. The most common way to extend the system is to use your own `PublisherExtension` implementation, which involves two steps: - - - implement the required phase and format specific methods - - register the extension for a specific Publisher class - - -The `DeadlockAnalyzer` (which is a listener to analyze concurrency defects) can be used as an example of how to do this: - -~~~~~~~~ {.java} -public class DeadlockAnalyzer extends ListenerAdapter { - ... - public DeadlockAnalyzer (Config config, JPF jpf){ - jpf.addPublisherExtension(ConsolePublisher.class, this); // (1) - ... - } - ... - public void publishPropertyViolation (Publisher publisher) { // (2) - PrintWriter pw = publisher.getOut(); - publisher.publishTopicStart("thread ops " + publisher.getLastErrorId()); - - ... // use 'pw' to generate the output - } -} -~~~~~~~~ diff --git a/doc/graphics/DFSListener.svg b/doc/graphics/DFSListener.svg deleted file mode 100644 index 1684827..0000000 --- a/doc/graphics/DFSListener.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2005-10-21 18:50:44 +0000Canvas 1Layer 1searchStartedsearchFinishedstateAdvancedpropertyViolatedstateBacktrackedsearchConstraintHit diff --git a/doc/graphics/app-types.svg b/doc/graphics/app-types.svg deleted file mode 100644 index f845707..0000000 --- a/doc/graphics/app-types.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2015-01-05 22:17:29 +0000App TypesLayer 1non-functional properties ■ unhandled exceptions (incl. AssertionError) ■ deadlocks ■ racesrestricted choice types ■ scheduling sequences ■ java.util.Random improved inspection ■ coverage statistics ■ exact object counts ■ execution costsconstraintsbenefitsrestricted application models ■ UML statemachines ■ does not run w/o JPF libraries runtime costs ■ order of magnitude slower ■ state storage memorystandard library support ■ java.net, javax.swing, .. (needs abstraction models) functional (domain) properties ■ built-in into JPF librariesfunctional property impl. costs ■ listeners, MJI knowledgeflexible state space ■ domain specific choices (e.g. UML "enabling events")runtime costs & library support ■ usually not a problem, domain libs can control state spaceruns on anyJVMruns onlyunder JPFlow modeling costs ■ statemachine w/o layout hassle,..initial domain impl. costs ■ domain libs can be tricky "sweet spot"annotate program ■ requirements ■ sequences (UML) ■ contracts (PbC) ■ tests … analyze program ■ symbolic exec → test data ■ thread safety / races *.class*.java@V*.javaJPF unawareprogramsJPF enabledprogramsJPF dependentprograms diff --git a/doc/graphics/attributes.svg b/doc/graphics/attributes.svg deleted file mode 100644 index 2aa20a4..0000000 --- a/doc/graphics/attributes.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-16 18:21:11 +0000Canvas 1Layer 1dup(), push(), pop(), ..------getOperandAttr(idx)setOperandAttr(idx,obj)getLocalAttr(idx)setLocalAttr(idx,obj)int[] localsObject[] localAttrint[] operandsObject[] operandAttrStackFramegetIntValue(idx), ...setIntValue(idx, v), ...------getFieldAttr(idx)setFieldAttr(idx,obj)getObjectAttr()setObjectAttr(obj)int[] valuesObject[] fieldAttrsObject objectAttrFieldslocalsvaluesattributesoperandsslotsfield-valuesattributesputfieldgetfielddup..iload..istore..invokevirtual..return..attributeobjectsetAttr(i,o)getAttr(i)- listener- Instruction- native peerget?Attr(i)set?Attr(i,o)JPF coreJPFextensionattribute APIobject-attrThreadInfoElementInfo diff --git a/doc/graphics/bc-factory.svg b/doc/graphics/bc-factory.svg deleted file mode 100644 index f69c951..0000000 --- a/doc/graphics/bc-factory.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-16 18:32:22 +0000Canvas 1Layer 1*.classInstruction ifeq(tgt)...«interface»InstructionFactory...Instruction execute()InstructionIFEQIFEQ......Instruction execute (){.. cond = popCondition() if (cond) return jumpTarget else return getNextInsn()setCode(code)factoryInstruction[] codeMethodInfoconcrete execution semanticsabstract execution semanticsconcrete valueexecutionsymbolic valueexecutioninstruction setInstruction execute(){.. if (!firstStepInsn()){ setNextCG(new PCChoiceGenerator()) return this } popCondition() // not interested cond = getCG().getNextChoice() if (cond){... return jumpTarget } else {... return getNextInsn()per bytecodefactory methodsInstruction ifeq(tgt)...gov.nasa.jpf.jvm.bytecodeInstructionFactoryInstruction ifeq(tgt)...gov.nasa.jpf.symbcSymbolicInstructionFactoryInstruction ifeq(int jumpTarget){ return new IFEQ(jumpTarget)ClassInfoClassFileCodeBuilderConfigvm.insn_factory.class=... diff --git a/doc/graphics/cg-impl.svg b/doc/graphics/cg-impl.svg deleted file mode 100644 index 07a14cb..0000000 --- a/doc/graphics/cg-impl.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-02 07:14:49 +0000Canvas 1Layer 1initNextTransition(){... curCg = nextCg nextCg = null curCg.advance() ..setExecThread() ...executeTransition(){.. isFirstStepInsn = true while (pc != null) { nextPc = executeInstruction() if (ss.breakTransition()) break else pc = nextPc isFirstStepInsn = falseexecute(){.. if (!ti.isFirstStepInsn()) { ChoiceGenerator cg = ..createMonitorEnterCG(..) if (cg != null){ ss.setNextChoiceGenerator(cg) return this // repeat } ei.lock(ti) return getNextPc(ti);execute()InstructioninitNextTransition()breakTransition()setNextChoiceGenerator()nextCgcurCgSystemStatehasMoreChoices()advance()ChoiceGeneratorgetNextChoice()threadSetThreadCGgetNextChoice()doubleSetDoubleCG......executeTransition()executeInstruction()isFirstStepInsn(){pc, nextPc}ThreadInfoMonitorEnterInvoke.....MethodInfoNativePeere.g. JPF_gov_nasa_jpf_vm_Verify.getBoolean(env)top half: executed on first invocationoptionally sets next CG and reexecutesbottom half: executed on revisit (orif no CG created because of policy)does semantic action based oncurrent CGs choicescheduling choicesdata acquisition choices123top halfbottomhalfif (!ti.isFirstStepInsn()){ cg = new BooleanCG() ss.setNextChoiceGenerator(cg) env.repeatInvocation() ..} else { cg = ss.getChoiceGenerator() return ((BooleanCG)cg).getNextChoice()}breakTransition(){... return nextCg != null diff --git a/doc/graphics/cg-motivation.svg b/doc/graphics/cg-motivation.svg deleted file mode 100644 index e8c750c..0000000 --- a/doc/graphics/cg-motivation.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2010-02-22 05:27:10 +0000Canvas 1Layer 1T ± Δ.. double v = Verify.getDouble("velocity"); ..velocity.class = gov.nasa.jpf.jvm.choice.DoubleThresholdGeneratorvelocity.threshold = 13250velocity.delta = 500application code(test driver)configuration (e.g. mode property file)C = { T-Δ, T, T+ Δ }Verify.getBoolean()Verify.getInt(0,4)Verify.getDouble(1.0,1.5)C = { true, false }C = { 0, 1, 2, 3, 4 }✓?potentially large sets with lots of uninteresting values??no finite value set without heuristicsC = { ∞ }e.g. "Threshold" heuristicChoice Generators+Configurable Heuristic Choice ModelsJPF internal object to store and enumerate a set of choicesconfigurable classes tocreate ChoiceGenerator instanceshasMoreChoices()advance()getNextChoice() → xchoiceSet: {x}xChoiceGenerator diff --git a/doc/graphics/cg-ontology.svg b/doc/graphics/cg-ontology.svg deleted file mode 100644 index fab55e3..0000000 --- a/doc/graphics/cg-ontology.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2010-02-22 02:58:46 +0000Canvas 1Layer 1TransitionStateChoiceScheduling ChoiceData Choiceboolean b = Verify.getBoolean();double d = Verify.getDouble("MyHeuristic");..synchronized (..) {..}wait (..)x = mySharedObject..Control Choiceif (<cond>) ..INVOKECG.setInvocations(..).. diff --git a/doc/graphics/cg-sequence.svg b/doc/graphics/cg-sequence.svg deleted file mode 100644 index 5e0ff92..0000000 --- a/doc/graphics/cg-sequence.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2006-05-05 17:02:45 +0000Canvas 1Layer 1......get_field...monitor_enter...get_fieldmonitor_enter...ChoiceGeneratorTjTj+1Tj+2CGkCGlsetNextCGgetNextChoiceTransitionc1kc2kc3kSkc1kc2k{{}},==Statebacktrackadvancec2k,c1l...,execute{Instruction}Sl diff --git a/doc/graphics/choicegen-example.svg b/doc/graphics/choicegen-example.svg deleted file mode 100644 index 675ec8d..0000000 --- a/doc/graphics/choicegen-example.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2006-05-03 17:51:17 +0000Canvas 1Layer 1T ± Δ.. double v = Verify.getDouble("velocity"); ..velocity.class = DoubleThresholdvelocity.threshold = 13250velocity.delta = 500application code(test driver)configuration (e.g. mode property file)C = { T-Δ, T, T+ Δ }Verify.getBoolean()Verify.getInt(0,4)Verify.getDouble(1.0,1.5)C = { true, false }C = { 0, 1, 2, 3, 4 }✓?potentially large sets with lots of uninteresting values??no finite value set without heuristicsC = { ∞ }e.g. "DoubleThresholdChoice"Choice Generators+Configurable Heuristic Choice ModelsJPF internal object to store and enumerate a set of choicesconfigurable classes tocreate ChoiceGenerator instanceshasMoreChoices()advance()getNextChoice() → xchoiceSet: {x}xChoiceGenerator diff --git a/doc/graphics/genpeer.svg b/doc/graphics/genpeer.svg deleted file mode 100644 index 6887428..0000000 --- a/doc/graphics/genpeer.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-04 01:29:55 +0000Canvas 1Layer 1GenPeerpackage x.y.z;class MyClass { ... native String foo (int i, String s);}class JPF_x_y_z_MyClass { ... @MJI public static int foo__ILjava_lang_String__2 (MJIEnv env, int objRef, int i, int sRef) { int ref = MJIEnv.NULL; // <2do> fill in body return ref; }}"java gov.nasa.jpf.GenPeer x.y.z.MyClass > JPF_x_y_z_MyClass.java" diff --git a/doc/graphics/interleavings.svg b/doc/graphics/interleavings.svg deleted file mode 100644 index 4dfa19e..0000000 --- a/doc/graphics/interleavings.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-11-19 20:18:08 +0000Canvas 1Layer 1.........12P1P2PNn1n2...AtomicInstructionsThreads12I1∑niIM......nN.........Interleavings(∑ n )!∏ (n !)Ni=1iNi=1iM = diff --git a/doc/graphics/jpf-abstractions.svg b/doc/graphics/jpf-abstractions.svg deleted file mode 100644 index b636c6f..0000000 --- a/doc/graphics/jpf-abstractions.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-11-26 21:24:31 +0000Canvas 1Layer 1search ()VM vmSearchforward ()backtrack ()restoreState ()VMsearch ()DFSearchrun ()search, vm, configJPFexecuteTransition ()executeInstruction ()ThreadInfoinitializeNextTransition()executeNextTransition()SystemStateClassInfoMethodInfoFieldInfoElementInfoFieldsMonitorStaticsbytecode executiontype + codemgntobjectmodelgov.nasa.jpfgov.nasa.jpf.searchsearch ()HeuristicSearchgov.nasa.jpf.vmgov.nasa.jpf.search.heuristicgov.nasa.jpf.vm.bytecodeexecute ()Instruction.........search ()BFSHeuristic...while (notDone) { ..vm.forward(); ..vm.backtrack(); if (!properties.check()){ reportError(); break; ...search.class=...vm.class=...push (), pop() ...StackFrameConfigHeap diff --git a/doc/graphics/jpf-basic.svg b/doc/graphics/jpf-basic.svg deleted file mode 100644 index fdfae11..0000000 --- a/doc/graphics/jpf-basic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-11-19 18:37:23 +0000Canvas 1Layer 1JPF*.classreport*.jpfSystem under Test(Java bytecode)Verification ResultJPF ConfigurationProperties to Verify diff --git a/doc/graphics/jpf-intro-new.svg b/doc/graphics/jpf-intro-new.svg deleted file mode 100644 index 56fc211..0000000 --- a/doc/graphics/jpf-intro-new.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2009-04-10 01:07:23 +0000Canvas 1Layer 1------------------------------------ error path..Step #14 Thread #1 oldclassic.java:95 event2.waitForEvent(); oldclassic.java:37 wait();------------------------------------ thread stacksThread: Thread-0 at java.lang.Object.wait(Object.java:429) at Event.waitForEvent(oldclassic.java:37) ..======================== 1 Error Found: DeadlockJPFCorebytecodesetlistener/propertypublisher/ -extchoicegeneratorserializer/restorerannotation (optional) in-sourceproperty specdomainframeworkmodellibraryapplicationSuTexecutionenvironmentsearchstrategyJavavirtualmachinebytecodereportJPFendseenerror-pathproperty violationhost - JVMJPF distribution...nativepeer......extensions*.jpfJPF configurationreportstandardJava libraries*.jar*.jar diff --git a/doc/graphics/jpf-layers.svg b/doc/graphics/jpf-layers.svg deleted file mode 100644 index ada4957..0000000 --- a/doc/graphics/jpf-layers.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-02 21:48:18 +0000Canvas 1Layer 1platform OShost JVMnative librarieslibrary classesJPF (Java application)modeled classesrt.jarJNIMJI*.classsystem under teststandard Java installationCLASSPATHModel layerJava layerNative layer"Java Native Interface""Model Java Interface" diff --git a/doc/graphics/jpf-project.svg b/doc/graphics/jpf-project.svg deleted file mode 100644 index 790b51b..0000000 --- a/doc/graphics/jpf-project.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2009-09-09 23:36:00 +0000Canvas 1Layer 1jpf-Xsrcbuildbuild.xmljpf.propertiesX.jarX-classes.jarX-annotations.jarmainpeersclassesannotationstestsexampleslibtoolsbinRunJPF.jarRunAnt.jarjpfantnbprojectproject.xmlide-file-targets.xml.classpathmainpeersclassesannotationstestsexampleseclipserun-jpf.launchJPF project properties file(runtime def: native_classpath, classpath, sourcepath)host-VM executed classes (listeners, infrastructure etc.)host-VM executed library classes (MJI native peers)JPF executed library classes →sourcepathJPF processed Java annotationsregression testsdemos →sourcepathAnt build script (compile, build, test, clean)temporary build artifacts (classfiles)main host-VM executed project jar (main,peers →native_classpath)JPF executed library jar (classes,annotations →classpath)separate anotations jar (for JPF external SUT exec)required runtime jars →native_classpathbuild toolsant.jar, junit.jar, ...bcel.jar, antlr.jar, ..(example) 3rd party jarsbuild artifactspermanent build artifacts(example) 3rd party jarsJPF startup jar (executable)JPF build jar (executable)scriptsJPF startup script (→RunJPF.jar)JPF build script (→RunAnt.jar)Eclipse project configurationproject sourcesproject root directorybinary distributionNetBeans project configurationNetBeans file actions (JPF execution)Eclipse launch configs (JPF execution)IDE supportcompilebuildtest diff --git a/doc/graphics/listener-overview.svg b/doc/graphics/listener-overview.svg deleted file mode 100644 index 8a58bd9..0000000 --- a/doc/graphics/listener-overview.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-02 07:42:37 +0000Canvas 1Layer 1SearchVMJPFSystem under testlistenersexecuted by JPFexecuted by host JVMsearch event notificationsexecution event notificationsconfigured- classLoaded (vm)- threadScheduled (vm)- threadNotified (vm) ...- executeInstruction (vm)- instructionExecuted (vm) ...- objectCreated (vm) ...- exceptionThrown(vm) ...- choiceGeneratorAdvanced (vm) ...- stateAdvanced (search)- stateBacktracked (search)- propertyViolated (search)- searchFinished (search) ...- +listener=<listener-class>- @JPFConfig(..)- listener.autoload=<annotations>- jpf.addListener(..) ...≪SearchListener≫≪VMListener≫ diff --git a/doc/graphics/listeners.svg b/doc/graphics/listeners.svg deleted file mode 100644 index 681d1ad..0000000 --- a/doc/graphics/listeners.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2009-04-08 19:52:28 +0000Canvas 1Layer 1«interface»JPFListenerexecuteInstruction(vm)instructionExecuted(..)threadStarted(..)objectCreated(..)choiceGeneratorSet(..)choiceGeneratorAdvanced(..). . .«interface»VMListenersearchStarted(search)stateAdvanced(..)stateBacktracked(..)propertyViolated(..)searchFinished(..). . .«interface»SearchListenercheck(search,vm)getErrorMessage()«interface»Propertycheck(search,vm) {}. . .GenericPropertyinstructionExecuted(vm) {}searchStarted(search) {}. . .ListenerAdapterpublishStart(publisher)publishFinished(..). . .«interface»PublisherExtensioninstructionExecuted(vm) {}searchStarted(search) {}. . .PropertyListenerAdapter diff --git a/doc/graphics/mji-call.svg b/doc/graphics/mji-call.svg deleted file mode 100644 index d5db418..0000000 --- a/doc/graphics/mji-call.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-24 04:08:50 +0000Canvas 1Layer 1package x.y.z;class C { ... native int foo (int p);}class JPF_x_y_z_C { ... public static int foo__I__I (MJIEnv env, int thisRef, int p) { int d = env.getIntField(thisRef, "data"); .. }}...int a = c.foo(3);...aload_1icont_3invokevirtual ..executeMethod (ThreadInfo ti..){ MJIEnv env = ti.getMJIEnv(); Object[] args = getArguments(); .. mth.invoke(peerCls, args); ..}ClassInfo (..){ peerCls = loadNativePeer(..); ..}executeMethod()peerClsClassInfoexecuteMethod()methodsNativePeergetXField(..)setXField(..)...threadInfoMJIEnvenvThreadInfoJPFclassloadingJPFmethodinvocationJPFobjectaccessJPF (model) classJVM (Java) classJava reflection callreflection diff --git a/doc/graphics/mji-functions.svg b/doc/graphics/mji-functions.svg deleted file mode 100644 index bac9b5c..0000000 --- a/doc/graphics/mji-functions.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-24 04:01:26 +0000Canvas 1Layer 1class JPF_x_y_z_MyClass { public static int foo__ILjava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int i, int sRef) { String s = env.getStringObject(sRef); .. int ref = env.newString(..); return ref; }}package x.y.z;class MyClass { .. native String foo (int i, String s);}MJIEnvJPF objectsJava objectsNativePeerJPF executedhost VM executed- method lookup- parameter conversion- invocation- field access- object conversion- JPF intrinsics access"Model" Class"NativePeer" ClassMJI - "Model Java Interface" diff --git a/doc/graphics/mji-mangling.svg b/doc/graphics/mji-mangling.svg deleted file mode 100644 index 7e59270..0000000 --- a/doc/graphics/mji-mangling.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-02 21:54:02 +0000Canvas 1Layer 1package x.y;class MyClass { native int foo (int i, String s);}class JPF_x_y_MyClass { public static int foo__ILjava_lang_String_2 (MJIEnv env, int objref, int i, int sRef) {..}}Model ClassNative Peer Classmodel parameters(refs become 'int')MJI parametersJNI conformant manglingbooleanbytecharshortintlongfloatdoubleZBCSIJFD'_'';''['_1_2_3<type> [][<type>x.y.ZLx_y_Z_2<func> (..)<func>__<signature> diff --git a/doc/graphics/new-testing.svg b/doc/graphics/new-testing.svg deleted file mode 100644 index 4254ad1..0000000 --- a/doc/graphics/new-testing.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-05 00:34:03 +0000Canvas 1Layer 1@Test public void testX() { if (verifyNoPropertyViolation()) { String s = "one" + " two"; assert "one two".equals(s); }}boolean verifyNoPropertyViolation (String... jpfArgs) { ... args = append(jpfArgs, caller.getClassName(), caller.getMethodName()); .. JPF jpf = createAndRunJPF(args); ... errors = jpf.getSearchErrors(); if (!errors.isEmpty()) throw new AssertionError(..); ... return false; // -> don't execute test block}boolean verifyNoPropertyViolation(..){ return true;}start()JPFShellrunTestsOfThisClass()createAndRunJPF()...verifyNoPropertyViolation()verifyPropertyViolation()verifyUnhandledException()verifyAssertionError()...TestJPFtestX()...MyJPFProjectTestjpf-coretested JPF projectverifyNoPropertyViolation()verifyPropertyViolation()verifyUnhandledException()verifyAssertionError()JPF_.._TestJPFnative peercode verified by JPFexecuted by JPF whenrunning testexecuted outside JPF (starting JPF on test) diff --git a/doc/graphics/por-mark.svg b/doc/graphics/por-mark.svg deleted file mode 100644 index f47b060..0000000 --- a/doc/graphics/por-mark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-12-02 07:35:36 +0000Canvas 1Layer 1XX1XX12Xstatic fieldsT1T2root setheapphase 1phase 21 & 2 : referencing thread numberX : shared diff --git a/doc/graphics/por-scheduling-relevance.svg b/doc/graphics/por-scheduling-relevance.svg deleted file mode 100644 index 45c2886..0000000 --- a/doc/graphics/por-scheduling-relevance.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-11 18:17:44 +0000Canvas 1Layer 1executed bytecode instructionfield insnsync insninvoke insnsync mththreading callscheduling relevant insn typeother runnable threadsrecursive locksshared objectslock protected accessscheduling relevant instruction (registeres a ThreadChoiceGenerator)data racesdeadlocks(lock races)tracking of access threadslock distance & statisticsThread. start(), yield() sleep(), join()Object.wait(),notify()configuredclass/mthdattributesGETFIELDPUTFIELDGETSTATICPUTSTATICxALOADxASTOREMONITORENTERMONITOREXITINVOKEVIRTUALINVOKESTATIC diff --git a/doc/graphics/properties.svg b/doc/graphics/properties.svg deleted file mode 100644 index ad56b87..0000000 --- a/doc/graphics/properties.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2011-05-11 18:07:23 +0000Canvas 1Layer 1jpf.home = ${user.home}/projects/jpfjpf-core = ${jpf.home}/jpf-corejpf-awt = ${jpf.home}/awtjpf-shell = ${jpf.home}/jpf-shelljpf-aprop = ......extensions = ${jpf-core},${jpf-shell}jpf-core = ${config_path}jpf-core.native_classpath=\ ${jpf-core}/build/jpf.jar;\ ... ${jpf-core}/lib/bcel.jar;jpf-core.classpath=\ build/jpf-classes.jarjpf-core.test_classpath=\ build/testsjpf-core.sourcepath=\ src/classes...jpf-awt-shell = ${config_path}@using = jpf-awtjpf-awt-shell.native_classpath=...jpf-awt-shell.classpath=......target = RobotManagertarget_args = ...@using = jpf-aprop@import = ./my.propertiesshell = .shell.basicshell.BasicShelllistener = .aprop.listener.SharedChecker...1. site properties2. project properties3. application properties4. command line~/.jpf/site.properties<project>/jpf.properties<project>/.../*.jpf> bin/jpf [-log][-show] {+log.info=..} .../RobotManager.jpf all jpf.properties inorder of extensionsjpf.properties in current directory- project locations- pre-loaded projects- project class paths- project dependencies- system-under-test- listeners, shells- debuggingcommand line property arguments...applicationpropertiessite properties diff --git a/doc/graphics/report.svg b/doc/graphics/report.svg deleted file mode 100644 index cad3324..0000000 --- a/doc/graphics/report.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2010-09-10 23:02:45 +0000Canvas 1Layer 1JPF()addPublisherExtension()setPublisherTopics()reporterJPF..reporter = config.getInstance("report.class", Reporter.class,..);..searchStarted()propertyViolated()searchFinished()publishersReporterpublishStart()getOut()extensionstopicsoutPublisherpublishStart()publishTransition()publishPropertyViolation()publishFinished()<<PublisherExtension>>........for (Publisher p : publishers){ p.openChannel(); .. p.publishStart();.. public void publishStart() { for (String topic : startTopics) { if ("jpf".equals(topic)){ publishJPF(); ... for (PublisherExtension e : extensions) { e.publishStart(this); } ...out.println("JPF version" + ..);publishJPF()...ConsolePublisherpublishFinished()...DeadlockAnalyzerPrintWriter out = publisher,getOut();printTraceAnalysis(out);data collectionpublisher managementdata formattingtopic managementoutput channel managementproperty/listenerspecific output topicsreport.class=.report.Reporterreport.publisher=console,..report.console.class=.report.ConsolePublisherreport.console.start=jpf,..JPF configuration(e.g. jpf.properties or *.jpf files) diff --git a/doc/graphics/states-mc.svg b/doc/graphics/states-mc.svg deleted file mode 100644 index 8d9f5fd..0000000 --- a/doc/graphics/states-mc.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2009-09-06 18:37:27 +0000Canvas 1Layer 1☠model checking:all program state are explored until none left or defect foundbacktrack≡≡≡match✘ diff --git a/doc/graphics/states-testing.svg b/doc/graphics/states-testing.svg deleted file mode 100644 index 12e5396..0000000 --- a/doc/graphics/states-testing.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-11-19 20:33:35 +0000Canvas 1Layer 1☠based on input set {d}only one pathexecuted at a time✔testing:{d} diff --git a/doc/graphics/sw-model-checking-2.svg b/doc/graphics/sw-model-checking-2.svg deleted file mode 100644 index a0575f7..0000000 --- a/doc/graphics/sw-model-checking-2.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2015-01-05 22:19:29 +0000Canvas 1Layer 1a=0b=0b=1b=2c=0c=0c=0/0starta=1b=0b=1b=2c=-1c=1/0c=1✘12345✔✔6 diff --git a/doc/graphics/sw-model-checking.svg b/doc/graphics/sw-model-checking.svg deleted file mode 100644 index 1fd0a54..0000000 --- a/doc/graphics/sw-model-checking.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - Produced by OmniGraffle 6.1 2014-11-19 20:40:12 +0000Canvas 1Layer 1Random random = new Random() int a = random.nextInt(2)int b = random.nextInt(3)int c = a/(b+a -2)①②③④a=0b=0b=1b=2c=0c=0c=0/0starta=1b=0b=1b=2c=-1c=1/0c=1✔ diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index a40d030..0000000 --- a/doc/index.md +++ /dev/null @@ -1,66 +0,0 @@ -## Welcome to the Java™Pathfinder System ## - -This is the main page for Java™ Pathfinder (JPF). JPF is an extensible software model checking framework for Java™ bytecode programs. The system was developed at the [NASA Ames Research Center](http://arc.nasa.gov), open sourced in 2005, and is freely available on this server under the [Apache-2.0 license](http://www.apache.org/licenses/LICENSE-2.0). - - -This page is our primary source of documentation, and is divided into the following sections. - - --- - - * [Introduction](intro/index) -- a brief introduction into model checking and JPF - * [What is JPF?](intro/what_is_jpf) - * [Testing vs. Model Checking](intro/testing_vs_model_checking) - - [Random value example](intro/random_example) - - [Data race example](intro/race_example) - * [JPF key features](intro/classification) - - --- - - * [How to obtain and install JPF](install/index) -- everything to get it running on your machine - - [System requirements](install/requirements) - - Downloading [binary snapshots](install/snapshot) and [sources](install/repositories) - - [Creating a site properties file](install/site-properties) - - [Building, testing, and running](install/build) - - Installing the JPF plugins - - [Eclipse](install/eclipse-plugin) - - [NetBeans](install/netbeans-plugin) - - --- - - * [How to use JPF](user/index) -- the user manual for JPF - - [Different applications of JPF](user/application_types) - - [JPF's runtime components](user/components) - - [Starting JPF](user/run) - - [Configuring JPF](user/config) - - [Understanding JPF output](user/output) - - [Using JPF's Verify API in the system under test](user/api) - - --- - - * [Developer guide](devel/index) -- what's under the hood - * [Top-level design](devel/design) - * Key mechanisms, such as - - [ChoiceGenerators](devel/choicegenerator) - - [Partial order reduction](devel/partial_order_reduction) - - [Slot and field attributes](devel/attributes) - * Extension mechanisms, such as - - [Listeners](devel/listener) - - [Search Strategies](devel/design) - - [Model Java Interface (MJI)](devel/mji) - - [Bytecode Factories](devel/bytecode_factory) - * Common utility infrastructures, such as - - [Logging system](devel/logging) - - [Reporting system](devel/report) - * [Running JPF from within your application](devel/embedded) - * [Writing JPF tests](devel/jpf_tests) - * [Coding conventions](devel/coding_conventions) - * [Hosting an Eclipse plugin update site](devel/eclipse_plugin_update) - - --- - - * [JPF core project](jpf-core/index) -- description and link to jpf-core - - --- - - * [Related research and publications](papers/index) - diff --git a/doc/install/build.md b/doc/install/build.md deleted file mode 100644 index 9e8d3d6..0000000 --- a/doc/install/build.md +++ /dev/null @@ -1,112 +0,0 @@ -# Building, Testing, and Running # - -If you downloaded binary snapshots, you don't have anything to build (except of creating/updating you [site.properties](./site-properties) file). - -## Building JPF ## - -If you have cloned the project repositories you are interested in (which at least includes [jpf-core](../jpf-core/index)), you can build and test each of them by means of their included [Ant](http://ant.apache.org) `build.xml` scripts. Note that you have to install Ant and JUnit separately, e.g. following directions [here](../install/requirements). - - -### Using the command line ### - -~~~~~~~~ {.bash} -> cd jpf-core -> ant test - -... lots of output, at the end you should see something like: -BUILD SUCCESSFUL -Total time: 2 minutes 31 seconds -~~~~~~~~ - -### Within NetBeans ### - - 1. run **File/Open Project..** from the application menu, entering the JPF project you just downloaded (e.g. "jpf-core") - 1. select the project that appears in our project pane (e.g. "jpf-core") - 1. run **Build** from the project context menu - -### Within Eclipse ### - -* Ensure that the `JAVA_HOME` environment variable points to the jdk1.6xxx directory. If it is empty or points to a JRE then errors such as **javac not found** maybe seen. If you do not want the system Java settings to point to jdk1.6xxx, you can also set project specific settings in eclipse. - -* If you eclipse settings are set to **Build Automatically** then the project after being cloned will be built. - -* To build a particular project in the Project menu select **Build Project**. All the dependencies for the project will be built automatically. - -#### Project Specific JDK settings within Eclipse #### -1. In Eclipse go to **Project** -> **Properties** - -2. Select **Builders** - -3. Pick **Ant_Builder** -> click **Edit** - -4. Click on the **JRE** tab - -5. Select **Separate JRE** -> **Installed JREs** - -6. On Windows and Unix-based systems pick JDK1.6xxx. If it is not listed under the installed JREs, click on **Add**, browse your file system to where JDK1.6xxx resides and select. On OSx systems pick the JVM 1.6.0. - - -## Running JPF ## - -### Using the command line ### - - -~~~~~~~~ {.bash} -> cd jpf-core -> java -jar build/RunJPF.jar src/examples/Racer.jpf -JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center -..... -====================================================== statistics -elapsed time: 0:00:00 -states: new=9, visited=1, backtracked=4, end=2 -search: maxDepth=5, constraints=0 -choice generators: thread=8, data=0 -heap: gc=8, new=291, free=32 -instructions: 3112 -max memory: 79MB -loaded code: classes=73, methods=1010 - -====================================================== search finished: 1/12/10 2:30 PM -~~~~~~~~ - -### Using eclipse plugin ### - - 1. Right click on a .jpf file. Examples can be found in the src\examples directory in jpf-core - 1. If the eclipse plugin is correctly installed, a Verify option will appear. - 1. Select the Verify option and the verification process of the system specified in the .jpf file begins - -Note that the Application.jpf file essentially replaces previous uses of eclipse launch configurations. The required element of a .jpf file is the `target=MAIN_CLASS` where `MAIN_CLASS` is the class containing main method of the system under test. Any other configurations that need to be specified can be added here. for example `listener=gov.nasa.jpf.tools.SearchMonitor`. - -Specify `classpath=PATH_TO_BIN_DIRECTORY` to add the class files for the program under test to JPF's class path. Windows users will need to use the double-backslash notation in specifying paths in the .jpf file. An example .jpf file for the Windows platform is included below for convenience: - -~~~~~~~~ {.bash} -target=mutex.DekkerTestMain -report.console.property_violation=error,trace,snapshot -listener=gov.nasa.jpf.listener.EndlessLoopDetector -classpath=C:\\Users\\fred\\Documents\\ch02-mutex\\bin -sourcepath=C:\\Users\\fred\\Documents\\ch02-mutex\\src,C:\\Users\\Fred\\Documents\\ch02-mutex\\src-test -~~~~~~~~ - -The .jpf file not only indicates the `target` and `classpath`, but it also turns on error reporting with trace generation (`report.console.property_violation`) and configures the source path (`sourcepath`). Note that multiple source directories are specified using the comma separator. - -### Using eclipse Run Configuration ### - - 1. Select a .jpf file by clicking on it in the Package Explorer - 1. Click **Run** -> **Run Configurations** -> **run-JPF-core**. It is important the correct .jpf file is selected when the configuration is run. - -#### Windows users #### -After a fresh install of jpf-core you may see the following when trying to use the Eclipse Run-jpf-core configuration: - -~~~~~~~~ -java.lang.NoClassDefFoundError: gov/nasa/jpf/Main -Caused by: java.lang.ClassNotFoundException: gov.nasa.jpf.Main - at java.net.URLClassLoader$1.run(Unknown Source) - at java.security.AccessController.doPrivileged(Native Method) - at java.net.URLClassLoader.findClass(Unknown Source) - at java.lang.ClassLoader.loadClass(Unknown Source) - at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) - at java.lang.ClassLoader.loadClass(Unknown Source) -Exception in thread "main" -~~~~~~~~ - -In this particular case, the error was generated after the initial build after the clone had completed. To resolve the issue, **refresh the Eclipse workspace** (F5 or right click Refresh). After the refresh, the Run-jpf-core configuration should work as described above. diff --git a/doc/install/eclipse-jpf.md b/doc/install/eclipse-jpf.md deleted file mode 100644 index bae977d..0000000 --- a/doc/install/eclipse-jpf.md +++ /dev/null @@ -1,24 +0,0 @@ -# eclipse-jpf # - -This is a plugin to launch JPF on selected application property files (*.jpf) from within Eclipse. This plugin is the Eclipse analog to netbeans-jpf. This plugin is minimal by design and serves mostly to start an external JPF process from within Eclipse. - -To this end, the plugin adds a "Verify.." popup menu item for *.jpf files that are selected in the package explorer window. - -Depending on the selected application property file, output will appear either in the eclipse console view or a jpf-shell. - -The site.properties location can be entered in the "JPF Preferences" pane within the normal Eclipse Preferences window. The default location is `$HOME/.jpf/site.properties`. - - -This project is *not* a normal JPF project, i.e. it does not follow the usual JPF directory structure and artifacts. This is an Eclipse plugin project that builds into a jar file (attached) that installs into Eclipse as a plugin. Of course that means you need an Eclipse installation that includes the Plugin Development Environment (PDE) in order to build this project. - -### Repository ### -The eclipse-jpf source repository is located on http://babelfish.arc.nasa.gov/hg/jpf/eclipse-jpf - -### Installation ### -If you have the eclipse PDE installed, the preferred way is to get the eclipse-jpf sources from the repository, build via the eclipse plugin Export Wizard into the /dropins folder and restart eclipse. - -If you don't have the eclipse PDE, you can either install this plugin via "Eclipse/Help/Install New Software..." by entering the the eclipse-jpf update site URL: - - http://babelfish.arc.nasa.gov/trac/jpf/raw-attachment/wiki/projects/eclipse-jpf/update - -or download the attached eclipse-jpf_.jar file and move it into your /dropins folder. In both cases, you need to restart eclipse in order to load the plugin. Note however that this might not be the latest eclipse-jpf version and it might or might not work with your eclipse. \ No newline at end of file diff --git a/doc/install/eclipse-plugin.md b/doc/install/eclipse-plugin.md deleted file mode 100644 index 2bcbb3a..0000000 --- a/doc/install/eclipse-plugin.md +++ /dev/null @@ -1,15 +0,0 @@ -# Installing the Eclipse JPF plugin # - -Note that this is assuming the latest Eclipse and Java versions, which is Eclipse 4.3.x and Java 7 at the time of this writing. Older versions might or might not work. -There are three different ways to install the plugin, which are listed in the order of preference if you want to ensure that you are using the latest plugin version: - -### Build from sources ### -If you have the Eclipse Plugin Development Environment installed (PDE -comes with standard Eclipse distribution), the preferred way is to download the [eclipse-jpf](./eclipse-jpf) sources from the repository, build the plugin into your /dropins/plugins directory, and restart Eclipse. This ensures you are using the latest version of the plugin, and the build process will tell you if your Eclipse is compatible. - -### Install from attached plugin jar ### -Alternatively, you can download one of the attached eclipse-jpf_.jar files, place it into your /dropins/plugins directory, and restart Eclipse. - -### Install from update site ### -The most convenient, but least up-to-date way to install eclipse-jpf is to use the Eclipse/Help/Install New Software... dialog, by entering the the eclipse-jpf update site URL: - - http://babelfish.arc.nasa.gov/trac/jpf/raw-attachment/wiki/projects/eclipse-jpf/update diff --git a/doc/install/eclipse-plugin/update.md b/doc/install/eclipse-plugin/update.md deleted file mode 100644 index 18ccf75..0000000 --- a/doc/install/eclipse-plugin/update.md +++ /dev/null @@ -1 +0,0 @@ -This is the target location for the eclipse-jpf update site. \ No newline at end of file diff --git a/doc/install/eclipse-plugin/update/features.md b/doc/install/eclipse-plugin/update/features.md deleted file mode 100644 index f22f5b8..0000000 --- a/doc/install/eclipse-plugin/update/features.md +++ /dev/null @@ -1 +0,0 @@ -Nothing to see here, just a place holder to upload the eclipse-jpf feature. \ No newline at end of file diff --git a/doc/install/eclipse-plugin/update/plugins.md b/doc/install/eclipse-plugin/update/plugins.md deleted file mode 100644 index 180eefa..0000000 --- a/doc/install/eclipse-plugin/update/plugins.md +++ /dev/null @@ -1 +0,0 @@ -Nothing to see here, just a place holder to upload the eclipse-jpf plugin. \ No newline at end of file diff --git a/doc/install/index.md b/doc/install/index.md deleted file mode 100644 index b7f40b8..0000000 --- a/doc/install/index.md +++ /dev/null @@ -1,19 +0,0 @@ -# How to Obtain and Install JPF # - -The JPF core and most of its extensions are pure Java applications, so they are not many platform requirements other than sufficient memory and a reasonably fast machine. Use of IDEs is optional, but most JPF modules include out-of-the-box configuration files for both Eclipse and Netbeans. - -You can obtain JPF sources from the [Mercurial](http://mercurial.selenic.com/wiki/) repositories, but it is not recommended to clone this directory itself (you most likely would get old sub-repository revisions). You need at least the core of JPF, [jpf-core](../jpf-core/index) which can be built with [Ant](http://ant.apache.org) from the command line, or directly opened as a [NetBeans](http://www.netbeans.org) or [Eclipse](http://www.eclipse.org) project. - -The JPF core project already come with its configuration file, but you have to create a per-site [site.properties](site-properties) file. - -If you use the JPF shells (graphical JPF front-ends), you might also want to install the corresponding NetBeans or Eclipse adapter plugins, although shells are standalone Java (swing) applications that can also be used without an IDE. - -Here are the details: - - - [System requirements](requirements) - - [Downloading binary snapshots](snapshot) - - [Downloading sources from the Mercurial repositories](repositories) - - [Creating a site properties file](site-properties) - - [Building, testing, and running](build) - - [Installing the Eclipse plugin](eclipse-plugin) - - [Installing the NetBeans plugin](netbeans-plugin) \ No newline at end of file diff --git a/doc/install/netbeans-jpf.md b/doc/install/netbeans-jpf.md deleted file mode 100644 index 539e0df..0000000 --- a/doc/install/netbeans-jpf.md +++ /dev/null @@ -1,10 +0,0 @@ -# netbeans-jpf # - -This is a plugin to launch JPF on selected application properties (*.jpf) files from within NetBeans. No worries, this is a minimal plugin that mainly starts an external process (JPF), so it doesn't muck with your NetBeans views. - -The main functions are - - - start the JPF shell in an external process - - wait for editor positioning requests from the JPF shell, and show the corresponding source lines - -Why is this named differently than all the other projects? Because it is a different kind of project: this is *not* a normal JPF project, i.e. it is not a freeform NetBeans project with the usual JPF directory structure and artifacts. It is a NetBeans module, and it's main artifact is a *.nbm file in the build directory. \ No newline at end of file diff --git a/doc/install/netbeans-plugin.md b/doc/install/netbeans-plugin.md deleted file mode 100644 index c5360a4..0000000 --- a/doc/install/netbeans-plugin.md +++ /dev/null @@ -1,11 +0,0 @@ -# Installing the NetBeans JPF plugin # - 1. Download and install [jpf-core](../jpf-core/index), e.g. from the [Mercurial repository](../install/repositories) - 2. -------------- take a break --------------- - 3. Download the `gov-nasa-jpf-netbeans-runjpf.nbm` file from [here](http://babelfish.arc.nasa.gov/trac/jpf/attachment/wiki/install/netbeans-plugin/gov-nasa-jpf-netbeans-runjpf.nbm). - 4. From within Netbeans go to **Tools**->**Plugins** (Alt+T followed by Alt+g) - 5. Select the **Downloaded** tab - 6. Click on **Add Plugins...** (Alt+A) - 7. Select the `gov-nasa-jpf-netbeans-runjpf.nbm` file that was downloaded in step 3 - 8. Select **install** - 9. Agree to the License agreement - 10. Restart Netbeans \ No newline at end of file diff --git a/doc/install/repo_shell.md b/doc/install/repo_shell.md deleted file mode 100644 index e5609b1..0000000 --- a/doc/install/repo_shell.md +++ /dev/null @@ -1,74 +0,0 @@ -# Checkout and Build from Shell Prompt (Unix) # - -While there is a CVS repository on the JPF Sourceforge site, it is not in use anymore. The current version is kept in the Subversion repository. - - We will shift to a distributed version control system (Mercurial or Git) soon - - -# SVN # - -This is not a general introduction of [nor do we cover details of [[https://sourceforge.net/svn/?group_id=136825|Subversion on Sourceforge]((SVN),)(http://subversion.tigris.org|Subversion]]). To obtain the current JPF version, execute the following command from a shell prompt: - -~~~~~~~~ {.bash} ->svn checkout https://javapathfinder.svn.sourceforge.net/svnroot/javapathfinder/trunk -~~~~~~~~ - -To update later-on, enter from within one of the javapathfinder directories - - -~~~~~~~~ {.bash} ->svn update -~~~~~~~~ - -To commit (in case you are a project member and have a sourceforge account), use - - -~~~~~~~~ {.bash} ->svn commit -m "commit message" -~~~~~~~~ - -In order to build and test JPF from the commandline, you need Ant and JUnit. If you do not want to use the scripts and versions that are provided with JPF, make sure you have set up your *CLASSPATH* to contain both tools. As of Ant 1.6.5 and JUnit 4.1, this involves the following environment settings: - - -~~~~~~~~ {.bash} ->export PATH=$PATH:/bin ->export CLASSPATH=/lib/ant.jar:/junit-4.1.jar -~~~~~~~~ - -~~~~~~~~ - for your convenience, we have added all required external libraries -and scripts to the *build-tools* directory, so you do not have to install -any of the external components. -~~~~~~~~ -Now you can proceed as described in section Building JPF from a Command Line. For the impatient reader, this is mainly one command - - -~~~~~~~~ {.bash} ->cd javapathfinder-trunk ->build-tools/bin/ant run-tests - -Buildfile: build.xml - -init: - [mkdir] Created dir: /users/pcmehlitz/projects/javapathfinder-trunk/build - ... -compile-jpf: - [javac] Compiling 543 source files to /users/pcmehlitz/projects/javapathfinder-trunk/build/jpf - ... -run-tests: - [echo] --- running Junit tests from build/test.. - [junit] Running TestJavaLangObjectJPF - [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.876 sec - ... -BUILD SUCCESSFUL -Total time: 2 minutes 25 seconds -~~~~~~~~ - -or (especially for non-Unix folk) - - -~~~~~~~~ {.bash} ->java RunAnt run-tests -~~~~~~~~ - -which should compile the whole system and runs the regression test suite with the provided Ant and JUnit versions. \ No newline at end of file diff --git a/doc/install/repositories.md b/doc/install/repositories.md deleted file mode 100644 index 7d43566..0000000 --- a/doc/install/repositories.md +++ /dev/null @@ -1,68 +0,0 @@ -# JPF Source Repository Access # - -JPF sources are kept as [Mercurial](http://www.selenic.com/mercurial) repositories within the http://babelfish.arc.nasa.gov/hg/jpf directory. You need to clone the subrepositories (e.g. http://babelfish.arc.nasa.gov/hg/jpf/jpf-core) that you are interested in, **not** the root directory ../hg/jpf itself (which most likely will give you old subrepo revisions). - -We provide anonymous, public read access. If you want to push your changes back to the repository, and you are not a NASA Ames employee, you need to [obtain a JPF contributor account](wiki:about/account). - -Mercurial is a [Distributed Version Control System](http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/) (DVCS), like Git. If you are not familiar with this, it means "all repositories are created equal", and you have to read up a bit. The foremost authority is ["Mercurial: The Definite Guide"](http://hgbook.red-bean.com/). - -For the inpatient, we also provide a short [Mercurial primer](../devel/mercurial). - -## Command Line Access ## - -To check out the jpf-core use the mercurial command `clone`: - -~~~~~~~~ {.bash} -> cd ~/projects - -> hg clone http://babelfish.arc.nasa.gov/hg/jpf/jpf-core -destination directory: jpf-core -requesting all changes -... -added 71 changesets with 2045 changes to 1694 files -updating working directory -683 files updated, 0 files merged, 0 files removed, 0 files unresolved -~~~~~~~~ - -The same process can be repeating by substituting `jpf-core` with the [project](../projects/index) you are interested in. You can install the projects wherever you want, but you have to remember where you installed them for the subsequent [site.properties](../install/site-properties) configuration. - -To update your local repository, change to its directory and do `pull` (don't forget the `-u` option, or your working directories will not get updated) - -~~~~~~~~ {.bash} -> cd ~/projects/jpf-core -> hg pull -u -~~~~~~~~ - -If you want - and are allowed - to push back your changes, you use **`https://`**`babelfish.arc.nasa.gov/hg/jpf/` as the URL, which will require entering your user-name and password. Before pushing the changes you have to commit the changes from your working directory to your local repository. - -~~~~~~~~ {.bash} -> cd ~/projects/jpf-core -> hg commit -m "this commits to the local repository" -~~~~~~~~ - -The changes now can be pushed to the central repository using the following command - -~~~~~~~~ {.bash} -> hg push https://babelfish.arc.nasa.gov/hg/jpf/jpf-core -~~~~~~~~ - -## Mercurial Support within NetBeans ## - -There is no need to install any plugins, NetBeans is distributed with Mercurial support. - - -## Mercurial Plugin for Eclipse ## - -To work within Eclipse - -* Download and install the [MercurialEclipse](http://javaforge.com/project/HGE) plugin, which at the time of this writing is available from the update site: http://cbes.javaforge.com/update (the usual Eclipse spiel: **Help** -> **Install New Software...** -> **add site**, enter the update URL above) - -* In the eclipse menu: **File** -> **Import** -> **Mercurial** -> **Clone repository using Mercurial** -> **Next** - -* In the repository location, URL, specify http://babelfish.arc.nasa.gov/hg/jpf/jpf-core - -* Check the box for 'Search for .project files in clone and use them to create projects' - -* Click on **Finish** - -The steps listed above will clone the repository in your workspace. Right clicking on the project will show a 'Team' option that allows to perform all the version control operations. diff --git a/doc/install/requirements.md b/doc/install/requirements.md deleted file mode 100644 index ccec451..0000000 --- a/doc/install/requirements.md +++ /dev/null @@ -1,79 +0,0 @@ -# System Requirements # - -## Java ## -Most of the JPF components, including the [jpf-core](../jpf-core/index), are pure Java applications. The minimal version is Java SE 8 (if you have to use JDK 1.7 or JDK 1.6 you have to check out the 'java-7' and 'java-1.6' branches of our repository, respectively), we generally advise to use the latest stable Java version that is available for your platform. You can find out about your java by running the following statement from the command line. - -~~~~~~~~ {.bash} -> java -version -java version "1.8.0_20" -... -~~~~~~~~ - -JPF is a resource hungry application. We recommend at least 2Gb of memory, and generally use a `-Xmx1024m` setting when launching Java. The disk footprint for most JPF projects is fairly small, the jpf-core takes about 40M when fully expanded with sources, compiled classes and jar files. The binary distribution (jar files) takes less than 1.5M. - -Some JPF projects do require 3rd party native executables (like DLLs) that are platform specific. Please refer to the specific project pages for details. - -### Java specifics for Windows ### -Make sure you have the JDK installed, otherwise there is no javac compiler available. - -In order to build JPF from a Windows Command Prompt (executing `ant.bat` from inside the respective JPF project directory), you have to set the `JAVA_HOME` environment variable. - -### Java specifics for OS X ### -On Mac OS X 10.10, Java 1.7 is default, but `/Applications/Utilities/Java Preferences.app` can change the setting. In some cases, it may be necessary to manually change the symlink that determines which version is default: - -~~~~~~~~ {.bash} -sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/Current -sudo ln -s 1.8 /System/Library/Frameworks/JavaVM.framework/Versions/Current -~~~~~~~~ - -## Mercurial (Version Control System) ## -If you want to download the JPF source repositories, you need to install the [Mercurial](http://mercurial.selenic.com/wiki/) distributed version control system on your machine, which requires [Python](http://www.python.org). If you are using a Windows machine, you can install [TortoiseHg](http://tortoisehg.bitbucket.org/), which provides a Windows Explorer extension and includes Python. - -On some Mac OS X systems, it may be necessary to set the `LC_ALL` and `LANG` environment variables for Mercurial to work correctly. - -in `~/.bashrc`: - -~~~~~~~~ {.bash} -export LC_ALL=en_US.UTF-8 -export LANG=en_US.UTF-8 -~~~~~~~~ - -in `~/.cshrc`: - -~~~~~~~~ {.bash} -setenv LC_ALL en_US.UTF-8 -setenv LANG en_US.UTF-8 -~~~~~~~~ - - -If you already have Eclipse installed, and want to download the source repositories from within the IDE, you need the [MercurialEclipse](http://javaforge.com/project/HGE) plugin, which you can install from this update-site: http://cbes.javaforge.com/update - -Note that NetBeans comes with Mercurial support by default. - - -## Apache Ant ## - -Although you can also build from Eclipse, we use [Apache Ant](http://ant.apache.org) as our primary build system. **Ant is no longer included in the jpf-core distribution** so you have to install it separately. Currently (as of Ant 1.9.3), this involves - - * getting Ant binaries e.g. from http://www.apache.org/dist/ant/binaries/ - * setting the `ANT_HOME` environment variable to the directory where you unpacked the binaries - * adding `ANT_HOME/bin` to your `PATH` environment variable - - -## JUnit ## - -Our Ant script (build.xml) includes a `test` target which uses [JUnit](http://junit.org) to run regression tests. **JUnit is no longer included in the jpf-core distribution**. For JUnit-4.11 installation involves the following steps - - * get junit-.jar and hamcrest-core-.jar, e.g. from the links on https://github.com/junit-team/junit/wiki/Download-and-Install - * add both jars to your `CLASSPATH` environment variable - - -## JPF IDE plugins ## - -JPF components come with project configurations for both [NetBeans](http://www.netbeans.org) and [Eclipse](http://www.eclipse.org), so you might want to use your favorite IDE. Since the JPF build process is [Ant](http://ant.apache.org)-based, NetBeans is generally a better fit because it is Ant-based and can make direct use of your JPF site configuration. - -If you want to install the [Eclipse plugin](./eclipse-jpf), you need an Eclipse version >= 3.5 (Galileo) **running under JavaSE-1.8**. Please see the [Installing the Eclipse JPF plugin](./eclipse-plugin) page for details. - -If you want to go with Eclipse and have to rebuild the JPF [Eclipse plugin](./eclipse-jpf), make sure you install the Eclipse Plugin Development Environment (PDE) from the respective Eclipse server. - -If you want to use the [NetBeans plugin](./netbeans-jpf), the minimal NetBeans version is 6.5. \ No newline at end of file diff --git a/doc/install/site-properties.md b/doc/install/site-properties.md deleted file mode 100644 index 691fa4d..0000000 --- a/doc/install/site-properties.md +++ /dev/null @@ -1,32 +0,0 @@ -# Creating a site.properties file # - -The site.properties file tells JPF at startup time where to look for installed projects, so that it can add classpaths accordingly without you having to type off your fingers. It is a normal [Java properties](http://en.wikipedia.org/wiki/.properties) file, which supports a few additional things like key expansion. - -While you can tell JPF at startup time where to look for `site.properties`, we recommend using the default location, which is **`/.jpf/site.properties`**. If you don't know what value the standard Java system property `user.home` has on your machine, please run the attached Java program. On Unix systems, this is your home directory. - -Assuming that you installed your JPF projects under `/projects/jpf`, a typical `site.properties` looks like this: - -~~~~~~~~ {.bash} -# JPF site configuration - -jpf-core = ${user.home}/projects/jpf/jpf-core - -# numeric extension -jpf-numeric = ${user.home}/projects/jpf/jpf-numeric - -# annotation-based program properties extension -jpf-aprop = ${user.home}/projects/jpf/jpf-aprop - -extensions=${jpf-core},${jpf-aprop} - -#... and all your other installed projects -~~~~~~~~ - -If you are a Windows user, and you want to enter absolute pathnames, don't use unquoted backslashes '\' since the `java.util.Properties` parser would interpret these as special chars (like `"\n"`). You can use ordinary slashes '/' instead. To avoid drive letters, use system properties like `${user.home}`. - - -A sample site.properties file is attached to this page. Note that the "`${..}`" terms are automatically expanded by JPF, i.e. you do not have to enter explicit paths. - -Each installed project is defined by a "` = `" key/value pair. The project name is usually the same as the repository name. - -Note that we don't require anymore that all projects are in the extensions list, **but** jpf-core (or wherever your JPF core classes are) now needs to be in there. In fact, you probably want to have only `jpf-core` in `extensions`, and use the `@using ` for the other ones from either your project properties (jpf.properties, for project dependencies) or - usually - from your application properties (*.jpf) files. See [JPF configuration](../user/config) for details. \ No newline at end of file diff --git a/doc/install/snapshot.md b/doc/install/snapshot.md deleted file mode 100644 index d7839c1..0000000 --- a/doc/install/snapshot.md +++ /dev/null @@ -1,14 +0,0 @@ -# Downloading Binary Snapshots # - - -Available binary snapshots are attached as *.zip archives to the [jpf-core](../jpf-core/index) page. Just click the on the download link and tell your browser where to store them on disk, which you need to remember for your subsequent [site.properties](../install/site-properties) configuration. We recommend putting all JPF modules under a single parent directory that holds the site.properties file: - -~~~~~~~~ {.bash} -jpf/ - site.properties - jpf-core/ - jpf-symbc/ - … -~~~~~~~~ - -Many JPF modules are still fast moving, so we recommend using the source repositories to stay up-to-date. Our policy is to only push changes to this server which pass all regression tests \ No newline at end of file diff --git a/doc/intro/classification.md b/doc/intro/classification.md deleted file mode 100644 index 667e755..0000000 --- a/doc/intro/classification.md +++ /dev/null @@ -1,25 +0,0 @@ -# JPF Key Features # - -By now, it should be clear that JPF is not just a model checker: it is a JVM that can be used for model checking. However, if you are familiar with formal methods, you might want to know what kind of model checking methods and features are supported. - -Some of the basic model checking traits are: - -* **Explicit State** model checking is JPF's standard mode of operation. It means JPF keeps track of concrete values of local variables, stackframes, heap objects and thread states. Other than the intentionally different scheduling behavior, JPF should produce the same results like a normal JVM. Of course it is slower (it is a JVM running on top of a JVM, doing a lot of additional work). - -* **Symbolic Execution** means that JPF can perform program execution with symbolic values obtained from how a certain variable was used along the current path of execution (e.g. `x>0 && x<43`). Moreover, JPF can even mix concrete and symbolic execution, or switch between them. Please see the Symbolic Pathfinder project documentation for details. - -* **State Matching** is a key mechanism to avoid unnecessary work. The execution state of a program mainly consists of heap and thread-stack snapshots. While JPF executes, it checks every new state if it already has seen an equal one, in which case there is no use to continue along the current execution path, and JPF can backtrack to the nearest non-explored non-deterministic choice. What variables contribute to state matching, and how state matching is performed can be controlled by the user. - -* **Backtracking** means that JPF can restore previous execution states, to see if there are unexplored choices left. For instance, if JPF reaches a program end state, it can walk backwards to find different possible scheduling sequences that have not been executed yet. While this theoretically can be achieved by re-executing the program from the beginning, backtracking is a much more efficient mechanism if state storage is optimized. - -* **Partial Order Reduction** is what JPF employs to minimize context switches between threads that do not result in interesting new program states. This is done on-the-fly, i.e. without prior analysis or annotation of the program, by examining which instructions can have inter-thread effects. While this is fast, it cannot handle the “diamond case”, since it cannot look ahead of the current execution. - -JPF's flexibility is achieved by an architecture that provides a large number of extension points, of which the most important ones are: - - * search strategies - to control in which order the state space is searched - * listeners - to monitor and interact with JPF execution (e.g. to check for new properties) - * native peers - to model libraries and execute code at the host VM level - * bytecode factories - to provide different execution models (like symbolic execution) - * publishers - to generate specific reports - -In general, flexibility through configuration is JPF's answer to the scalability problem of software model checking. \ No newline at end of file diff --git a/doc/intro/index.md b/doc/intro/index.md deleted file mode 100644 index 8fcec1f..0000000 --- a/doc/intro/index.md +++ /dev/null @@ -1,17 +0,0 @@ -# Introduction # -JPF started as a software model checker, but nowadays, JPF is a runtime system with many different execution modes and extensions which go beyond model checking. All the various modes of JPF, while serving different purposes, used to verify Java programs by - - * detecting and explaining defects - * collecting "deep" runtime information like coverage metrics - * deducing interesting test vectors and creating corresponding test drivers - * and many more... - -Although JPF is mostly associated with software model checking, it can be applied in variety of ways. People often confuse this with testing, and indeed JPF's notion of model checking can be close to systematic testing. Below we use a simple example that illustrates the differences. - -Here is the outline of this section: - - * [What is JPF?](what_is_jpf) - * [Testing vs. Model Checking](testing_vs_model_checking) - * [Random value example](random_example) - * [Data race example](race_example) - * [JPF key features](classification) diff --git a/doc/intro/race_example.md b/doc/intro/race_example.md deleted file mode 100644 index bb7074b..0000000 --- a/doc/intro/race_example.md +++ /dev/null @@ -1,105 +0,0 @@ -# Example: Data Race # - -That's nice, but of course we also could have provoked the error in our random value example by using explicit loops instead of the `Random.nextInt()` calls, i.e. by explicitly enumerating all possible `a` and `b` values in our program. This would be typically done in a program that is a dedicated test driver, in a process which is called *systematic testing*. However, the program we want to verify might not be a test driver, and we might not even have the sources so that we could modify it accordingly. - -But the real show stopper for systematic testing lies within the instructions representing choices: at the application level, we might neither be aware of that there are choices, what the choice values are, nor be able to explicitly pick them. - -To demonstrate this point, let us look at a little concurrency example using two threads of execution. Quite obviously, the program produces different results depending on if line (2) or (4) gets executed first. But assuming we can't control what happens in (1) and (2), this time we cannot explicitly enumerate the choices - they are made by the system scheduler, i.e. outside of our application. - -~~~~~~~~ {.java} -public class Racer implements Runnable { - - int d = 42; - - public void run () { - doSomething(1000); // (1) - d = 0; // (2) - } - - public static void main (String[] args){ - Racer racer = new Racer(); - Thread t = new Thread(racer); - t.start(); - - doSomething(1000); // (3) - int c = 420 / racer.d; // (4) - System.out.println(c); - } - - static void doSomething (int n) { - // not very interesting.. - try { Thread.sleep(n); } catch (InterruptedException ix) {} - } -} -~~~~~~~~ - -Chances are, we don't encounter this defect at all during normal testing: - -~~~~~~~~ {.bash} -> java Racer -10 -> -~~~~~~~~ - -Not so with JPF. Being a real virtual machine, there is nothing we can't control. And being a different kind of a Java virtual machine, JPF recognizes that 'racer' is an object that is shared between two threads, and hence executes all possible statement sequences / scheduling combinations in which this object can be accessed. This time, we give the complete output, which also shows the trace (the execution history) that lead to the defect found by JPF: - -~~~~~~~~ {.bash} -> bin/jpf Racer -JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center -====================================================== system under test -application: /Users/pcmehlitz/tmp/Racer.java - -====================================================== search started: 5/24/07 12:32 AM -10 -10 - -====================================================== error #1 -gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty -java.lang.ArithmeticException: division by zero - at Racer.main(Racer.java:20) - -====================================================== trace #1 ------------------------------------------------------- transition #0 thread: 0 -gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main} - [insn w/o sources](282) - Racer.java:15 : Racer racer = new Racer(); - Racer.java:1 : public class Racer implements Runnable { - [insn w/o sources](1) - Racer.java:3 : int d = 42; - Racer.java:15 : Racer racer = new Racer(); - Racer.java:16 : Thread t = new Thread(racer); - [insn w/o sources](51) - Racer.java:16 : Thread t = new Thread(racer); - Racer.java:17 : t.start(); ------------------------------------------------------- transition #1 thread: 0 -gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main,Thread-0} - Racer.java:17 : t.start(); - Racer.java:19 : doSomething(1000); // (3) - Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} - [insn w/o sources](2) - Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} - Racer.java:7 : } - Racer.java:20 : int c = 420 / racer.d; // (4) ------------------------------------------------------- transition #2 thread: 1 -gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {main,>Thread-0} - Racer.java:10 : doSomething(1000); // (1) - Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} - [insn w/o sources](2) - Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} - Racer.java:7 : } - Racer.java:11 : d = 0; // (2) ------------------------------------------------------- transition #3 thread: 1 -gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {main,>Thread-0} - Racer.java:11 : d = 0; // (2) - Racer.java:12 : } ------------------------------------------------------- transition #4 thread: 0 -gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main} - Racer.java:20 : int c = 420 / racer.d; // (4) - -====================================================== search finished: 5/24/07 12:32 AM -> -~~~~~~~~ - -Looking at the output created by our test program, we see the result `"10"` printed twice, but that doesn't confuse us anymore. From our first example, we know this simply means that JPF first tried two scheduling sequences that normally terminated the program without provoking the defect, before finally picking the one that causes the error. - -It still might be a bit confusing that the printed trace contains some source lines twice. Ignoring the details of its choice generation mechanism, this is caused by JPF executing bytecode instructions, not source lines, and a single source line can easily get translated into a number of bytecode instructions. This would go away if we configure JPF so that it reports the executed bytecode, but at the cost of much larger trace that is harder to read. What is more interesting is that JPF tells us about the thread choices it made in each transition (the lines starting with `gov.nasa.jpf.jvm.ThreadChoice..`). diff --git a/doc/intro/random_example.md b/doc/intro/random_example.md deleted file mode 100644 index 3499e9f..0000000 --- a/doc/intro/random_example.md +++ /dev/null @@ -1,95 +0,0 @@ -# Example: `java.util.Random` # - -We start with a simple example that uses java.util.Random. Consider the following program that obtains two random values in (2) and (3), and then performs some computation (4) with them. - -~~~~~~~~ {.java} -import java.util.Random; - -public class Rand { - public static void main (String[] args) { - Random random = new Random(42); // (1) - - int a = random.nextInt(2); // (2) - System.out.println("a=" + a); - - //... lots of code here - - int b = random.nextInt(3); // (3) - System.out.println(" b=" + b); - - int c = a/(b+a -2); // (4) - System.out.println(" c=" + c); - } -} -~~~~~~~~ - - -## Testing ## - -Executing this program with a normal Java VM yields something like the following output. If we don't provide an explicit seed when creating the Random object in (1), the result is going to differ between runs, but every run will choose just a single `a` and `b` value (i.e. print just a single `"a=.."` and `"b=.."` line. - -~~~~~~~~ {.java} -> java Rand -a=1 - b=0 - c=-1 -> -~~~~~~~~ - -Let's look at a graphical representation of all the ways our program could be executed, and how it actually was executed in our test run. The nodes of the graph represent *program states*, and the edges *transitions* the execution could take from a certain state. - -![Figure 1: Random example](../graphics/sw-model-checking.svg){align=center width=700} - -## Model Checking ## - -Enter JPF - not much different results if we start JPF as a plain 'java' replacement. The only difference is that it (a) takes longer to complete, and (b) tells us something about a "search", which hints on that something more than in our test run is going on - -~~~~~~~~ {.bash} -> bin/jpf Rand -JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center -====================================================== system under test -application: /Users/pcmehlitz/tmp/Rand.java - -====================================================== search started: 5/23/07 11:48 PM -a=1 - b=0 - c=-1 - -====================================================== results -no errors detected - -====================================================== search finished: 5/23/07 11:48 PM -> -~~~~~~~~ - -What is this "search" supposed to mean? Looking at source line (4) we realize that there is a potential problem: for certain `a` and `b` values, this expression can cause a division by zero `ArithmeticException`. Depending on the random seed used in (1), it's quite possible we would never encounter this case if we run (i.e. test) the program with a normal JVM. - -Re-enter JPF - but this time we tell it to not only consider single values for `a` and `b`, but look at all possible choices: - -~~~~~~~~ {.bash} -> bin/jpf +cg.enumerate_random=true Rand -JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center -====================================================== system under test -application: /Users/pcmehlitz/tmp/Rand.java - -====================================================== search started: 5/23/07 11:49 PM -a=0 - b=0 - c=0 - b=1 - c=0 - b=2 - -====================================================== error #1 -gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty -java.lang.ArithmeticException: division by zero - at Rand.main(Rand.java:15) -.... -> -~~~~~~~~ - -What has happened? By specifying "+vm.enumerate_random=true" we told JPF to consider all possible values for expressions (2) and (3). JPF starts with `"a=0"`, then picks `"b=0"`, which yields a valid `"c=0"` value. But instead of terminating like a normal VM, JPF recognized that there are more choices left, so it backtracks to (3) and picks `"b=1"`. Again, no problem here with computing `"c=0"`. Back to (3), JPF now tries `"b=2"`, which of course spells disaster for our little program when executing (4), as can be seen by the following error report. - -Here is a graphical representation of this search process. It should be noted that JPF per default only runs up to the point where it finds an error or there are no more choices left to explore. But if we would somehow fix the `"a=0,b=2"` case, JPF would still find the `"a=1,b=1"` case in the next run, since it systematically tries all choices. No matter what error it finds, JPF also keeps the complete trace (execution path) how it got to this error (denoted by the red arrows), which means we don't have to debug the program to find out. - -![Figure 2: Random example](../graphics/sw-model-checking-2.svg){align=center width=450} diff --git a/doc/intro/testing_vs_model_checking.md b/doc/intro/testing_vs_model_checking.md deleted file mode 100644 index 56b41d5..0000000 --- a/doc/intro/testing_vs_model_checking.md +++ /dev/null @@ -1,28 +0,0 @@ -# Testing vs. Model Checking # - -So what JPF does is test our program for defects? No, it usually does more, at least when used as a model checker. How does testing differ from model checking? - -Software testing is an empirical set of techniques where you execute your program with a number of inputs in order to find out if it behaves correctly. This comes with two parts that involve the right choices: test input and test oracle. - -![Figure 1: Testing](../graphics/states-testing.svg){align=center} - -Testing techniques differ on how we choose the input (random, "interesting" problem domain values like corner cases etc.), and on how much knowledge about the SUT and its execution environment we assume (black/grey/white box), which especially affects how we can define and check correct behavior. This involves a lot of educated guesses, or as Edsger Dijkstra has put it: "program testing can at best show the presence of errors but never their absence". We usually compensate this by performing "enough" tests - which would be the next guess. Testing complex systems can easily turn into finding a needle in a haystack. If you are a good tester, you make the right guesses and hit the defect that is inevitably there. If not, don't worry - your users will find it later. - -![Figure 2: Model checking](../graphics/states-mc.svg){align=center} - -[Model Checking](http://en.wikipedia.org/wiki/Model_checking) as a [Formal Method](http://en.wikipedia.org/wiki/Formal_methods) does not depend on guesses. At least as the theory goes, if there is a violation of a given specification, model checking will find it. Model checking is supposed to be a rigorous method that exhaustively explores all possible SUT behaviors. - -To illustrate this, look at the [Random value example](random_example), which shows how testing differs from model checking if we have a program that uses a sequence of random values: the test always processes just one set of values at a time, and we have little control over which ones. Model checking doesn't stop until it has checked all data combinations or has found an error. - -With the random example, we can at least see the choices in our program. Consider a concurrent program, such as [Data race example](race_example) - do you know where the operating system switches between threads? All we know is that different scheduling sequences can lead to different program behavior (e.g. if there are data races), but there is little we can do in our tests to force scheduling variation. There are program/test spec combinations which are "untestable". Being a virtual machine, our software model checker doesn't suffer the same fate - it has complete control over all threads of our program, and can execute all scheduling combinations. - -![Figure 3: Threads interleaving](../graphics/interleavings.svg){align=center width=550} - -That is the theory. In reality "all possible" can be a pretty large number - too large for existing computing resources or our patience. Just assume the number of different scheduling sequences of a program consisting of N threads P,,1,, .. P,,N,, that each have n,,i,, atomic instruction sequences. - -For 2 threads with 2 atomic sections each this gives us 6 different scheduling combinations. For 8 sections the result is 12870, 16 sections yield 601080390 - that is why it is called *state explosion*. Software model checking has a scalability problem, even more so than model checking of hardware, since programs usually have a lot more states. - -There are several things we can do. First, we can optimize the model checker, which is simply an engineering feat. Next, we can find program states which are equivalent with respect to the properties we are checking, which can be done with various degrees of abstractions and value representations. Last, we can try to get to the defect first, before we run out of time or memory. But this is where the boundary between testing and model checking becomes blurred, as it involves things like heuristics about interesting input values or system behaviors, and these heuristics tend to drop reachable program states. - -JPF does all of the above to curb the state space explosion, and most things are configured instead of hardwired, so you don't depend on built-in heuristics. But no matter how much we shrink the state space, JPF can still observe a lot more about the program execution than normal tests (i.e. we can be more precise with our oracles), and it still knows about the execution history in case we find a defect, which is always just the first part - we also need to understand it so that it can be fixed eventually. - diff --git a/doc/intro/what_is_jpf.md b/doc/intro/what_is_jpf.md deleted file mode 100644 index e8a5ce2..0000000 --- a/doc/intro/what_is_jpf.md +++ /dev/null @@ -1,44 +0,0 @@ -# What is JPF? # - -That depends on how you configure it. -First and foremost, there is no single, monolithic JPF - it is a runtime configured combination of different components. The project *jpf-core* is the essential component that constitutes the core structure of JPF. -Here we explain what *jpf-core* is. - - -## The Core : a VM that supports Model Checking ## - -![Figure 1: High level view of JPF](../graphics/jpf-basic.svg){align=center width=400} - -The JPF core is a Virtual Machine (VM) for Java™ bytecode. That means that JPF is a program which executes the system under test (SUT). The VM of JPF is able to handle bytecode instructions that are created by a standard Java compiler. While execution semantics of Java bytecodes are clearly defined in [Sun's Java virtual machine specifications](http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html/), we have little hardwired semantics in JPF - the VM instruction set is represented by a set of classes that can be replaced. -JPF is a special VM. JPF itself is written in Java, so it is not as fast as your normal Java. That implies that JPF is VM which is running on top of another VM. - -As JPF executes the SUT, it checks for certain properties which are given to JPF as input. Some of the properties that can be checked by JPF are unhandled exceptions, deadlocks, and user-defined assertions which are used to test properties of the code's behavior. -JPF gets back to you with a report that says if the properties hold and/or which verification artifacts have been created by JPF for further analysis (like test cases). - -JPF (theoretically) explores *all* potential executions in a systematic way. In contrast, an ordinary JVM executes the code in only one possible way. -Basically, JPF can identify points, which represent *execution choices*, in your program from which the execution could proceed differently. Then it systematically explores all of them. -Typical execution choices are different scheduling sequences or random values, but JPF allows you to introduce your own type of choices such as user input or state machine events. - -The number of paths can grow out of hand, and it usually will. This is known as the most challenging problem in software model checking referred to as *state space explosion problem*. -JPF uses different ways to mitigate this problem. The first line of defense employed by JPF is *state matching*: each time JPF reaches a choice point, it checks if it has already seen a similar program state, in which case it can safely abandon this path, *backtrack* to a previous choice point that has still unexplored choices, and proceed from there. That's right, JPF can restore program states, which is like telling a debugger "go back 100 instructions". - -So what are these features used for? Normally to find defects in the SUT, but what kind of defects? By now you know the answer: it depends on how you configure JPF. By default, the core checks for properties that can be identified by the VM without you having to specify them: deadlocks and unhandled exceptions (which also covers Java `assert` expressions). We call these *non-functional* properties, and no application should violate them. But JPF doesn't stop there - you can define your own properties, which is mostly done with so called *listeners*, little "plugins" that let you closely monitor all actions taken by JPF, like executing single instructions, creating objects, reaching a new program state and many more. An example of a property implemented in the form of a listener is a race detector, which identifies unsynchronized access to shared variables in concurrent programs (the JPF core comes with two of them). - -One additional feature that comes in handy in case JPF finds a defect is the complete execution history that leads to the defect, including every executed bytecode instruction. We call this a program *trace*, and it is invaluable to find out what really caused the defect. Think of a deadlock - usually there is not much you can directly deduce from a snapshot of call stacks. - -All this explains why JPF is called "a debugger toolbox on steroids": first it automatically executes your program in all possible ways to find defects you don't even know about yet, then it explains you what caused these defects. - -## Caveat : not a lightweight tool ## - -Of course that is the ideal world. In reality, this can require quite a lot of configuration and even some programming. JPF is not a "black box" tool like a compiler, and the learning curve can be steep. What makes this worse is that JPF cannot execute *native code* which is implemented in a language other than Java but invoked from Java applications. -Not because it doesn't know how to do that, but because it often doesn't make sense: native code like system calls to write to a file cannot easily be reverted - JPF would loose its capability to match or backtrack program states. But of course there is a remedy, and it is configurable: *native peers* and *model classes*. Native peers are classes that hold methods that are executed in lieu of real native methods. This code is executed by the real Java VM, not JPF, hence it can also speed up things. Model classes are simple replacements of standard classes, like `java.lang.Thread` that provide alternatives for native methods which are fully observable and backtrackable. - -If you are familiar with Java implementations, you know about the humongous proportions of the included libraries, and hence it is obvious that we cannot handle all of them, at least not yet. There is no theoretical limit, and implementing missing library methods is usually pretty easy, but you should be prepared to encounter `UnsatisfiedLinkErrors` and such if you let JPF loose on large production systems. Notorious white spots are `java.io` and `java.net`, but there are people working on it. Who knows, maybe you are interested to join the effort - JPF is open sourced and there is nothing you can't see. We now have more than two dozen major collaborators in industry, government and academia around the world. - -So what makes it worthwhile to invest in JPF? After all, it is a heavyweight tool, not a quick and simple bug finder. First, if you are looking for a research platform to try out your new software verification ideas, chances are you can get along with JPF in a fraction of time compared to native production VMs, which are typically optimized towards speed and care little about extensibility or observability. - -The second answer is that - as of this writing - there are bugs *only* JPF can find (before the fact, that is), and there are more and more Java applications that cannot afford to learn about these bugs after the fact. JPF is a tool for mission critical applications, where failure is not an option. No surprise it was started by NASA. - - - diff --git a/doc/jpf-core/AssertionProperty.md b/doc/jpf-core/AssertionProperty.md deleted file mode 100644 index 21c49e8..0000000 --- a/doc/jpf-core/AssertionProperty.md +++ /dev/null @@ -1,88 +0,0 @@ -# AssertionProperty # - -This listener adds some special capabilities for `java.lang.AssertionError` processing: - - * report `AssertionErrors` that are otherwise carelessly caught in `... catch (Throwable t) {..}` clauses - * ignore AssertionErrors if `ap.go_on` is set - -`AssertionErrors` differ a bit from other exceptions - they should never be handled, and they usually represent functional properties (as opposed to non-functionals like `NullPointerExceptions` and `ArithmeticExceptions`). Consequently, it can be regarded as an error if an `AssertionError` is swallowed by a 'catch-all', and it is at least an option to ignore an unhandled `AssertionError`, e.g. to see what non-functional defects - if any - it might cause downstream. - -### Example 1: catch-all ### - -~~~~~~~~ {.java} -public class CatchAll { - public static void main(String[] args){ - try { - int d = 42; - //.. some stuff - assert d > 50 : "d below threshold"; - int x = d - 50; - //.. some more stuff - } catch (Throwable t) { // bad - // ..I'm careless - } - } -} -~~~~~~~~ - -Checked with: - -~~~~~~~~ {.bash} ->jpf +listener=.listener.AssertionProperty CatchAll -~~~~~~~~ - -Produces: - -~~~~~~~~ -JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center -====================================================== system under test -application: CatchAll.java - -====================================================== search started: 10/13/09 1:33 PM - -====================================================== error #1 -gov.nasa.jpf.listener.AssertionProperty -d below threshold -... -~~~~~~~~ - - -### Example 2: go-on ### - -~~~~~~~~ {.java} -public class GoOn { - public static void main (String[] args){ - int d = 42; - // lots of computations... - assert d > 50 : "d below threshold"; - int x = Math.max(0, d - 50); - // lots of more computations... - int y = 42000 / x; - } -} -~~~~~~~~ - -Checked with - -~~~~~~~~ {.bash} ->jpf +listener=.listener.AssertionProperty +ap.go_on GoOn -~~~~~~~~ - -Produces: - -~~~~~~~~ {.bash} -JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center - -====================================================== system under test -application: GoOn.java - -====================================================== search started: 10/13/09 1:59 PM -WARNING - AssertionError: d below threshold - at GoOn.main(GoOn.java:5) - -====================================================== error #1 -gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty -java.lang.ArithmeticException: division by zero - at GoOn.main(GoOn.java:8) -... -~~~~~~~~ diff --git a/doc/jpf-core/ErrorTraceGenerator.md b/doc/jpf-core/ErrorTraceGenerator.md deleted file mode 100644 index 0edf13c..0000000 --- a/doc/jpf-core/ErrorTraceGenerator.md +++ /dev/null @@ -1,32 +0,0 @@ -## Error Trace Generator ## - -This is a listener to output a lightweight error trace. It prints the instructions at POR boundaries or points where there are multiple choices. An example is shown below. - -~~~~~~~~ - -====================### Lightweight Error Trace ###======================= - - -Length of Error Trace: 35 ---------------------------------------------------- Thread1 - Event.wait_for_event(oldclassic.java:79) - wait(); ---------------------------------------------------- Thread2 - SecondTask.run(oldclassic.java:129) - if (count == event2.count) { // ditto ---------------------------------------------------- Thread2 - SecondTask.run(oldclassic.java:127) - event1.signal_event(); // updates event1.count ---------------------------------------------------- Thread2 - SecondTask.run(oldclassic.java:133) - count = event2.count; // ditto ---------------------------------------------------- Thread1 - FirstTask.run(oldclassic.java:103) - event1.wait_for_event(); ---------------------------------------------------- Thread1 - -~~~~~~~~ - -Configuration: **+listener=gov.nasa.jpf.listener.ErrorTraceGenerator** - -Note the Error trace generator does not have the same memory bottlenecks as **report.console.property_violation=trace** that stores every bytecode instruction executed along the path from the start of the program to the error state. The error trace generator dynamically recreates the counterexample by tracing back to the start from the error state. The head of the error trace (list shown in the example) represents the last instruction in the error trace while the tail represents the first instruction. \ No newline at end of file diff --git a/doc/jpf-core/ExceptionInjector.md b/doc/jpf-core/ExceptionInjector.md deleted file mode 100644 index 4ab7766..0000000 --- a/doc/jpf-core/ExceptionInjector.md +++ /dev/null @@ -1,105 +0,0 @@ -# ExceptionInjector # - -The ExceptionInjector is a listener that can throw user configured exceptions at arbitrary program locations. The main purpose is to ease the testing of exception handler code that would otherwise hard to reach, e.g. because it is not clear if/how an exception could be thrown in 3rd party code. - -## Properties ## - -~~~~~~~~ {.bash} -**ei.exception** = ;... \ - - := '@' \ - - := [[string-literal]('(') ')'] \ - - := ':'line | '.'[ [[BR](':'line])] -~~~~~~~~ - -Relative line numbers count from the first executable statement in the method body. They are mostly used to have tests that are more robust against changes in the target source file. - -If a method is given without a line offset, the exception is thrown before executing INVOKE instructions that call the specified method. - -If a line is specified (either absolute or method-body relative), the exception is thrown before executing the associated bytecode at this line. - -If more than one exception specification is given, these need to be separated by semicolons ';' (commas cannot be used because they can appear within argument type lists of the target method). - -Method argument types have to be specified the same way as they are reported by 'javap', i.e. with fully qualified type names in dot notation (e.g. "`foo(java.lang.String,int[])`"). Return types can be omitted. - -`ei.throw_first` [`boolean`] - if true, throw exception on first bytecode instruction associated with the given (absolute or relative) source line. If false, throw on last associated bytecode instruction - - -## Examples ## - -### (1) throw exception on absolute line 42 in xyz.MyClass: ### - -The application property file - -~~~~~~~~ {.bash} -target = yxz.MyClass -ei.exception = ArithmeticException@xyz.MyClass:42 -~~~~~~~~ -on file -~~~~~~~~ {.java} -1: package x.y.z; - .. - public class MyClass { - .. - try { - .. -42: int z = x / y; - .. - } catch (ArithmeticException ax){ - // the handler code to test - } - .. -~~~~~~~~ - -will throw an ArithmeticException on line 42 regardless of the 'x' and 'y' values. - -### (2) throw a `Zapp("gotcha")` exception on (relative) line 2 in method body `xyz.MyClass.foo()` ### - -The application property file - -~~~~~~~~ {.bash} -target = yxz.MyClass -ei.exception = Zapp("gotcha")@xyz.MyClass.foo(int[]):2 -~~~~~~~~ -on file -~~~~~~~~ {.java} - package x.y.z; - .. - public class MyClass { - .. - void foo (int[] whatever) { - // some comment (doesn't count for line offsets) -+0: int n = .. // first statement line in foo() -+1: // some more comment (does count for line offsets) -+2: doSomething(n); // can throw a Zapp exception - .. -~~~~~~~~ -will throw a Zapp("gotcha") exception on relative line 2 of method body xyz.MyClass.foo(). Note that the line offset counts from the first executable statement line within foo(). - - -### (3) throw an `IOException` when calling `File.createTempFile()` ### -The application property file - -~~~~~~~~ {.bash} -target = yxz.MyClass -ei.exception = java.io.IOException@java.io.File.createTempFile(java.lang.String,java.lang.String) -~~~~~~~~ - -will throw an exception on the first call of File.createTempFile(), regardless of where this occurs and what the parameters to the call are - -~~~~~~~~ {.java} -1: package x.y.z; - .. - public class MyClass { - .. - try { - .. - File tmp = File.createTempFile(prefix,suffix); - .. - } catch (IOException iox) { - // the handler code to test - } - .. -~~~~~~~~ diff --git a/doc/jpf-core/IdleFilter.md b/doc/jpf-core/IdleFilter.md deleted file mode 100644 index 03c6e98..0000000 --- a/doc/jpf-core/IdleFilter.md +++ /dev/null @@ -1,99 +0,0 @@ -# IdleFilter # - -The `gov.nasa.jpf.listener.IdleFilter` is a listener that can be used to close state spaces with loops. Consider a simple "busy waiting" loop - -~~~~~~~~ {.java} -for (long l=0; l<10000000; l++); -~~~~~~~~ - -While not a good thing to do in general, it is benign if executed in a normal VM. For JPF, it causes trouble because it adds a lot of useless steps to the stored path, and slows down execution considerably. - -In addition, people who expect JPF to match states can get surprised by programs like - -~~~~~~~~ {.java} -while (true){ - // no transition break in here -} -~~~~~~~~ -not being state matched, and hence not terminating (it wouldn't terminate in a normal VM either). - -`IdleFilter` is a little tool to deal with such (bad) loops. It counts the number of back-jumps it encounters within the same thread and stackframe, and if this number exceeds a configured threshold it takes one of the following actions: - - * warn - just prints out a warning that we have a suspicious loop - * break - breaks the transition at the back-jump `goto` instruction, to allow state matching - * prune - sets the transition ignored, i.e. prunes the search tree - * jump - skips the back-jump. This is the most dangerous action since you better make sure the loop does not contain side-effects your program depends on. - - -### Properties ### -Consequently, there are two options: - - * `idle.max_backjumps = \` : max number of back-jumps that triggers the configured action (default 500) - * `idle.action = warn|break|prune|jump` : action to take when number of back-jumps exceeds threshold - -### Examples ### - -**(1)** The test program - -~~~~~~~~ {.java} -... -public void testBreak () { - int y = 4; - int x = 0; - - while (x != y) { // JPF should state match on the backjump - x = x + 1; - if (x > 3) { - x = 0; - } - } -} -~~~~~~~~ - -would never terminate under JPF or a host VM. Running it with - -~~~~~~~~ {.bash} -> bin/jpf +listener=.listener.IdleFilter +idle.action=break ... -~~~~~~~~ - -does terminate due to state matching and produces the following report - -~~~~~~~~ {.bash} -... -====================================================== search started: 4/8/10 4:14 PM -[WARNING] IdleFilter breaks transition on suspicious loop in thread: main - at gov.nasa.jpf.test.mc.basic.IdleLoopTest.testBreak(gov/nasa/jpf/test/mc/basic/IdleLoopTest.java:42) -... -====================================================== results -no errors detected -~~~~~~~~ - ------ -**(2)** The following program would execute a long time under JPF - -~~~~~~~~ {.java} -... -public void testJump () { - for (int i=0; i<1000000; i++){ - //... - } - - System.out.println("Ok, jumped past loop"); -} -~~~~~~~~ - -If we run it with - -~~~~~~~~ {.bash} -> bin/jpf +listener=.listener.IdleFilter +idle.action=jump ... -~~~~~~~~ - -JPF comes back quickly with the result - -~~~~~~~~ {.bash} -====================================================== search started: 4/8/10 4:20 PM -[WARNING] IdleFilter jumped past loop in: main - at gov.nasa.jpf.test.mc.basic.IdleLoopTest.testJump(gov/nasa/jpf/test/mc/basic/IdleLoopTest.java:74) -Ok, jumped past loop -... -~~~~~~~~ diff --git a/doc/jpf-core/index.md b/doc/jpf-core/index.md deleted file mode 100644 index 28fda0e..0000000 --- a/doc/jpf-core/index.md +++ /dev/null @@ -1,43 +0,0 @@ -# jpf-core # -This is the basis for all JPF projects, i.e. you always need to install it. jpf-core contains the basic VM and model checking infrastructure, and can be used to check for concurrency defects like deadlocks, and unhandled exceptions like `NullPointerExceptions` and `AssertionErrors`. - - -## Repository ## -The Mercurial repository is on http://babelfish.arc.nasa.gov/hg/jpf/jpf-core - -## Properties ## -jpf-core supports two rather generic properties, which are configured by default: - - * `gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty` - * `gov.nasa.jpf.jvm.NotDeadlockedProperty` - -There is no need to parameterize any of them. `NoUncaughtExceptionsProperty` covers all `Throwable` objects that are not handled within the application, i.e. would terminate the process. - -Some of the listeners (like `PreciseRaceDetector`) are `ListenerAdapter` instances, i.e. work as more specific Property implementations. - -## Listeners ## -jpf-core includes a variety of [listeners](../devel/listener) that fall into three major categories: - - * program properties - * execution monitoring - * execution control - -Some of the main listeners are - - * [AssertionProperty](./AssertionProperty) - * [IdleFilter](./IdleFilter) - * [ExceptionInjector](./ExceptionInjector) - -## Properties ## -jpf-core uses many JPF properties, you can find most of them in the `defaults.properties` file. The following ones are of interest for users - - * `listener` - a comma separated list of class names representing listeners that should be automatically instantiated and registered during JPF startup - * `listener.autoload` - a comma separated list of annotation types. If JPF encounters such an annotation in one of the analyzed classes at runtime, it automatically loads and registered the associated listener - * `listener.` - class name of the listener associated with `` - * `vm.insn_factory.class` - class name of a [`BytecodeInstructionFactory`](../devel/bytecode_factory), e.g. to switch to the symbolic execution mode or to use specific bytecode implementations for checking numeric properties - * `vm.halt_on_throw (true|false)` - tells JPF if it should try to find a handler if it encounters an exception in the analyzed program (useful to avoid masking exceptions within handlers) - * [`cg.randomize_choices`](../user/config/random) `(random|path|def)` - tells JPF if it should randomize the order of choices for each [`ChoiceGenerator`](../devel/choicegenerator), to avoid degenerated searches (e.g. always indexing with the main thread in scheduling choices). - * `report.console.property_violation` - comma separated list of topics that should be printed by JPF if it detects an error. Possible values include - - `error` error description - - `snapshot` thread stacks - - `trace` instruction/statement trace (can be long and memory-expensive) \ No newline at end of file diff --git a/doc/papers/chicago-author-date.csl b/doc/papers/chicago-author-date.csl deleted file mode 100644 index 595235f..0000000 --- a/doc/papers/chicago-author-date.csl +++ /dev/null @@ -1,549 +0,0 @@ - - diff --git a/doc/papers/index.md b/doc/papers/index.md deleted file mode 100644 index 87fb93a..0000000 --- a/doc/papers/index.md +++ /dev/null @@ -1,133 +0,0 @@ -# Related Publications # - -JPF has been both a research target and a system in use for a number of years. A broad collection of papers and reports is available, including the following (incomplete) list - -> **Notes:** some of the older papers now have mostly historical relevance. JPF has undergone a lot of changes since 2000. If you need more recent information, especially about the design and usage of current -JPF versions, please consult the documentation. - - ---- -bibliography: ./references.bib -csl: ./chicago-author-date.csl -... - -## Core Papers ## - -@visser:2003 - -@lerda:2001 - -## JPF Infrastructure and Features ## - -@shafiei:breugel:2014 - -@nshafiei:2012 - -@kulikov:2010 - -## Testing and Symbolic Execution ## - -@indradeep:2013 - -@person:2008 - -@pasareanu:2008 - -@visser:2004 - -@pasareanu:2004 - -@artho:2003 - -@khurshid:2003 - -## Heuristic Search ## - -@groce:2004 - -@groce:2002 - -@groce:visser:2002 - -## Verification of Networked Software ## - -@shafiei:2014 - -@artho:2011 - -@artho:2009 - -@artho:2008 - -## Explaining Counter Examples ## - -@grove:2003 - -## Applying Java PathFinder ## - -@shafiei:2013 - -@stergiopoulos:2012 - -@mehlitz:2008 - -@penix:2005 - -@giannakopoulou:2004 - -@brat:2004 - -@bordini:2003 - - -## Misc ## - -@havelund:2007 - -@mansouri:2007 - -@havelund:2002 - -@pasareanu:dwyer:2003 - -@brat:2001 - -@visser:park:2000 - -@havelund:2000 - -@havelund:1999 - -@havelund:skakkebaek:1999 - -@havelund:Pressburger:1998 - -## Papers from Darko Marinov's group ## - -@gligoric:2010 - -@gligoric:jagannath:2010 - -@lauterburg:2010 - -@sobeih:2010 - -@lauterburg:2009 - -@gligoric:2009 - -@damorim:2008 - -@lauterburg:2008 - -@gvero:2008 - -@damorim:2007 - -@zhou:2007 - -@damorim:2006 - -@damorim:pacheco:2006 - -## References ## \ No newline at end of file diff --git a/doc/papers/references.bib b/doc/papers/references.bib deleted file mode 100644 index 698195f..0000000 --- a/doc/papers/references.bib +++ /dev/null @@ -1,636 +0,0 @@ -@article{visser:2003, - author = {Visser, Willem and Havelund, Klaus and Brat, Guillaume and Park, Seungjoon and Lerda, Flavio}, - title = "{M}odel {C}hecking {P}rograms", - journal = {Automated Software Engineering}, - volume = {10}, - number = {2}, - month = {April}, - year = {2003}, - pages = {203--232}, - publisher = {Kluwer Academic Publishers}, - url = "http://dl.acm.org/citation.cfm?id=641186" - } - -@inproceedings{lerda:2001, - author = {Lerda, Flavio and Visser, Willem}, - title = {Addressing Dynamic Issues of Program Model Checking}, - booktitle = {Proceedings of the 8th International SPIN Workshop on Model Checking of Software}, - year = {2001}, - pages = {80--102}, - publisher = {Springer}, - url = "http://dl.acm.org/citation.cfm?id=380921.380931", -} - -@inproceedings{khurshid:2003, - author = {Sarfraz Khurshid and Corina S. P\v{a}s\v{a}reanu and Willem Visser}, - title = {Generalized Symbolic Execution for Model Checking and Testing}, - booktitle = {Proceedings of the Ninth International Conference on Tools and Algorithms for the Construction and Analysis of Systems}, - year = {2003}, - pages = {553--568}, - publisher = {Springer}, - url = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.8.8862" -} - -@article{visser:2004, - author = {Visser, Willem and P\v{a}s\v{a}reanu, Corina S. and Khurshid, Sarfraz}, - title = {Test Input Generation with Java PathFinder}, - journal = {Proceedings of International Symposium on Software Testing and Analysis}, - volume = {29}, - number = {4}, - month = jul, - year = {2004}, - pages = {97--107}, - publisher = {ACM}, - url = "http://dl.acm.org/citation.cfm?id=1007526", -} - -@article{pasareanu:2004, -year={2004}, -volume={2989}, -series={Lecture Notes in Computer Science}, -title={Verification of Java Programs Using Symbolic Execution and Invariant Generation}, -url={http://link.springer.com/chapter/10.1007%2F978-3-540-24732-6_13#}, -publisher={Springer}, -author={Păsăreanu, Corina S. and Visser, Willem}, -pages={164-181}, -} - -@inproceedings{person:2008, - author = {Person, Suzette and Dwyer, Matthew B. and Elbaum, Sebastian and P\v{a}s\v{a}reanu, Corina S.}, - title = {Differential Symbolic Execution}, - booktitle = {Proceedings of the 16th {ACM} {SIGSOFT} International Symposium on Foundations of Software Engineering}, - year = {2008}, - pages = {226--237}, - url = {http://doi.acm.org/10.1145/1453101.1453131}, - publisher = {ACM}, - } - -@inproceedings{pasareanu:2008, - author = {Corina S. P\v{a}s\v{a}reanu and - Peter C. Mehlitz and - David H. Bushnell and - Karen Gundy{-}Burlet and - Michael R. Lowry and - Suzette Person and - Mark Pape}, - title = {Combining unit-level symbolic execution and system-level concrete - execution for testing {NASA} software}, - booktitle = {Proceedings of the {ACM} {SIGSOFT} International Symposium on Software - Testing and Analysis}, - pages = {15--26}, - year = {2008}, - url = {http://doi.acm.org/10.1145/1390630.1390635}, -} - -@inproceedings{pasareanu:2007, - author = {Corina S. P\v{a}s\v{a}reanu and - Willem Visser}, - title = {Symbolic Execution and Model Checking for Testing}, - booktitle = {Hardware and Software: Verification and Testing, Third International - Haifa Verification Conference}, - pages = {17--18}, - year = {2007}, - url = {http://dx.doi.org/10.1007/978-3-540-77966-7_5}, -} - -@inproceedings{artho:2003, - author = {Cyrille Artho and - Doron Drusinsky and - Allen Goldberg and - Klaus Havelund and - Michael R. Lowry and - Corina S. P\v{a}s\v{a}reanu and - Grigore Rosu and - Willem Visser}, - title = {Experiments with Test Case Generation and Runtime Analysis}, - booktitle = {Abstract State Machines, Advances in Theory and Practice}, - pages = {87--107}, - year = {2003}, - url = {http://dx.doi.org/10.1007/3-540-36498-6_5}, -} - -@article{groce:2004, - author = {Alex Groce and - Willem Visser}, - title = {Heuristics for model checking Java programs}, - journal = {International Journal on Software Tools for Technology Transfer}, - volume = {6}, - number = {4}, - pages = {260--276}, - year = {2004}, - url = {http://dx.doi.org/10.1007/s10009-003-0130-9}, -} - -@inproceedings{groce:2002, - author = {Alex Groce and - Willem Visser}, - title = {Model checking Java programs using structural heuristics}, - booktitle = {Proceedings of International Symposium on Software Testing and Analysis}, - pages = {12--21}, - year = {2002}, - url = {http://doi.acm.org/10.1145/566172.566175}, -} - -@inproceedings{groce:visser:2002, - author = {Alex Groce and - Willem Visser}, - title = {Heuristic Model Checking for Java Programs}, - booktitle = {Proceedings of the 9th International SPIN Workshop on Model Checking of Software}, - pages = {242--245}, - year = {2002}, - url = {http://dx.doi.org/10.1007/3-540-46017-9_21}, -} - -@inproceedings{artho:2011, - author = {Leungwattanakit, Watcharin and Artho, Cyrille and Hagiya, Masami and Tanabe, Yoshinori and Yamamoto, Mitsuharu}, - title = {Model checking distributed systems by combining caching and process checkpointing}, - booktitle = {Proceedings of the 26th IEEE/ACM International Conference on International Conference on Automated Software Engineering}, - year = {2011}, - pages = {103--112}, - publisher = {IEEE}, -month={November}, - address = {Lawrence, KS, USA}, - url = {​http://staff.aist.go.jp/c.artho/papers/checkpointing.pdf}, -} - -@inproceedings{artho:2009, - author = {Artho, Cyrille and Leungwattanakit, Watcharin and Hagiya, Masami and Tanabe, Yoshinori and Yamamoto, Mitsuharu}, - title = {Cache-Based model Checking of Networked Applications: From Linear to Branching Time}, - booktitle = {Proceedings of the 27th International Conference on Automated Software Engineering}, - year = {2009}, -month = {November}, - pages = {447--458}, - publisher = {IEEE}, - address = {Auckland, New Zealand}, - url = {​http://staff.aist.go.jp/c.artho/papers/ase-2009.pdf}, -} - -@inproceedings{artho:2008, -author={Artho, Cyrille and Leungwattanakit, Watcharin and Hagiya, Masami and Tanabe, Yoshinori}, -title={Efficient Model Checking of Networked Applications}, -year={2008}, -volume={11}, -series={Lecture Notes in Business Information Processing}, -booktitle = {Proceedings of the 46th International Conference on Objects, Components, Models and Patterns}, -publisher={Springer}, -pages={22--40}, -address={Zurich, Switzerland}, -month={June/July}, -url = {http://staff.aist.go.jp/c.artho/papers/tools-2008.pdf} -} - -@inproceedings{grove:2003, - author = {Alex Groce and - Willem Visser}, - title = {What Went Wrong: Explaining Counterexamples}, - booktitle = {Proceedings of the 10th International SPIN Workshop on Model Checking of Software}, - pages = {121--135}, - year = {2003}, - url = {http://dx.doi.org/10.1007/3-540-44829-2_8}, - publisher = {Springer}, - address = {Portland}, -} - -@article{penix:2005, - author = {John Penix and - Willem Visser and - Seungjoon Park and - Corina S. P\v{a}s\v{a}reanu and - Eric Engstrom and - Aaron Larson and - Nicholas Weininger}, - title = {Verifying Time Partitioning in the {DEOS} Scheduling Kernel}, - journal = {Formal Methods in System Design}, - volume = {26}, - number = {2}, - pages = {103--135}, - year = {2005}, - url = {http://dx.doi.org/10.1007/s10703-005-1490-4}, -} - -@article{brat:2004, - author = {Guillaume P. Brat and - Doron Drusinsky and - Dimitra Giannakopoulou and - Allen Goldberg and - Klaus Havelund and - Michael R. Lowry and - Corina S. Pasareanu and - Arnaud Venet and - Willem Visser and - Richard Washington}, - title = {Experimental Evaluation of Verification and Validation Tools on Martian - Rover Software}, - journal = {Formal Methods in System Design}, - volume = {25}, - number = {2-3}, - pages = {167--198}, - year = {2004}, - url = {http://dx.doi.org/10.1023/B:FORM.0000040027.28662.a4}, -} - -@inproceedings{bordini:2003, - author = {Rafael H. Bordini and - Michael Fisher and - Carmen Pardavila and - Willem Visser and - Michael Wooldridge}, - title = {Model Checking Multi-Agent Programs with {CASP}}, - booktitle = {Proceedings of Computer Aided Verification}, - pages = {110--113}, - year = {2003}, - url = {http://dx.doi.org/10.1007/978-3-540-45069-6_10}, -} - -@inproceedings{giannakopoulou:2004, - author = {Dimitra Giannakopoulou and - Corina S. Pasareanu and - Jamieson M. Cobleigh}, - title = {Assume-Guarantee Verification of Source Code with Design-Level Assumptions}, - booktitle = {26th International Conference on Software Engineering {(ICSE} 2004), - 23-28 May 2004, Edinburgh, United Kingdom}, - pages = {211--220}, - year = {2004}, - url = {http://doi.ieeecomputersociety.org/10.1109/ICSE.2004.1317443}, -} - -@inproceedings{mehlitz:2008, - author = {Peter Mehlitz}, - title = {Trust Your Model - Verifying Aerospace System Models with Java Pathfinder}, - booktitle = {Aerospace Conference, 2008 IEEE}, - pages = {1--11}, - year = {2008}, - url = {http://ti.arc.nasa.gov/m/pub-archive/1402/1402%20(Mehlitz).pdf}, -} - -@inproceedings{stergiopoulos:2012, - author = {Stergiopoulos, George and Tsoumas, Bill and Gritzalis, Dimitris}, - title = {Hunting Application-level Logical Errors}, - booktitle = {Proceedings of the 4th International Conference on Engineering Secure Software and Systems}, - year = {2012}, - address = {Eindhoven, The Netherlands}, - pages = {135--142}, - url = {http://dx.doi.org/10.1007/978-3-642-28166-2_13}, - publisher = {Springer}, -} - -@article{mansouri:2007, - author = {Masoud Mansouri-Samani and John Penix and Lawrence Markosian}, - title = {Assume-Guarantee Verification of Source Code with Design-Level Assumptions}, - journal = {Software Assurance Research Program (SARP), NASA IV&V publication}, - year = {2007}, - pages = {203--232}, - publisher = {Kluwer Academic Publishers}, - url = {http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20080015887.pdf}, - } - - @article{havelund:2002, - author = {Klaus Havelund and Willem Visser}, - title = {Program Model Checking as a New Trend}, - journal = {International Journal on Software Tools for Technology Transfer (STTT)}, - volume = {4}, - number = {1}, - month = {October}, - year = {2002}, - url = {http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20030003734.pdf}, -} - -@article{pasareanu:dwyer:2003, - author = "C. P\v{a}s\v{a}reanu and M. Dwyer and W. Visser.", - title = "{Finding Feasible Abstract Counter-Examples}", - journal = "International Journal on Software Tools for Technology Transfer (STTT)", - year = "2003", - volume = "5", - number = "1", - month = "November", - url = "http://ti.arc.nasa.gov/m/profile/pcorina/papers/tacas_sttt01.ps" -} - -@inproceedings{brat:2001, - author = {Guillaume Brat and Willem Visser}, - title = {Combining Static Analysis and Model Checking for Software Analysis}, - booktitle = {Proceedings of the 15th IEEE International Conference on Automated Software Engineering}, - year = {2001}, - address = {San Diego, USA}, - month = {November}, - url = {http://dl.acm.org/citation.cfm?id=872568}, -} - -@inproceedings{visser:park:2000, - author = {Willem Visser and Seungjoon Park and John Penix}, - title = {Using Predicate Abstraction to Reduce Object-Oriented Programs for Model Checking}, - booktitle = {Proceedings of the 3rd ACM SIGSOFT Workshop on Formal Methods in Software Practice}, - year = {2000}, - pages = {3--12}, - month = {August}, - url = "http://ti.arc.nasa.gov/m/tech/rse/publications/papers/SIGSOFT00/fmsp00.pdf", -} - -@article{havelund:2000, - author = {Klaus Havelund and - Thomas Pressburger}, - title = {Model Checking {Java} Programs using {Java} PathFinder}, - journal = {International Journal on Software Tools for Technology Transfer (STTT)}, - volume = {2}, - number = {4}, - pages = {366--381}, - year = {2000}, - url = {http://www.havelund.com/Publications/jpf-sttt.ps.Z}, -} - -@inproceedings{havelund:1999, - author = {Klaus Havelund}, - title = {Java PathFinder, {A} Translator from Java to Promela}, - booktitle = {Theoretical and Practical Aspects of {SPIN} Model Checking}, - month = {July}, - year = {1999}, - url = {http://www.havelund.com/Publications/jpf1-spin-99.pdf}, -} - -@inproceedings{havelund:skakkebaek:1999, - author = {Klaus Havelund and - Jens U. Skakkeb{\ae}k}, - title = {Applying Model Checking in Java Verification}, - booktitle = {Theoretical and Practical Aspects of {SPIN} Model Checking, 5th and - 6th International {SPIN} Workshops}, - pages = {216--231}, - year = {1999}, - url = {http://www.havelund.com/Publications/jpf-fm99.ps.Z}, -} - -@article{havelund:2007, - author = {Klaus Havelund}, - title = {Java PathFinder User Guide}, - booktitle = {Unpublished Report}, - year = {1999}, - url = {​http://www.havelund.com/Publications/jpf-manual.ps.Z}, -} - -@article{havelund:Pressburger:1998, - author = {Klaus Havelund and Thomas Pressburger}, - title = {Java PathFinder, A Translator from Java to Promela}, - booktitle = {Unpublished Report}, - year = {1998}, - url = {​​http://www.havelund.com/Publications/jpf1-report-99.pdf}, -} - -@inproceedings{gligoric:2010, - author = {Milos Gligoric and - Tihomir Gvero and - Vilas Jagannath and - Sarfraz Khurshid and - Viktor Kuncak and - Darko Marinov}, - title = {Test generation through programming in {UDITA}}, - booktitle = {Proceedings of the 32nd {ACM/IEEE} International Conference on Software - Engineering}, - address = {Cape Town, South Africa}, - month = {May}, - pages = {225--234}, - year = {2010}, - url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL10UDITA.pdf}, -} - -@inproceedings{gligoric:jagannath:2010, - author = {Milos Gligoric and - Vilas Jagannath and - Darko Marinov}, - title = {MuTMuT: Efficient Exploration for Mutation Testing of Multithreaded - Code}, - booktitle = {Third International Conference on Software Testing, Verification and - Validation}, - pages = {55--64}, - month = {April}, - address = {Paris, France}, - year = {2010}, - url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL10MuTMuT.pdf}, -} - -@inproceedings{lauterburg:2010, - author = {Steven Lauterburg and - Rajesh K. Karmani and - Darko Marinov and - Gul Agha}, - title = {Evaluating Ordering Heuristics for Dynamic Partial-Order Reduction - Techniques}, - booktitle = {Fundamental Approaches to Software Engineering}, - address = {Paphos, Cyprus}, - month = {March}, - pages = {308--322}, - year = {2010}, - url = {http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL10DPORHeuristics.pdf}, -} - -@inproceedings{lauterburg:2009, - author = {Steven Lauterburg and - Mirco Dotta and - Darko Marinov and - Gul A. Agha}, - title = {A Framework for State-Space Exploration of Java-Based Actor Programs}, - booktitle = {24th {IEEE/ACM} International Conference on Automated Software Engineering}, - month = {November}, - address = {Auckland, New Zealand}, - pages = {468--479}, - year = {2009}, - url = {http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL09Basset.pdf}, -} - -@article{sobeih:2010, - author = {Ahmed Sobeih and - Marcelo d'Amorim and - Mahesh Viswanathan and - Darko Marinov and - Jennifer C. Hou}, - title = {Assertion Checking in J-Sim Simulation Models of Network Protocols}, - journal = {Simulation: Transactions of The Society for Modeling and Simulation International}, - volume = {86}, - number = {11}, - pages = {651--673}, - year = {2010}, - url = {http://dx.doi.org/10.1177/0037549709349326}, -} - -@inproceedings{gligoric:2009, - author = {Milos Gligoric and - Tihomir Gvero and - Steven Lauterburg and - Darko Marinov and - Sarfraz Khurshid}, - title = {Optimizing Generation of Object Graphs in Java PathFinder}, - booktitle = {Second International Conference on Software Testing Verification and Validation}, - month = {April}, - address = {Denver, Colorado, {USA}}, - pages = {51--60}, - year = {2009}, - url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL09OptimizingGeneration.pdf}, -} - -@article{damorim:2008, - author = {Marcelo d'Amorim and - Steven Lauterburg and - Darko Marinov}, - title = {Delta Execution for Efficient State-Space Exploration of Object-Oriented Programs}, - journal = {{IEEE} Transactions on Software Engineering}, - volume = {34}, - number = {5}, - pages = {597--613}, - year = {2008}, - month = {September/October}, - url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL08DeltaExecution.pdf}, -} - -@inproceedings{lauterburg:2008, - author = {Steven Lauterburg and - Ahmed Sobeih and - Darko Marinov and - Mahesh Viswanathan}, - title = {Incremental state-space exploration for programs with dynamically - allocated data}, - booktitle = {International Conference on Software Engineering}, - address = {Leipzig, Germany}, - month = {May}, - pages = {291--300}, - year = {2008}, - url = {​http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL08IncrementalChecking.pdf}, -} - -@inproceedings{gvero:2008, - author = {Tihomir Gvero and - Milos Gligoric and - Steven Lauterburg and - Marcelo d'Amorim and - Darko Marinov and - Sarfraz Khurshid}, - title = {State extensions for java pathfinder}, - booktitle = {International Conference on Software Engineering, Demo Papers}, - address = {Leipzig, Germany}, - month = {May}, - pages = {863--866}, - year = {2008}, - url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL09OptimizingGeneration.pdf}, -} - -@inproceedings{damorim:2007, - author = {Marcelo d'Amorim and - Steven Lauterburg and - Darko Marinov}, - title = {Delta execution for efficient state-space exploration of object-oriented - programs}, - booktitle = {Proceedings of the {ACM/SIGSOFT} International Symposium on Software - Testing and Analysis}, - address = {London, UK}, - month = {July}, - pages = {50--60}, - year = {2007}, - url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL07DeltaExecution.pdf}, -} - -@inproceedings{zhou:2007, - author = {Zhou, Yuanyuan and Marinov, Darko and Sanders, William and Zilles, Craig and d'Amorim, Marcelo and Lauterburg, Steven and Lefever, Ryan M. and Tucek, Joe}, - title = {Delta Execution for Software Reliability}, - booktitle = {Proceedings of the 3rd Workshop on on Hot Topics in System Dependability}, - series = {HotDep'07}, - year = {2007}, - address = {Edinburgh, UK}, - url = {http://mir.cs.illinois.edu/~marinov/publications/ZhouETAL07DeltaExecution.pdf}, - publisher = {USENIX Association}, -} - -@inproceedings{damorim:2006, - author = {Marcelo d'Amorim and - Ahmed Sobeih and - Darko Marinov}, - title = {Optimized Execution of Deterministic Blocks in Java PathFinder}, - booktitle = {Proceedings of Formal Methods and Software Engineering, 8th International Conference - on Formal Engineering Methods}, - address = {Macao, China}, - month = {November}, - pages = {549--567}, - year = {2006}, - url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL06OptimizedDeterministicBlocks.pdf}, -} - -@inproceedings{damorim:pacheco:2006, - author = {Marcelo d'Amorim and - Carlos Pacheco and - Tao Xie and - Darko Marinov and - Michael D. Ernst}, - title = {An Empirical Comparison of Automated Generation and Classification - Techniques for Object-Oriented Unit Testing}, - booktitle = {Proceedings of 21st {IEEE/ACM} International Conference on Automated Software Engineering}, - address = {Tokyo, Japan}, - month = {September}, - pages = {59--68}, - year = {2006}, - url = {​http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL06Symclat.pdf}, -} - -@unpublished{kulikov:2010, - author = {Sergey Kulikov and Nastaran Shafiei and Franck van Breugel and Willem Visser}, - title = {{Detecting Data Races with Java PathFinder}}, - year = "2010", - url = {http://www.cse.yorku.ca/~franck/research/drafts/race.pdf} -} - -@inproceedings{indradeep:2013, - author = {Ghosh, Indradeep and Shafiei, Nastaran and Li, Guodong and Chiang, Wei-Fan}, - title = {{JST: an automatic test generation tool for industrial Java applications with strings}}, - booktitle = {Proceedings of the 35th International Conference on Software Engineering}, - year = {2013}, - month = {May}, - address = {San Francisco, CA, USA}, - pages = {992--1001}, - publisher = {IEEE}, - url = {http://dl.acm.org/citation.cfm?id=2486925} -} - -@article{nshafiei:2012, - author = {Shafiei, Nastaran and Mehlitz, Peter C.}, - journal = {ACM SIGSOFT Software Engineering Notes}, - number = 6, - pages = {1-5}, - title = {{Modeling class loaders in Java PathFinder version 7}}, - volume = 37, - year = 2012, - month = {November}, - url = {http://dl.acm.org/citation.cfm?id=2382800} -} - -@article{shafiei:2014, - author = {Shafiei, Nastaran and Mehlitz, Peter C.}, - journal = {ACM SIGSOFT Software Engineering Notes}, - number = 1, - pages = {1-5}, - title = {{Extending JPF to verify distributed systems}}, - volume = 39, - year = 2014, - month = {January}, - url = {http://dl.acm.org/citation.cfm?id=2560577}, -} - -@inproceedings{shafiei:2013, - author = {Nastaran Shafiei and - Franck van Breugel}, - title = {Towards model checking of computer games with Java PathFinder}, - booktitle = {Proceedings of the 3rd International Workshop on Games and Software - Engineering}, - address = {San Francisco, CA, USA}, - month = {May}, - pages = {15--21}, - year = {2013}, - url = {http://dl.acm.org/citation.cfm?id=2662596}, -} - - -@inproceedings{shafiei:breugel:2014, - author = {Nastaran Shafiei and - Franck van Breugel}, - title = {Automatic handling of native methods in Java PathFinder}, - booktitle = {Proceedings of the International SPIN Workshop on Model Checking of Software}, - address = {San Jose, CA, USA}, - month = {July}, - pages = {97--100}, - year = {2014}, - url = {http://dl.acm.org/citation.cfm?id=2632363}, -} \ No newline at end of file diff --git a/doc/user/api.md b/doc/user/api.md deleted file mode 100644 index fdfd9a6..0000000 --- a/doc/user/api.md +++ /dev/null @@ -1,125 +0,0 @@ -# The Verify API # -Although the primary purpose of JPF is to verify applications that are not JPF dependent, it can also be used to check programs that are explicitly written to execute under JPF. There are two ways to do this - - * use of jpf annotations such as `@gov.nasa.jpf.annotation.JPFConfig` and `@gov.nasa.jpf.annotation.FilterField` - * use of the various `gov.nasa.jpf.vm.Verify` APIs - -The first method provides only directives to JPF (by means of Java annotations), and does not modify or add any specific code to your system under test. The second one is imperative and should only be used by JPF specific test drivers. - -## JPF Annotations ## -The JPF core currently supports two annotation types: `@JPFConfig` and `@FilterField` - -~~~~~~~~ {.java} -import gov.nasa.jpf.annotation.JPFConfig -... -@JPFConfig({"listener+=,gov.nasa.jpf.aprop.listener.SharedChecker", ..}) -public class MyClass { - .. -} -~~~~~~~~ - -The `@JPFConfig` annotation allows to set JPF properties (= pairs) for classes and methods of your application, which is especially useful to add specific listeners. You have to be aware of the property effects though, since not all behavior can be changed at runtime, and you usually cannot reverse features with this method - -The `@FilterField` annotation is used to mark certain fields in your application as not relevant for state matching. This is useful if you have to add debugging information like counters that would otherwise increase the state space (i.e. would prevent state matching). - -~~~~~~~~ {.java} -import gov.nasa.jpf.annotation.FilterField; -... -public class MyClass { - .. - @FilterField int counter; - .. -} -~~~~~~~~ - -This does not change execution of your program in any way, and also does not affect backtracking within JPF (i.e. values are properly restored). It only tells JPF to ignore marked fields when hashing/matching program states. - -There is a [jpf-aprop](wiki:projects/jpf-aprop) JPF module that is dedicated to Java annotation based program properties such as `@Nonnull`, `@NonShared`, `@Immutable`, `@Requires` and many others. - -## The Verify API ## - -Sometimes it is useful to create JPF specific test drivers, like you create JUnit test cases. In this code, you can make explicit use of JPF APIs, since it is not supposed to run outside JPF. There are several categories of APIs which are encapsulated in the `gov.nasa.jpf.vm.Verify` class. - -### Data ChoiceGenerators ### -Data ChoiceGenerators (CGs) are suitable for writing test drivers that are JPF aware. The idea is to obtain non-deterministic input values from JPF in a way that it can systematically analyze all relevant choices. In its most simple form, this can be used like - -~~~~~~~~ {.java} -// test driver code -import gov.nasa.jpf.vm.Verify; -.. -boolean cond = Verify.getBoolean(); -// following code is executed for both cond=true AND cond=false -.. -~~~~~~~~ - -The `Verify` class contains methods for creating a number of different choice generators for builtin Java types, like - -~~~~~~~~ {.java} -.. -int i = Verify.getInt(min,max); // evaluates for all values between 'min' and 'max' (inclusive) -.. -double d = Verify.getDoubleFromSet(-42.0, 0.0, 42.0 ..); // evaluates all given values -.. -~~~~~~~~ - - -CGs don't stop at value sets that can be completely enumerated based on their type (like boolean, and - at least theoretically - integers). JPF also supports configured heuristics based choice generators, where the values sets are application dependent and can be specified in property files. - -![Figure: Data ChoiceGenerators](../graphics/choicegen-example.svg){align=center width=750} - -Choice generator implementation is described in a [separate section](wiki:devel/choicegenerator) of this documentation. - -### Search Pruning ### - -Explicitly restricting the search is useful for highly application specific properties, where it is obvious that certain values are not of interest with respect to the property. - -~~~~~~~~ {.java} -// ..compute some data.. -Verify.ignoreIf(data > someValue); // prune search if true -// ..do some stuff with data.. -~~~~~~~~ -If the provided expression evaluates to true, JPF does not continue to execute the current path, and backtracks to the previous non-deterministic choice point. - -### State Annotation ### -Based on certain value combinations, an application might give JPF hints about the relevance of a program state that can be subsequently used by Search and/or Heuristic implementations. - -~~~~~~~~ {.java} -// ..compute some data -Verify.interesting( data < someValue ); -// ..do some stuff with data -~~~~~~~~ - -This does not stop execution by JPF, but stores an 'interesting' attribute for the current state. Its more general version is used to attach arbitrary strings to states: - -~~~~~~~~ {.java} -// ..compute some data -if (data < someValue) { - Verify.setAnnotation("critical data value"); - // ..do some stuff with dat -~~~~~~~~ - -Again, this category is about to become less important since Search- and VMListeners are superior mechanisms to store not just strings but arbitrary objects as state annotations. - -### Verification Output ### - -This is the most simple category, which is used to differentiate between normal program output (that is executed and analyzed by JPF), and output that is strictly verification relevant, i.e. should not appear when executing a program outside JPF. Not very surprising, it contains a number of print(..) methods. - -### Atomicity Control ### - -this category can be used to control the number of thread interleavings JPF has to analyze. While this is problematic in terms of missing potential defects, it is was often the only way to constrain the state space so that JPF could verify a given application. - -~~~~~~~~ {.java} -Verify.beginAtomic(); -... -// all code in here is executed by JPF in one transition -... -Verify.endAtomic(); -~~~~~~~~ - -Direct atomicity control was mainly used before the automatic, on-the-fly partial order reduction (POR) was implemented, and only remains relevant for applications that are (still) problematic with respect to POR. JPF's on-the-fly POR implementation is described in a [separate section](../devel/partial_order_reduction) of this documentation. - -### Other Usages ### - -Some `Verify` methods support collecting information during JPF execution, which is persistent and can be later-on queried by JPF embedding code (programs that execute JPF). This uses an MJI trick where the [native peer](../devel/mji) class (`JPF_gov_nasa_jpf_vm_Verify`) is used to set some data during JPF execution, which can be later-on retrieved by model class code (through `gov.nasa.jpf.vm.Verify`) that is executed outside of JPF. This is currently used to implement counters, which in turn are used to verify JPF itself. - -It should be noted that while most of the Verify APIs have alternative implementations that enable execution outside of JPF, applications using them at least don't build outside the JPF environment. Their use therefore is only recommended for JPF specific test drivers. \ No newline at end of file diff --git a/doc/user/application_types.md b/doc/user/application_types.md deleted file mode 100644 index 352e9c9..0000000 --- a/doc/user/application_types.md +++ /dev/null @@ -1,36 +0,0 @@ -# JPF Application Goals and Types # - -By now, you already know that you run JPF on compiled Java programs, just like a normal VM. But what are the goals to apply JPF, and - based on these goals - what are the different JPF application types? - -## Why to Use JPF? ## -Before we classify the different types of JPF applications, it is worth to spend a few thoughts on why we actually want to apply it. A word of caution: if you have a strictly sequential program with only a few well defined input values, you are probably better off writing a few tests - using JPF won't tell you much. There are two major reasons to run JPF: - -### Explore Execution Alternatives ### -After all, JPF started as a software model checker, so its original domain is to explore execution choices, of which we have four different types: - - - scheduling sequences - concurrent applications are still the major domain for JPF application because (a) defects like deadlocks and data races are subtle and usually spurious, and (b) the scheduler can usually not be controlled from a testing environment, i.e. this is hard to impossible to test. JPF on the other hand not only "owns" the scheduler (it is a virtual machine) and explores all interesting scheduling combinations, it even lets you define your own scheduling policies - - input data variation - JPF allows you to explore input value sets that can be defined by heuristics (e.g. a value below, at, and above a certain threshold). This is especially useful when writing test drivers - - environment events - program types like Swing or web applications usually react to external events like user input. Such events can be simulated by JPF as choice sets - - control flow choices - JPF can not only check how your program reacts to a concrete input, it can also turn around and systematically explore the program control structure (branch instructions) to compute input data values that would execute a certain part of your code. - -### Execution Inspection ### - -Even if your program does not have a lot of execution alternatives, you can make use of JPF's inspection capabilities. Being an extensible virtual machine, it is relatively easy to implement coverage analyzers, or non-invasive tests for conditions that would otherwise go unnoticed because they are hard or tedious to implement (like overflow in numerical instructions). - -## JPF Application Types ## -There are three basic JPF application types, each of them having different strengths and weaknesses: JPF- aware, unaware, and "enabled" programs. - -![Figure: JPF application types](../graphics/app-types.svg){align=center width=800} - -### JPF Unaware Programs ### -This is the usual case - you run JPF on an application that is not aware of verification in general, or JPF in particular. It just runs on any VM that is Java compatible. The typical reason to check such an application with JPF is to look for violations of so called non-functional properties that are hard to test for, such as deadlocks or race conditions. JPF is especially good at finding and explaining concurrency related defects, but you have to know the costs: JPF is much slower than a production VM (for a reason - it does a lot more than a normal byte code interpreter), and it might not support all the Java libraries that are used by the system under test. - -### JPF Dependent Programs ### -On the other side of the spectrum we have applications that are models - their only purpose in life is to be verified by JPF (e.g. to check a certain algorithm), so Java just happens to be the implementation language because that is what JPF understands. Typically, these applications are based on a domain specific framework (such as the [statechart extension](../projects/jpf-statechart) that has been written so that JPF can verify the model. As a consequence, the model applications themselves are usually small, scale well, and do not require additional property specification. The downside is that it is quite expensive to develop the underlying domain frameworks. - -### JPF Enabled Programs ### -The third category probably has the best return on investment - programs that can run on any VM, but contain Java annotations that represent properties which cannot easily be expressed with standard Java language. - -For example, assume you have a class which instances are not thread safe, and hence are not supposed to be used as shared objects. You can just run JPF and see if it finds a defect (like a data race) which is caused by illegally using such an object in a multi-threaded context. But even if JPF out-of-the-box can handle the size of the state space and finds the defect, you probably still have to spend a significant effort to analyze a long trace to find the original cause (which might not even be visible in the program). It is not only more easy on the tool (means faster), but also better for understanding if you simply mark the non-threadsafe class with a `@NonShared` annotation. Now JPF only has to execute up to the point where the offending object reference escapes the creating thread, and can report an error that immediately shows you where and how to fix it. - -There is an abundance of potential property-related annotations (such as `@NonNull` for a static analyzer and JPF), including support for more sophisticated, embedded languages to express pre- and post-conditions. diff --git a/doc/user/components.md b/doc/user/components.md deleted file mode 100644 index 55a01d2..0000000 --- a/doc/user/components.md +++ /dev/null @@ -1,57 +0,0 @@ -# JPF components # -Java is more than a programming language. It is a set of layers that starts with a platform specific VM implementation (which is referred to as the *host VM*) that sits on top of native libraries written for and using your operating system. To this stack, we add JPF - a Java application that runs on top of the "host VM", but is itself a VM which then executes your System Under Test (SUT). - -![Figure 1: Different layers involved when using JPF](../graphics/jpf-layers.svg){align=center width=700} - -With all this recursion, it is easy to get confused about what Java code gets processed at which level. To make things worse, most of the standard library class files (java.* classes) and some of the annotations get processed by both VMs, but of course in different instantiations. Purpose of this page is to shed some light on what code is associated with the different layers and parts of the system. - -In order to untangle, we have to step back and look at what components are involved when applying JPF to the SUT. We categorize the components with respect to two aspects: - - 1. processing VM (host VM, JPF) - 1. associated distribution entity (host Java installation, JPF core, JPF extensions, SUT) - -Remember the [What is JPF](../intro/what_is_jpf) diagram from the introduction? This is a more detailed version of it.  - -![Figure 2: JPF infrastructure](../graphics/jpf-intro-new.svg){align=center width=800} - -Let us walk this diagram left-to-right. We start with the compiled Java application we want to verify. This is of course not part of the JPF distribution, but will be executed by JPF, so the corresponding class files do not have to be visible to the host VM (that runs JPF). However, the application code might use classes and interfaces that reside in the JPF distribution. Together, the application and such modeling libraries and/or annotations form the System under Test (SUT) - -Next comes the JPF core itself. By now we know this is mainly a VM that is written in Java itself, so you run it on whatever Java system is installed on your machine. This means all classes that constitute JPF need to be visible to the host JVM, e.g. by setting the global `CLASSPATH` environment variable (which is not the recommended way to do this). - -Now comes the important part: **JPF is not a monolithic system**. It uses various configured components to do things such as - - * property implementation - * library modeling - * report generation - -and much more. Even if you don't specify anything when you run it, JPF will use a default configuration that pulls in a lot of components such as [listeners](../devel/listener), which do not have to be part of the [JPF core](../jpf-core/index), but can reside in their own JPF extension modules. - -If you do specify your own [configuration](../user/config), you can tell JPF to use components that live outside of the [JPF core](../jpf-core/index) distribution, either in one of the installed JPF extension modules, or in your own project. Either way, all these [listeners](../devel/listener), [native peers](../devel/mji), [publishers](../devel/report) and other components are at runtime part of the whole JPF system, so they need to be visible to the host VM. - -The last part is the most tricky one - your application is most probably using standard Java libraries (e.g. `System.out.println()`), as do the classes that constitute JPF. Some of the standard library classes have to be replaced by JPF specific versions when JPF executes the SUT (e.g. classes such as `java.lang.Class`that have native methods), and JPF has a special [MJI](../devel/mji) mechanism to do that. However, most standard library classes have pure Java implementations, and we take these straight from the host-JVM installation. This means, standard libraries end up in JPF's classpath *and* the host JVM CLASSPATH: and their code is executed by JPF *and* the host VM, but the corresponding instances are different (for instance, a `java.lang.String` object has very different representations in the host VM and JPF). - - -JPF keeps associated class paths separate. There are three different path settings in the JPF configuration: - - 1. `native_classpath` - this includes everything that has to be visible to the host VM, which includes mostly the classes of JPF itself, listeners, native peers and bytecode instruction sets. The `native_classpath` is dynamically constructed from your site.properties and jpf.properties [configuration files](../user/config) during JPF startup, and processed by the JPF classloader - 2. `classpath` - this includes the classes that are executed by JPF, which include your SUT, and all libraries that are used by it (*-classes.jar of installed JPF components). Note that some of the library classes (like `java.lang.Thread`) are replaced by JPF specific versions. Again, this is constructed by JPF during startup from all your configured jpf.properties files, but processed by JPFs internal classfile lookup mechanism. - 3. `sourcepath` - depending on the reports that have to be generated by JPF, it might have to find SUT and library sources for the executed classfiles (bytecodes). This is how you tell JPF where these sources reside. - -You can set these path lists explicitly from your application property file or the command line, but it is better to let JPF collect them when processing the jpf.properties files of your installed JPF components, which all include lines like - -~~~~~~~~ {/bash} -.native_classpath = .. -.classpath = .. -.sourcepath = .. -~~~~~~~~ - -A word of caution: if - during JPF startup - you encounter a message like - -~~~~~~~~ {.bash} -... -[SEVERE} error during VM runtime initialization: wrong model classes (check 'classpath') -~~~~~~~~ - -it means the `classpath` setting is wrong and JPF loads some of the standard library classes that have to be replaced with its own versions - they need to be *modeled* (like `java.lang.Thread`, `java.lang.Class` and others - all part of jpf-classes.jar within the jpf-core module). - -This can also happen later-on with less essential library classes that are not part of jpf-core, but should be loaded from one of the installed extensions. In this case, this usually shows up as an `UnsatisfiedLinkError` diff --git a/doc/user/config.md b/doc/user/config.md deleted file mode 100644 index a57d07b..0000000 --- a/doc/user/config.md +++ /dev/null @@ -1,153 +0,0 @@ -# Configuring JPF # - -JPF configuration can be intimidating. It is worth to think about why we need such a heavy mechanism before we dive into its details. Little in JPF is hardwired. Since JPF is such an open system that can be parameterized and extended in a variety of ways, there is a strong need for a general, uniform configuration mechanism. The challenge for this mechanism is that many of the parts which are subject to parameterization are configured themselves (i.e. options for optional JPF components like listeners). This effectively prohibits the use of a configuration object that contains concrete fields to hold configuration data, since this class would be a central "design bottleneck" for a potentially open number of JPF components like Searches, Instruction sets and Listeners. - -The goal is to have a configuration object that - - * is based on string values - * can be extended at will - * is passed down in a hierarchical initialization process so that every component extracts only its own parameters - -We achieve this by means of a central dictionary object (`gov.nasa.jpf.Config`) which is initialized through a hierarchical set of Java property files that target three different initialization layers: - - 1. site: optionally installed JPF components - 2. project: settings for each installed JPF module and (optionally) systems under test - 3. application: the class and program properties JPF should check (this is part of your system under test) - -Initialization happens in a prioritized order, which means you can override anything from later configuration stages, all the way up to command line parameters. Actually, this can be even overridden by using the `Verify` API from system under test code, but this is a developer topic. Here is the blueprint, which we will examine in order of execution: - -![Figure: Configuring JPF](../graphics/properties.svg){align=center width=800} - - -## Property Types ## - -Property specifications are processed in a hierarchical order: site properties, project properties, application properties and command line properties. Later stages can override previous stages. Each property is a `=` pair, but we do support some special notations (see below) for key/value expansion, value extension, and pseudo properties that act as directives. - -### Site Properties ### -The site.properties file is machine specific and not part of any JPF project, which means you have to create a [ site.properties](wiki:install/site-properties) file as part of the install process. A sample site.properties might look like: - -~~~~~~~~ -jpf-core = ${user.home}/projects/jpf/jpf-core -jpf-shell = ${user.home}/projects/jpf/jpf-shell -jpf-awt = ${user.home}/projects/jpf/jpf-awt -... -extensions=${jpf-core},${jpf-shell} -~~~~~~~~ - -Each module is listed as a `=` pair, and optionally added to the comma separated list of `extensions`. The order in which modules are added to `extensions` does matter, since it will determine the order in which each of these components is initialized, which basically maps to an ordered list of classpath entries (both for the host VM and JPF itself - paths are kept separate). - -Note that we do **not** require all modules being added to `extensions`, **but** jpf-core needs to be in there. Dependencies on modules not listed in `extensions` can be specified later-on with the `@using` directive. It is a good idea to keep the `extensions` list small to avoid conflicts, and to improve class load times (shorter classpaths). - -Note also that the `extensions` entries are of the form `${}`, which tells JPF to replace these expressions with the value that is associated to . - -Site properties have to be stored in the directory from where you start JPF, one of its parent directories, or a global `${user.home}/.jpf/site.properties`. We recommend a to keep it in a common root directory that contains all your JPF projects and modules. - - -### Project Properties ### -Each JPF module contains a jpf.properties file in its root directory, no matter if this is the jpf-core or an extension. System under test projects can contain a jpf.properties file to factor out common settings (such as class paths) for all JPF applications within this project. - -A project property file defines the JPF specific paths that need to be set for the module or system under test to work properly - - 1. `.`**`native_classpath`**: the host VM classpath (i.e. the classes that constitute JPF itself) - 1. `.`**`classpath`**: the classpath JPF uses to execute the system under test - 1. `.`**`test_classpath`**: host VM and JPF classpath for regression tests - 1. `.`**`sourcepath`**: the path entries JPF uses to locate sources in case it needs to create program traces - -Additionally, `jpf.properties` should contain default values for all module or project specific settings (e.g. report options). - -An example project properties file might look like: - -~~~~~~~~ {.bash} -jpf-aprop = ${config_path} - -#--- path specifications -jpf-aprop.native_classpath = build/jpf-aprop.jar;lib/antlr-runtime-3.1.3.jar -jpf-aprop.classpath = build/examples -jpf-aprop.test_classpath = build/tests -jpf-aprop.sourcepath = src/examples - -#--- other project specific settings -listener.autoload=${listener.autoload},javax.annotation.Nonnull,... -listener.javax.annotation.Nonnull=gov.nasa.jpf.aprop.listener.NonnullChecker -... -~~~~~~~~ - - - -The first entry (`=${config_path}`) in a jpf.properties should always define the module name. JPF automatically expands `${config_path}` with the pathname of the directory in which this jpf.properties file resides. - -jpf.properties are executed in order of definition within site.properties, with one caveat: if you start JPF from within a directory that contains a jpf.properties file, this one will always take precedence, i.e. will be loaded last (overriding previous settings except of the command line). This way, we ensure that JPF developers can enforce priority of the component they are working on. - -Both site.properties and jpf.properties can define or override any key/value pairs they want, but keep in mind that you might end up with different system behavior depending on where you start JPF - avoid configuration force fights by keeping jpf.properties settings disjunct wherever you can. - -Please note that site and project properties have to be consistent, i.e. the module names (e.g. jpf-awt) in site.properties and jpf.properties need to be the same. This is also true for the build.xml Ant project names. - -It is perfectly fine to have a jpf.properties in a SUT that only uses JPF for verification. You need at least to set up the `classpath` so that JPF knows where to find the SUT classes. - - -### Application Properties ### -In order to run JPF, you need to tell it what main class it should start to execute. This is the minimal purpose of the *.jpf application properties files, which are part of your systems under test (SUT). Besides the `target` setting that defines the main class of your SUT, you can also define a list of `target_args` and any number of JPF properties that define how you want your application to be checked (listeners, search policy, bytecode factories etc.). A typical example looks like - -~~~~~~~~ {.bash} -#--- dependencies on other JPF modules -@using = jpf-awt -@using = jpf-shell - -#--- what JPF should run -target = RobotManager - -#--- other stuff that defines how to run JPF -listener+=,.listener.OverlappingMethodAnalyzer - -shell=.shell.basicshell.BasicShell -awt.script=${config_path}/RobotManager-thread.es -cg.enumerate_random=true -... -~~~~~~~~ - -The `@using = ` directive tells JPF to load the `jpf.properties` of the specified projects (defined in `site.properties`). This is the way to ensure proper path initialization of projects that are not listed in `extensions`. - -### Command Line Properties ### -Last not least, you can override or extend any of the previous settings by providing "**+**=" pairs as command line options. This is convenient for experiments if you have to determine the right settings values empirically - - -## Special Property Syntax ## -JPF supports a number of special notations that are valid Java properties syntax, but are only processed by JPF (and - to a certain extend - by Ant): - - * **`key=...${x}..`** - replaces `"${x}"` with whatever is currently stored under the key "`x`". This also works recursively, as in "`classpath = mypath;${classpath}`". Note that while Apache Ant does also support value expansion, but not recursively. In addition, JPF also supports expansion in the key part (i.e. left of the "`=`") - - * **`key+=val`** - appends val to whatever is currently stored under "`key`". Note that there can be no blank between key and "`+=`", which would not be parsed by Java. This expansion only works in JPF - - * **`+key=val`** - in a properties file adds "`val`" in front of what is currently stored under "`key`". Note that if you want to use this from the command line, you have to use two "`++`", since command line options start with "+" - - * **`${config_path}`** - is automatically set to the directory pathname of the currently parsed property file. This can be useful to specify relative pathnames (e.g. input scripts for the jpf-awt extension) - - * **`${config}`** - is set to the file pathname of the currently parsed file - - * **`@requires=`** - can be used to short-circuit loading of a properties file. This is a simple mechanism to control loading of jpf.properties file sections that are incompatible with other modules, and compares to `#ifdef` preprocessor directives. The respective keys are usually set from application properties (*.jpf) files. -Note this does not throw an exception if the required key is not defined, it just bails out of loading the properties file that contains the @requires directive - - * **`@include=`** - recursively loads the properties file with the specified pathname. You can use the automatically defined `${config_path}` property to specify path names that are relative to where the file containing the `@include` directive is, or use `${}` for paths that are relative to the specified module. - - * **`@using=`** - is similar to `@include`, but loads the jpf.properties of the specified module name (which has to be defined in site.properties). Note that there is no `${..}` around the module name - otherwise it would be replaced. The `@using` directive is the preferred way to specify dependencies on modules that are not in the `extensions` list (i.e. automatically initialized). - - * **`@include_if = ??`** - is a conditional `@include` that only loads the properties file if the specified `` is defined - - * **`@include_unless = ??`** - likewise loads the file only if `` is not defined. Both of these directives are used rarely. - - * Omitting the "`=..`" part in command line settings defaults to a "`true`" value for the corresponding key - - * Setting an empty value (`key=`) removes the key from the config dictionary - -## Debugging ## -Depending on the number of installed and loaded projects, you can easily end up with hundreds of settings. There are two command line options you can use if you assume there is a configuration error: - - * **`-show`** - prints all Config entries after the initialization is complete - - * **`-log`** - lists the order in which properties files got loaded by JPF - -## Details on various options ## - -* [Randomization](config/random) - -* Error Reporting diff --git a/doc/user/config/random.md b/doc/user/config/random.md deleted file mode 100644 index 4fae737..0000000 --- a/doc/user/config/random.md +++ /dev/null @@ -1,15 +0,0 @@ -## Randomization Options in JPF ## - -The randomization options in JPF allow the user to experiment in randomizing the order of choices explored. - -`cg.randomize_choices` can have three possible values: random, path, def. - - * `random`: It explores random choices during program execution with **varying results among different trials**. The default seed used to generate different results is the **system time in milliseconds** - - * `path`: It explores random choices during program execution with **reproducible results among different trials**. The default seed used to generate reproducible results is **42**. The value of the seed can be changed by setting the seed config option. - - * `def`: No randomization, choices are explored using the default search order imposed by the model checker. - -`cg.seed (_INT_)`: The user can specify a particular seed for the random number generator in order to obtain reproducible results in the presence of randomization. Note that this is effective only when the `path` option of `randomize_choices` is selected. - - diff --git a/doc/user/index.md b/doc/user/index.md deleted file mode 100644 index 6626007..0000000 --- a/doc/user/index.md +++ /dev/null @@ -1,19 +0,0 @@ -# How to Use JPF # - -This section is where the real fun starts. Here you learn about - - - [Different applications of JPF](application_types) - - [JPF's runtime components](components) - - [Starting JPF](run) - - [Configuring JPF](config) - - [Understanding JPF output](output) - - [Using JPF's Verify API in the system under test](api) - -All this assumes you are more interested in running JPF than in developing with/for it, so we will leave most of the JPF internals for the [developer section](../devel/index) of this wiki. - -We do have to bother you with some basic concepts though. Keep in mind that JPF is usually not a black-box tool (such as a compiler). Most probably you have to configure it according to your needs because - - * you have specific verification goals (properties) - * your application has a huge state space that is challenging for a model checker - -On the other hand, JPF is also not a "works-or-fails" tool. Depending on how much time you want to invest, you can adapt it to almost all application types and verification goals. And since JPF is open sourced, chances are somebody has already done that diff --git a/doc/user/output.md b/doc/user/output.md deleted file mode 100644 index 349242d..0000000 --- a/doc/user/output.md +++ /dev/null @@ -1,98 +0,0 @@ -# Understanding JPF Output # - -There are three different ways a JPF run can produce output, each of them with a different purpose, but all controlled by the [general JPF configuration mechanism](config): - - 1. System under test output - what is the SUT doing?\ - - 2. JPF logging - what is JPF doing?\ - - 3. JPF reporting system - what is the result of the JPF run?\ - - - -## System Under Test Output ## - -This is the most simple form of output, which usually just consists of `System.out.println(..)` calls embedded in the application code. There is only one caveat - since this is executed by JPF as part of the application, the same print statement might be executed several times: - -~~~~~~~~ {.java} -public class MyApplication ..{ - ... - boolean cond = Verify.getBoolean(); - System.out.println("and the cond is: " + cond); - ... -} -~~~~~~~~ - -will produce - -~~~~~~~~ -... -and the cond is: true -... -and the cond is: false -... -~~~~~~~~ - -The second execution of the print statement is of course preceded by a backtrack operation of JPF (the `Verify.getBoolean()` statement has two choices `{true,false}`), but the backtracking might not be visible, e.g. when running without the `ExecTracker` or `ChoiceTracker` listeners. - -Since it can be sometimes confusing to see the same output twice without knowing if there is an iteration in the application, or JPF did backtrack between executions, there are two configuration options to control the output behavior: - -`vm.tree_output = {true|false}` - means output is shown on the console each time a print statement is executed. This corresponds to the above example, and is the default behavior. - -`vm.path_output = {true|false}` - will not immediately print the output on the console, but store in the path for subsequent processing once JPF terminates (if the *output* topic is specified - see below). This should produce the same output as running the test application on a normal JVM. - -## Logging ## - -This is a more interesting form of JPF output, primarily intended to show what JPF does internally. For this purpose, it has to support various levels of details, ranging from severe errors to fine grained logging of JPF operations. - -JPF's logging mechanism does not reinvent the wheel, it piggybacks on the standard java.util.logging infrastructure. While this means it would be possible to use customized LogHandlers and Formatters (e.g. to log in XML format), there are specialized JPF incarnations of these classes, mainly to enable logging configuration via the standard JPF configuration mechanism rather than system properties. - -Using the JPF Logging involves two aspects: (1) controlling log output destination, and (2) setting log levels. Both are done with JPF property files. - -To set the default log level, use the `log.level` property (the supported levels being *severe,warning,info,fine,finer,finest*) - -If you want to log to a different console that possibly even runs on a remote machine, use the gov.nasa.jpf.tools.LogConsole on the machine that should display the log messages: - -~~~~~~~~ {.bash} -$ java gov.nasa.jpf.tools.LogConsole -~~~~~~~~ - -Then start JPF on the test machine, specifying where the log output should go: - -~~~~~~~~ {.bash} -$ jpf +log.output=: ... MyTestApp -~~~~~~~~ - -The default host is "localhost", default port is 20000. If these are suitable settings, you can start the `LogConsole` without parameters, and just specify `+log.output=socket` when running JPF. - - -If you develop your own JPF classes, please also check the [JPF logging API](../devel/logging) page. - -## Reports ## - -The JPF reporting system is used to show the outcome of a JPF run, to report property violations, print traces, show statistics and much more. This is in a way the most important part of the JPF user interface, and might involve various different output formats (text, XML, API calls) and targets (console, IDE). Depending on application and project, users might also need control over what items are displayed in which order. It is also obvious this needs to be an extensible mechanism, to adapt to new tools and properties. The JPF report system provides all this, again controlled by JPF's general configuration mechanism. - -The basic concept is that reporting depends on a predefined set of output phases, each of them with a configured, ordered list of topics. The output phases supported by the current system are: - - * start - processed when JPF starts - * transition - processed after each transition - * property_violation - processed when JPF finds a property violation - * finished - processed when JPF terminates - -There is no standard transition topic yet (but it could be implemented in `PublisherExtensions`). The standard `property_violation` topics include: - - * error - shows the type and details of the property violation found - * trace - shows the program trace leading to this property violation - * snapshot - lists each threads status at the time of the violation - * output - shows the program output for the trace (see above) - * statistics - shows property statistics information - -Last not least, the finished list of topics that usually summarizes the JPF run: - - * result - reports if property violations were found, and shows a short list of them - * statistics - shows overall statistics information - -The system consists of three major components: (1) the Reporter, (2) any number of format specific Publisher objects, and (3) any number of tool-, property- and Publisher-specific PublisherExtension objects. Here is the blueprint: - - -Again, there is separate [report system API](../devel/report) documentation if you are interested in JPF development. diff --git a/doc/user/run.md b/doc/user/run.md deleted file mode 100644 index ce3b515..0000000 --- a/doc/user/run.md +++ /dev/null @@ -1,258 +0,0 @@ -# Running JPF # -There are five general ways to run JPF, depending on your execution environment (command prompt or IDE) and desired level of configuration support. This page has to cover quite some ground, so bear with us - - 1. [from a command prompt (operating system shell)](#command-line) - 2. [from an IDE (NetBeans, Eclipse) without using JPF plugins](#running-jpf-from-within-ide-without-plugins) - 3. [from an IDE with JPF plugins installed](#running-jpf-from-within-ide-with-plugins) - 4. [from within a JUnit test class](#launching-jpf-from-junit-tests) - 5. [single tests from command line](#explicitly-running-tests-from-the-command-line) - 6. [explicitly from an arbitrary Java program](#explicitly-launching-jpf-from-a-java-program) - -## Command Line ## - -There are several ways to run JPF from the command line, using varying degrees of its runtime infrastructure. The most simple way is to use the provided `bin/jpf` script of the jpf-core distribution. Go to the directory where your system under test (SUT) classes reside, and do a - -~~~~~~~~ {.bash} -> /bin/jpf +classpath=. -~~~~~~~~ - -or preferably - -~~~~~~~~ {.bash} -> /bin/jpf .jpf -~~~~~~~~ - -(see target specification below). If you want to avoid platform specific scripts, you only have to slightly expand this to - -~~~~~~~~ {.bash} -> java -jar /build/RunJPF.jar +classpath=. -~~~~~~~~ - -This makes use of the small RunJPF.jar startup jar that is part of the jpf-core distribution, which only includes the classes that are required to start the JPF bootstrapping process (esp. the JPF classloader). These classes automatically process the various [JPF configuration files](config). If your SUT is not trivial, it is also recommended to add a "-Xmx1024m" host VM option, to avoid running out of memory. - -Last (and probably most rarely), you can directly start JPF and give it an explicit classpath. This amounts to something like - -~~~~~~~~ {.bash} -> java -classpath /build/jpf.jar gov.nasa.jpf.JPF +classpath=. -~~~~~~~~ - -Of course, this gets quickly more complicated if you use JPF extensions, which require to add to both the host VM and the JPF classpath, which is completely automated if you use the RunJPF.jar method. Explicitly setting paths is only for rare occasions if you develop JPF components yourself. - -There are three different argument groups that are processed by JPF: - -#### (1) JPF command line options #### - -These options should come first (after RunJPF.jar), and all start with a hyphen ("-"). The set of currently supported options is: - - * -help : show usage information and exit - * -log : print the configuration steps - * -show : print the configuration dictionary after configuration is complete - -The last two options are mostly used to debug if the JPF configuration does not work as expected. Usually you start with `-show`, and if you don't see the values you expect, continue with `-log` to find out how the values got set. - - -#### (2) JPF properties #### - -This is the second group of options, which all start with a plus ("+") marker, and consist of "`+=`" pairs like - -~~~~~~~~ {.bash} -.. +cg.enumerate_random=true -~~~~~~~~ - -All properties from the various JPF properties [configuration files](config) can be overridden from the command-line, which means there is no limit regarding number and values of options. If you want to extend an existing value, you can use any of the following notations - - * `++=` - which appends - * `++=` - which prepends - * `+=..${}..` - which gives explicit control over extension positions - -Normal JPF properties `${}` expansion is supported. - -If the `=` part is omitted, a default value of `true` is assumed. If you want to set a value to null (i.e. remove a key), just skip the `` part, as in `+=` - -#### (3) target specification #### - -There are two ways to specify what application JPF should analyze - - * explicit classname and arguments - -~~~~~~~~ {.bash} -> jpf ... x.y.MyApplication arg1 arg2 .. -~~~~~~~~ - - * application property file (*.jpf) - -~~~~~~~~ {.bash} -> jpf ... MyApplication.jpf -~~~~~~~~ - -We recommend using the second way, since it enables you to store all required settings in a text file that can be kept together with the SUT sources, and also allows you to start JPF from within !NetBeans or Eclipse just by selecting the *.jpf file (this is mainly what the IDE plugins are for). Please note that application property files require a "`target`" entry, as in - -~~~~~~~~ {.bash} -# JPF application property file to verify x.y.MyApplication -target = x.y.MyApplication -target.args = arg1,arg2 -# Note that target_args in JPF 6 changed to target.args in JPF 7. -... -~~~~~~~~ - -## Running JPF from within IDE without plugins ## - -You can start JPF from within !NetBeans or Eclipse without having the IDE specific JPF plugins installed. In this case, JPF uses the standard IDE consoles to report verification results. For details, please refer to the following pages: - - * [Running JPF from within NetBeans without plugin](run_nb) - * [Running JPF from Eclipse without plugin](run_eclipse) - -Note that this is **not** the recommended way to run JPF from within an IDE, unless you want to debug JPF or your classes. - -## Running JPF from within IDE with plugins ## - -You can simplify launching JPF from within !NetBeans or Eclipse by using the respective plugins that are available from this server. In this case, you just have to create/select an application property (*.jpf) file within your test project, and use the IDE context menu to start a graphical JPF user interface. These so called "JPF shells" are separate applications (that can be configured through normal JPF properties), i.e. appear in a separate window, but can still communicate with the IDE, e.g. to position editor windows. You can find more details on - - * [Running JPF from within NetBeans with netbeans-jpf plugin](run_nb_plugin) - * [Running JPF from Eclipse with eclipse-jpf plugin](run_eclipse_plugin) - -This is becoming the primary method of running JPF. The benefits are twofold: (1) this is executed outside of the IDE process, i.e. it doesn't crash the IDE if JPF runs out of memory, and (2) it makes use of all your standard JPF configuration (site.properties and jpf.properties), in the same way like running JPF from a command-line. - -## Launching JPF from JUnit tests ## - -JPF comes with [JUnit](http://www.junit.org) based testing infrastructure that is used for its own regression test suite. This mechanism can also be used to create your own test drivers that are executed by JUnit, e.g. through an [Ant](http://ant.apache.org) build script. The source structure of your tests is quite simple - -~~~~~~~~ {.java} -import gov.nasa.jpf.util.test.JPFTestSuite; -import org.junit.Test; - -public class MyTest extends TestJPF { - - @Test - public void testSomeFunction() { - if (verifyNoPropertyViolation(jpfOptions)) { // specifies the test goal, "jpfOptions" are optional - someFuntction(); .. // this section is verified by JPF - } - } - - //.. more @Test methods -~~~~~~~~ - -From a JUnit perspective, this is a completely normal test class. You can therefore execute such a test with the standard `` [Ant](http://ant.apache.org) task, like - -~~~~~~~~ {.xml} - - - ... - - ... - - ... - - - - - - ... - - - - - ... -~~~~~~~~ - -Only jpf.jar needs to be in the host VM classpath when compiling and running the test, since `gov.nasa.jpf.util.test.TestJPF` will use the normal JPF configuration (site.properties and configured jpf.properties) to set up the required `native_classpath`, `classpath`, 'test_classpath` and `sourcepath` settings at runtime. Please refer to the [JPF configuration](config) page for details. - -If you don't have control over the build.xml because of the IDE specific project type (e.g. if your SUT is configured as a NetBeans "Class Library Project"), you have to add jpf.jar as an external jar to your IDE project configuration. - -In addition to adding jpf.jar to your build.xml or your IDE project configuration, you might want to add a jpf.properties file to the root directory of your project, to set up things like where JPF finds classes and sources it should analyze (i.e. settings that should be common for all your tests). A generic example could be - -~~~~~~~~ {.bash} - # example of JPF project properties file to set project specific paths - - # no native classpath required if this is not a JPF project itself - myproject.native_classpath=... - - # where does JPF find the classfiles to execute - myproject.classpath=build/classes - - # where do test classes reside - myproject.test_classpath=build/test/classes - - # other project common JPF settings like autoloaders etc. - listener.autoload+=,javax.annotation.Nonnull - listener.javax.annotation.Nonnull=.aprop.listener.NonnullChecker - ... -~~~~~~~~ - -You can find project examples here - - * [standard NetBeans project](../projects/standardnbproject) ("Java Class Library" or "Java Application") - * Freeform NetBeans project (with user supplied build.xml) - * standard Eclipse project (with user supplied build.xml) - -Please refer to the [Verify API](api) and the [JPF tests](../devel/jpf_tests) pages for details about JPF APIs (like `verifyNoPropertyViolation(..)` or `Verify.getInt(min,max)`) you can use within your test classes. - -Since JPF projects use the same infrastructure for their regression tests, you can find a wealth of examples under the `src/tests` directories of your installed JPF projects. - -## Explicitly Running Tests from the command line ## - -You can also run your `TestJPF` derived test drivers by using the `bin/test` script (which in turn just a short for "`java -jar tools/RunTest.jar`", i.e. is platform independent): - -~~~~~~~~ {.bash} -bin/test [] -~~~~~~~~ - -Note that each `verify..(jpfArgs)` uses its own `Config` instance in this case. If you want to specify temporary JPF options from the command-line when running `RunTest`, prefix them with `test` like in the following example - -~~~~~~~~ {.bash} -bin/test +test.listener=.listener.ExecTracker gov.nasa.jpf.test.mc.basic.AttrsTest -~~~~~~~~ - -## Explicitly Launching JPF from a Java Program ## -Since JPF is a pure Java application, you can also run it from your own application. The corresponding pattern looks like this: - -~~~~~~~~ {.java} -public class MyJPFLauncher { - ... - public static void main(String[] args){ - .. - try { - - // this initializes the JPF configuration from default.properties, site.properties - // configured extensions (jpf.properties), current directory (jpf.properies) and - // command line args ("+=" options and *.jpf) - Config conf = JPF.createConfig(args); - - // ... modify config according to your needs - conf.setProperty("my.property", "whatever"); - - // ... explicitly create listeners (could be reused over multiple JPF runs) - MyListener myListener = ... - - JPF jpf = new JPF(conf); - - // ... set your listeners - jpf.addListener(myListener); - - jpf.run(); - if (jpf.foundErrors()){ - // ... process property violations discovered by JPF - } - } catch (JPFConfigException cx){ - // ... handle configuration exception - // ... can happen before running JPF and indicates inconsistent configuration data - } catch (JPFException jx){ - // ... handle exception while executing JPF, can be further differentiated into - // ... JPFListenerException - occurred from within configured listener - // ... JPFNativePeerException - occurred from within MJI method/native peer - // ... all others indicate JPF internal errors - } - ... -~~~~~~~~ - -Please refer to the [Embedding JPF](../devel/embedded) developers documentation for details. If you start JPF through your own launcher application, you have to take care of setting up the required `CLASSPATH` entries so that it finds your (and JPFs) classes, or you can use the generic `gov.nasa.jpf.Main` to load and start your launcher class, which makes use of all the path settings you have in your [site.properties](../install/site-properties) and the directories holding project properties (jpf.properties) referenced therein (details on [how to configure JPF](../user/config). This brings us back to the command line at the top of this page, only that you specify which class should be loaded through `Main`: - -~~~~~~~~ {.bash} -> java -jar .../RunJPF.jar -a MyJPFLauncher ... -~~~~~~~~ - -(note that `gov.nasa.jpf.Main` is the `Main-Class` entry of the executable RunJPF.jar, which also holds the `JPFClassLoader`). - -Just for the sake of completeness, there is another way to start JPF explicitly through a `gov.nasa.jpf.JPFShell` implementation, which is using the normal `JPF.main()` to load your shell, which in turn instantiates and runs a `JPF` object. This is specified in your application property (*.jpf) file with the `shell=` option. Use this if your way to start JPF is optional, i.e. JPF could also be run normally with your *.jpf. \ No newline at end of file diff --git a/doc/user/run_eclipse.md b/doc/user/run_eclipse.md deleted file mode 100644 index 72a8e3a..0000000 --- a/doc/user/run_eclipse.md +++ /dev/null @@ -1,20 +0,0 @@ -## Running JPF within eclipse ## - -To run JPF in eclipse after building - -* JPF click "Run"-->"Run" or click "Play"-->"Run As Dialog". - -* Select Java Application and click "New". - -* Click on the "Main" tab. Ensure the project selected is jpf-core and the in the Main Class pick `gov.nasa.jpf.JPF`. - -* Click on the "Arguments" tab. Specify the `` in the Program Arguments. Any additional configuration properties can be specified. For example, - -~~~~~~~~ {.bash} -+cg.randomize_choices=true -oldclassic -~~~~~~~~ - -* Click on "Run" to verify the application in JPF. The output of the program and the results will be displayed on the eclipse console window. - -Alternatively you pick the run-jpf-core launch configuration and add the `` of the system under test. The eclipse IDE detects the various launch configurations. When you click on the Run button they appear on the left column, pick "run-jpf-core". It is, however, recommended you run the application with the eclipse plugin for better performance and ease of usability. \ No newline at end of file diff --git a/doc/user/run_eclipse_plugin.md b/doc/user/run_eclipse_plugin.md deleted file mode 100644 index a2f40e8..0000000 --- a/doc/user/run_eclipse_plugin.md +++ /dev/null @@ -1,12 +0,0 @@ -# Running JPF from within Eclipse using eclipse-jpf # - -eclipse-jpf can be easily configured to run JPF from within Eclipse - - 1. Install eclipse-jpf (see [Installing Eclipse JPF plugin](../install/eclipse-plugin)) - 2. Make sure that the correct site.properties file is being used for JPF (The default is usually correct) - To see which site.properties file is being used: - 3. From the Eclipse top menu go to **Window**->**Preferences** - 4. Select **JPF Preferences** - 5. Make sure that "Path to site.properties" is defined properly. - 6. From either the **Package Explorer** view (On the left of the main Eclipse screen by default) right-click on the *.jpf with the JPF configuration wanted and select **Verify...** - 7. Make sure that the **Console view** (Usually at the bottom of the main Eclipse screen) is opened to view the results from JPF \ No newline at end of file diff --git a/doc/user/run_nb.md b/doc/user/run_nb.md deleted file mode 100644 index b6e60d9..0000000 --- a/doc/user/run_nb.md +++ /dev/null @@ -1,92 +0,0 @@ -# Running JPF from within NetBeans without JPF plugin # - -Please Note that the following description assumes NetBeans "freeform projects". In general, it is much better to use the JPF plugins, which not only make the configuration steps described below obsolete, but also work with other NetBeans project types. - -Since the NetBeans build process is Ant based, and Ant can read a subset of JPF configuration files, integration is fairly straight forward. Every JPF project comes with its own build.xml, and a `.../nbproject` directory that holds a NetBeans specific project.xml and ide-file-target.xml file, which can serve as templates for your own projects. - -Once everything is configured correctly, you can run JPF by selecting application property (*.jpf) files in the "project view", and do a "Run"->"Run File" from the NetBeans main menu (without the plugin, there will be no "run" item in the project view context menu, but hotkeys should still work). - -To make this work, you have to configure two NetBeans specific files: - -### nbproject/project.xml ### - -If you want to use JPF specific classes (like annotations), you have to make sure the NetBeans source checker will see them. You can achieve this by re-using the JPF property files to set the required classpaths, like - -~~~~~~~~ {.xml} -... - - ... - - ${user.home}/.jpf/site.properties - ${jpf-core}/jpf.properties - ... - - ... - - - ... - ...;${jpf-core.native_classpath} - - ... -~~~~~~~~ - -This works for two reasons: - - * Ant supports `${key}` expansion from properties (as long as they are not self-recursive) - * Ant properties are single-assignment, i.e. subsequent definitions of the same property name will be ignored - -The next step is required no matter if you use JPF types or not - you have to define file actions, which will link to the ide-file-targets.xml - -~~~~~~~~ {.xml} - ... - - ... - - - run-selected-jpf - - jpf.config - ... - \.jpf$ - absolute-path - - - - - - ... -~~~~~~~~ - -It seems this has to be defined for each source folder, which can require a number of redundant XML elements - -### nbproject/ide-file-targets.xml ### - -Within this file, you have to provide the scripts to run the actions defined in the project.xml. This can also make use of the JPF configuration files: - -~~~~~~~~ {.xml} - - - - - - - ... - - - ... - - Must set property 'jpf.config' - - - - - - - ... - - - - - ... -~~~~~~~~ - diff --git a/doc/user/run_nb_plugin.md b/doc/user/run_nb_plugin.md deleted file mode 100644 index 134634e..0000000 --- a/doc/user/run_nb_plugin.md +++ /dev/null @@ -1,12 +0,0 @@ -# Running JPF from within NetBeans with netbeans-jpf plugin # -netbeans-jpf can be easily configured to run JPF at the click of a mouse. - - 1. Install netbeans-jpf (see: [Installing the NetBeans JPF plugin](../install/netbeans-plugin)) - 2. Make sure the correct `site.properties` file is being used for JPF (The default is usually correct)\ - To see which `site.properties` file is being used: - 3. From the NetBeans top menu go to "Tools"->"Options" (Alt+T followed by Alt+O) - 4. Select "Miscellaneous" from the top of the Options Window - 5. Select the "Java Pathfinder" tab - 6. Make sure that "Path to `site.properties`" is defined properly, uncheck "Use default `site.properties` location" to change the path - 7. From either the "Projects" or "Files" view (on the left of the main NetBeans screen by default,) select the JPF properties file (i.e., a file with a `.jpf` extension) you would like to run. Right click on this file and select the "Verify..." menu item to run JPF. - 8. To view the results, make sure that the "Output" View is open (On the bottom of the main NetBeans screen by default) \ No newline at end of file diff --git a/docs/devel/attributes.md b/docs/devel/attributes.md new file mode 100644 index 0000000..69c7f83 --- /dev/null +++ b/docs/devel/attributes.md @@ -0,0 +1,18 @@ +# The Attribute System # + +While JPF stores values for operands, local variables and fields very similar to a normal VM, it also features a storage extension mechanism that lets you associate arbitrary objects with stack slots (operands and locals), fields, and whole objects (ElementInfos). The attribute objects can be set/used in [native peers](mji) or [listeners](listener) to add state stored/restored information that automatically follows the data flow. + +Note that JPF does not restore attribute object values upon backtracking per default, only attribute references. If you need to make sure attribute values are restored, you have to use copy-on-write and then store back when accessing and modifying such attributes. + +![Figure: JPF Attribute System](../graphics/attributes.svg){align=center width=650} + +JPF provides an API to set/access these attributes, which is located in `gov.nasa.jpf.vm.Fields` (for field attributes) and `gov.nasa.jpf.vm.StackFrame` (for local variables and operands). Once set, the VM copies the attributes each time it reads/writes the associated field or stackframe slot. + +## Usage ## + +For example, such attributes can be used to represent symbolic values or numeric error bounds. It should be noted though that attributes impose additional runtime costs, which is also why we don't treat normal, concrete values just as a special kind of attribute (normal values are still stored separately as builtin types like `int`). The upside of this is that your attributes coexist with normal, concrete values, which for instance allows things like mixed symbolic and concrete execution. + +> **Note:** JPF now can associate attributes not only with fields of an object, but with the object as a whole. See the `gov.nasa.jpf.vm.ElementInfo` API for details. + +> **Note:** while there is an API to set/retrieve attributes based on type, there is no implementation +yet that allows multiple attributes to be stored. \ No newline at end of file diff --git a/docs/devel/bytecode_factory.md b/docs/devel/bytecode_factory.md new file mode 100644 index 0000000..6fb8c2c --- /dev/null +++ b/docs/devel/bytecode_factory.md @@ -0,0 +1,70 @@ +# Bytecode Factories # +Normally, a VM defines the semantics of it's programming language. In case of Java, the corresponding instruction set represents a multi-threaded stack machine, where values are kept on the heap, or inside of local and/or operand slots within stack frames. The effect of Java bytecode instructions with respect to heap, locals and operands are described in [Sun's Java virtual machine specifications](http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html/). +JPF is different. The VM of JPF and its associated constructs like `ThreadInfo`, `ClassInfo`, `ElementInfo` etc. provide all the necessary means to implement a normal Java interpreter. However, JPF delegates the use of these means to the instructions. Every bytecode that gets executed by JPF is represented by a corresponding `Instruction` object, which normally gets instantiated during class load time. The `Instruction` classes of the standard execution mode can be found in package `gov.nasa.jpf.jvm.bytecode`. + +When it comes to executing a bytecode, the VM simply calls the `execute()` method of this `Instruction` instance. The implementation of this method defines the execution semantics. + +The trick is now that JPF uses a configurable [abstract factory](http://en.wikipedia.org/wiki/Abstract_factory_pattern) to choose and instantiate the `Instruction` classes. By providing your own concrete `InstructionFactory`, together with a set of related `Instruction` classes, you can change the execution semantics of Java. + +![Figure: Bytecode Factories](../graphics/bc-factory.svg){align=center width=850} + +## Usages ## + +Why would it be useful to change the standard semantics? One reason is to extend normal semantics with additional checks. For example, this is performed by the JPF extension jpf-numeric which overrides numeric bytecode classes with versions that check for over-/underflow and silent NaN propagation (among other things). A much more involved example is the JPF extension jpf-symbc, which implements a symbolic execution mode for Java, e.g. to automatically generate test cases based on the program structure of an application. It does so by overriding branch instructions, turning them into state space branches represented by their own [ChoiceGenerators](choicegenerator), collecting the path conditions on the way, and feeding them to an external SAT solver. + +## Implementation ## + +Since there is a large number of Java bytecode instructions, it would be tedious having to implement all 250+ Instruction classes in order to override just a couple of them. You can reduce the effort in three ways: + + +### GenericInstructionFactory ### + + +Using the `GenericInstructionFactory` as a base class for your `InstructionFactory`. This only requires you to specify an alternative package where your bytecode classes reside, together with the set of bytecodes that should be overridden. The resulting code can be quite short, as can be seen in the *numeric* extension example: + +~~~~~~~~ {.java} +public class NumericInstructionFactory extends GenericInstructionFactory { + + // which bytecodes do we replace + static final String[] BC_NAMES = { + "DCMPG", "DCMPL", "DADD", "DSUB", "DMUL", "DDIV", + "FCMPG", "FCMPL", "FADD", "FSUB", "FMUL", "FDIV", + "IADD", "ISUB", "IMUL", "IDIV", "IINC", + "LADD", "LSUB", "LMUL", "LDIV" + }; + + // where do they reside + protected static final String BC_PREFIX = "gov.nasa.jpf.numeric.bytecode."; + + // what classes should use them + protected static final String[] DEFAULT_EXCLUDES = { "java.*", "javax.*" }; + + public NumericInstructionFactory (Config conf){ + super(conf, BC_PREFIX, BC_NAMES, null, DEFAULT_EXCLUDES); + + NumericUtils.init(conf); + } +} +~~~~~~~~ + + +### Super Delegation ### + +You can derive your overriding bytecode classes from the ones in `gov.nasa.jpf.jvm.bytecode`. If you just want to add some checks before or after performing the "normal" operation, you can use the standard `Instruction` classes as base classes, and call `super.execute(..)` from within your derived classes. + + +### Attributes ### + +As your execution semantics get more complex, you probably need to store and restore additional information that is associated with variables. JPF provides an automatically managed [attribute system](attributes) for this purpose. You can attach objects to locals, operands and fields, and JPF takes care of propagating these attribute objects whenever it manipulates stackframes or heap objects. + + +## Configuration ## + + +Configuring your bytecode factory just requires one JPF property, e.g. + +~~~~~~~~ {.bash} +vm.insn_factory.class = gov.nasa.jpf.numeric.NumericInstructionFactory +~~~~~~~~ + +which can be either done from the command line or from within a *.jpf property file diff --git a/docs/devel/choicegenerator.md b/docs/devel/choicegenerator.md new file mode 100644 index 0000000..e8272eb --- /dev/null +++ b/docs/devel/choicegenerator.md @@ -0,0 +1,212 @@ +# ChoiceGenerators # + +The goal of every model checker is to check if certain properties hold in states of the system under test. The way that choices are computed is a fundamental part of model checking, since they determine which states are checked. We refer to the mechanism used by JPF to capture choices as ChoiceGenerators. + +ChoiceGenerators can be approached from an application perspective, or from the JPF implementation perspective. In this section, we cover both perspectives. + +## Motivation ## + +Whenever the model checker reaches non-determinism in code, it needs to compute choices. Non-determinism can be due to thread scheduling or non-deterministic data acquisitions. Here, we present an example including data non-determinism to justify our implementation approach. JPF provides support for "random" data acquisition, using the interface `gov.nasa.jpf.jvm.Verify`. + +~~~~~~~~ {.java} +... +boolean b = Verify.getBoolean(); // evaluated by JPF for both `true` and `false` +... +~~~~~~~~ + +This worked nicely for small sets of choice values (such as `{true,false}` for boolean), but the mechanism for enumerating all choices from a type specific interval becomes already questionable for large intervals (e.g. `Verify.getInt(0,10000)`), and fails completely if the data type does not allow finite choice sets at all (such as floating point types): + +![Figure 1: Motivation behind ChoiceGenerator](../graphics/cg-motivation.svg){align=center width=750} + +To handle this case, we have to leave the ideal world of model checking (that considers all possible choices), and make use of what we know about the real world - we have to use heuristics to make the set of choices finite and manageable. However, heuristics are application and domain specific, and it would be a bad idea to hardcode them into the test drivers we give JPF to analyze. This leads to a number of requirements for the JPF choice mechanism: + + * choice mechanisms have to be decoupled (i.e. thread choices should be independent of data choices, double choices from int choices etc.) + * choice sets and enumeration should be encapsulated in dedicated, type specific objects. The VM should only know about the most basic types, and otherwise use a generic interface to obtain choices + * selection of classes representing (domain specific) heuristics, and parametrization of ChoiceGenerator instances should be possible at runtime, i.e. via JPF's configuration mechanism (properties) + +The diagram shown above depicts this with an example that uses a "randomly" chosen velocity value of type double. As an example heuristic we use a threshold model, i.e. we want to know how the system reacts below, at, and above a certain application specific value (threshold). We reduce an infinite set of choices to only three "interesting" ones. Of course, "interesting" is quite subjective, and we probably want to play with the values (delta, threshold, or even used heuristic) efficiently, without having to rebuild the application each time we run JPF. + +The code example does not mention the used `ChoiceGenerator` class (`DoubleThresholdGenerator`) at all, it just specifies a symbolic name `"velocity"`, which JPF uses to look up an associated class name from its configuration data (initialized via property files or the command line - see Configuring JPF Runtime Options). But it doesn't stop there. Most heuristics need further parameterization (e.g. threshold, delta), and we provide that by passing the JPF configuration data into the `ChoiceGenerator` constructors (e.g. the `velocity.threshold` property). Each `ChoiceGenerator` instance knows its symbolic name (e.g. `"velocity"`), and can use this name to look up whatever parameters it needs. + +## The JPF Perspective ## + +Having such a mechanism is nice to avoid test driver modification. But it would be much nicer to consistently use the same mechanism not just for data acquisition choices, but also scheduling choices (i.e. functionality that is not controlled by the test application). JPF's ChoiceGenerator mechanism does just this, but in order to understand it from an implementation perspective we have to take one step back and look at some JPF terminology: + +![Figure 2: States, Transitions and Choices](../graphics/cg-ontology.svg){align=center width=650} + + +*State* is a snapshot of the current execution status of the application (mostly thread and heap states), plus the execution history (path) that lead to this state. Every state has a unique id number. State is encapsulated in the `SystemState` instance (almost, there is some execution history which is just kept by the JVM object). This includes three components: + + * KernelState - the application snapshot (threads, heap) + * trail - the last Transition (execution history) + * current and next ChoiceGenerator - the objects encapsulating the choice enumeration that produces different transitions (but not necessarily new states) + +*Transition* is the sequence of instructions that leads from one state to the next. There is no context switch within a transition, it's all in the same thread. There can be multiple transitions leading out of one state (but not necessarily to a new state). + +*Choice* is what starts a new transition. This can be a different thread (i.e. scheduling choice), or different "random" data value. + +In other words, possible existence of choices is what terminates the last transition, and selection of a choice value precludes the next transition. The first condition corresponds to creating a new `ChoiceGenerator`, and letting the `SystemState` know about it. The second condition means to query the next choice value from this `ChoiceGenerator` (either internally within the VM, or in an instruction or native method). + +## How it comes to Life ## +With this terminology, we are ready to have a look at how it all works. Let's assume we are in a transition that executes a `getfield` bytecode instruction (remember, JPF executes Java bytecode), and the corresponding object that owns this field is shared between threads. For simplicity's sake, let's further assume there is no synchronization when accessing this object, (or we have turned off the property `vm.sync_detection`). Let's also assume there are other runnable threads at this point. Then we have a choice - the outcome of the execution might depend on the order in which we schedule threads, and hence access this field. There might be a data race. + +![Figure 3: ChoiceGenerator Sequence](../graphics/cg-sequence.svg){align=center width=550} + +Consequently, when JPF executes this `getfield` instruction, the `gov.nasa.jpf.jvm.bytecode.GETFIELD.execute()` method does three things: + + 1. create a new `ChoiceGenerator` (`ThreadChoiceGenerator` in this case), that has all runnable threads at this point as possible choices + 2. registers this `ChoiceGenerator` via calling `SystemState.setNextChoiceGenerator()` + 3. schedules itself for re-execution (just returns itself as the next instruction to execute within the currently running thread) + +At this point, JPF ends this transition (which is basically a loop inside `ThreadInfo.executeStep()`), stores a snapshot of the current State, and then starts the next transition (let's ignore the search and possible backtracks for a moment). The `ChoiceGenerator` created and registered at the end of the previous transition becomes the new current `ChoiceGenerator`. Every state has exactly one current `ChoiceGenerator` object that is associated with it, and every transition has exactly one choice value of this `ChoiceGenerator` that kicks it off. Every transition ends in an instruction that produces the next `ChoiceGenerator`. + +The new transition is started by the `SystemState` by setting the previously registered `ChoiceGenerator` as the current one, and calling its `ChoiceGenerator.advance()` method to position it on its next choice. Then the `SystemState` checks if the current `ChoiceGenerator` is a scheduling point (just a `ThreadChoiceGenerator` used to encapsulate threads scheduling), and if so, it gets the next thread to execute from it (i.e. the `SystemState` itself consumes the choice). Then it starts the next transition by calling `ThreadInfo.executeStep()` on it. + +The `ThreadInfo.executeStep()` basically loops until an Instruction.execute() returns itself, i.e. has scheduled itself for re-execution with a new `ChoiceGenerator`. When a subsequent `ThreadInfo.executeStep()` re-executes this instruction (e.g. `GETFIELD.execute()`), the instruction notices that it is the first instruction in a new transition, and hence does not have to create a `ChoiceGenerator` but proceeds with it's normal operations. + +If there is no next instruction, or the Search determines that the state has been seen before, the VM backtracks. The `SystemState` is restored to the old state, and checks for not-yet-explored choices of its associated ChoiceGenerator by calling `ChoiceGenerator.hasMoreChoices()`. If there are more choices, it positions the `ChoiceGenerator` on the next one by calling `ChoiceGenerator.advance()`. If all choices have been processed, the system backtracks again (until it's first `ChoiceGenerator` is done, at which point we terminate the search). + +![Figure 4: ChoiceGenerator Implementation](../graphics/cg-impl.svg){align=center width=850} + +The methods that create `ChoiceGenerators` have a particular structure, dividing their bodies into two parts: + + 1. *top half* - (potentially) creates and registers a new `ChoiceGenerator`. This marks the end of a transition + 2. *bottom half* - which does the real work, and might depend on acquiring a new choice value. This is executed at the beginning of the next transition + +To determine which branch you are in, you can call `ThreadInfo.isFirstStepInsn()`. This will return `true` if the currently executed instruction is the first one in the transition, which corresponds to the *bottom half* mentioned above. + +The only difference between scheduling choices and data acquisition choices is that the first ones are handled internally by the VM (more specifically: used by the `SystemState` to determine the next thread to execute), and the data acquisition is handled in the bottom half of `Instruction.execute()`, native method, or listener callback method (in which case it has to acquire the current `ChoiceGenerator` from the `SystemState`, and then explicitly call `ChoiceGenerator.getNextChoice()` to obtain the choice value). For a real example, look at the `JPF.gov_nasa_jpf_jvm_Verify.getBoolean()` implementation. + +As an implementation detail, creation of scheduling points are delegated to a `Scheduler` instance, which encapsulates a scheduling policy by providing a consistent set of `ThreadChoiceGenerators` for the fixed number of instructions that are scheduling relevant (`monitor_enter`, synchronized method calls, `Object.wait()` etc.). Clients of this `Scheduler` therefore have to be aware of that the policy object might not return a new `ChoiceGenerator`, in which case the client directly proceeds with the bottom half execution, and does not break the current transition. + +The standard classes and interfaces for the ChoiceGenerator mechanism can be found in package `gov.nasa.jpf.vm`, and include: + + * `ChoiceGenerator` + * `BooleanChoiceGenerator` + * `IntChoiceGenerator` + * `DoublechoiceGenerator` + * `ThreadChoiceGenerator` + * `SchedulingPoint` + * `SchedulerFactory` + * `DefaultSchedulerFactory` + +Concrete implementations can be found in package `gov.nasa.jpf.vm.choice`, and include classes like: + + * `IntIntervalGenerator` + * `IntChoiceFromSet` + * `DoubleChoiceFromSet` + * `DoubleThresholdGenerator` + * `ThreadChoiceFromSet` + +As the number of useful generic heuristics increases, we expect this package to be expanded. + + +## Cascaded ChoiceGenerators ## +There can be more than one `ChoiceGenerator` object associated with a transition. Such ChoiceGenerators are referred to as *cascaded*, since they give us a set of choice combinations for such transitions. + +For example, assume that we want to create a listener that perturbs certain field values, i.e. it replaces the result operand that is pushed by a `getfield` instruction. This is easy to do from a listener, but the VM (more specifically our on-the-fly [partial order reduction](partial_order_reduction)) might already create a `ThreadChoiceGenerator` (scheduling point) for this `getfield` if it refers to a shared object, and the instruction might cause a data race. Without cascaded `ChoiceGenerators` we could only have the perturbation listener **or** the race detection, but not both. This is clearly a limitation we want to overcome, since you might not even know when JPF - or some of the other [listeners](listener) or [bytecode_factories](bytecode_factory) - create `ChoiceGenerators` that would collide with the ones you want to create in your listener. + +Using cascaded ChoiceGenerators requires little more than what we have already seen above. It only involves changes to two steps: + + 1. ChoiceGenerator creation - you need to identify `ChoiceGenerators` with a `String` id. We can't use the type of the `ChoiceGenerator` - or it's associated choice type - to identify a particular instance, since different listeners might use different `ChoiceGenerator` instances of same types for different purposes. Resolving through unique types would throw us back to where we would have to know about all the other `ChoiceGenerators` created by all the other JPF components. We can't use the associated instruction either, because the whole point is that we can have more than one `ChoiceGenerator` for each of them. So we have to give our `ChoiceGenerator` instances names when we create them, as in + +~~~~~~~~ {.java} +... +IntChoiceFromSet cg = new IntChoiceFromSet("fieldPerturbator", 42, 43); +~~~~~~~~ + +The name should be reasonably unique, describing the context in which this choice is used. Don't go with "generic" names like "myChoice". In case of doubt, use the method name that creates the `ChoiceGenerator`. The reason why we need the *id* in the first place is that we later-on want to be able to retrieve a specific instance. Which brings us to: + + 2. ChoiceGenerator retrieval - at some point we want to process the choice (usually within the *bottom half* of the method that created the `ChoiceGenerator`), so we need to tell JPF all we know about the `ChoiceGenerator` instance, namely id and type. The simple `SystemState.getChoiceGenerator()` we used above will only give us the last registered one, which might or might not be the one we registered ourselves. Retrieval is done with a new method `SystemState.getCurrentChoiceGenerator(id,cgType)`, which in the above case would look like: + +~~~~~~~~ {.java} +... +IntChoiceFromSet cg = systemState.getCurrentChoiceGenerator("fieldPerturbator", IntChoiceFromSet.class); +assert cg != null : "required IntChoiceGenerator not found"; +... +~~~~~~~~ + +This method returns `null` if there is no `ChoiceGenerator` of the specified id and type associated with the currently executed instruction. If this is the bottom half of a method that created the instance, this is most likely an error condition that should be checked with an assertion. If the retrieval is in another method, existence of such a `ChoiceGenerator` instance could be optional and you therefore have it checked in an `if (cg != null) {..}' expression. + +This is all there is to it in case you don't refer to a particular execution state of an instruction. As an example, assume that you want to add some int choices on top of each `Verify.getInt(..)` call. Your listener would look like this: + +~~~~~~~~ {.java} + @Override + public void instructionExecuted(VM vm, ThreadInfo ti, Instruction nextInsn, Instruction executedInsn) { + SystemState ss = vm.getSystemState(); + + if (executedInsn instanceof EXECUTENATIVE) { // break on method call + EXECUTENATIVE exec = (EXECUTENATIVE) executedInsn; + + if (exec.getExecutedMethodName().equals("getInt")){ // Verify.getInt(..) - this insn did create a CG on its own + if (!ti.isFirstStepInsn()){ // top half - first execution + IntIntervalGenerator cg = new IntIntervalGenerator("instrumentVerifyGetInt", 3,4); + ss.setNextChoiceGenerator(cg); + ... + + } else { // bottom half - re-execution at the beginning of the next transition + IntIntervalGenerator cg = ss.getCurrentChoiceGenerator("instrumentVerifyGetInt", IntIntervalGenerator.class); + assert cg != null : "no 'instrumentVerifyGetInt' IntIntervalGenerator found"; + int myChoice = cg.getNextChoice(); + ... // process choice + } + } + } + } +~~~~~~~~ + + +Sometimes what you do with your choice depends on the execution state of the instruction this `ChoiceGenerator` was created for, and you have to be aware of that the instruction might get re-executed (e.g. after processing the top half of another `ChoiceGenerator` creating method) before it has done what you depend on for your local choice processing. Consider our previous example of the field perturbation. Simply speaking, all we want to do in our listener is just swap operand stack values after a certain `getfield`. However, the partial order reduction of the VM might get in our way because it reschedules the instruction *before* it pushes the value if execution of this instruction might constitute a data race, and therefore required creation of a `ThreadChoiceGenerator` instance. What is worse is that the VM might do this conditionally - if there is only one runnable thread, there is no need for a scheduling point since there can't be a data race. Our own perturbator listener has to account for all that. Luckily, we can use `SystemState.getCurrentChoiceGenerator(id,type)` to unify all these cases, and we just have to restore execution state in case we want to re-execute the instruction ourselves. Here is an example: + +~~~~~~~~ {.java} + @Override + public void instructionExecuted(VM vm, ThreadInfo ti, Instruction nextInsn, Instruction executedInsn) { + SystemState ss = vm.getSystemState(); + + if (executedInsn instanceof GETFIELD){ + GETFIELD getInsn = (GETFIELD) executedInsn; + FieldInfo fi = getInsn.getFieldInfo(); + if (fi.getName().equals("perturbedFieldName")){ + + IntChoiceFromSet cg = ss.getCurrentChoiceGenerator("fieldReplace", IntChoiceFromSet.class); + StackFrame frame = ti.getModifiableTopFrame(); + if (cg == null){ + + // we might get here after a preceding rescheduling exec, i.e. + // partial execution (with successive re-execution), or after + // non-rescheduling exec has been completed (only one runnable thread). + // In the first case we have to restore the operand stack so that + // we can re-execute + if (!ti.willReExecuteInstruction()){ + // restore old operand stack contents + frame.pop(); + frame.push(getInsn.getLastThis()); + } + + cg = new IntChoiceFromSet("fieldReplace", 42, 43); + ss.setNextChoiceGenerator(cg); + ti.reExecuteInstruction(); + + } else { + int v = cg.getNextChoice(); + int n = frame.pop(); + frame.push(v); + } + } + } + } +~~~~~~~~ + +These examples show you that at the beginning of each transition, there is a choice value for all the cascaded `ChoiceGenerators` associated with it. If you would add `choiceGeneratorAdvanced()` notifications to your listener, you would also see that JPF processes all related choice combinations. + +If you really want to see the context, there are a number of additional methods in `SystemState` that might help you: + + * `getChoiceGenerator()` - returns only the last registered one + * `getChoiceGenerators()` - returns an array of all `ChoiceGenerators` in the current execution path + * `getLastChoiceGeneratorOfType(cgType)` - returns the last registered `ChoiceGenerator` in the path that is of the specified type + * `getCurrentChoiceGenerators()` - returns array of all cascaded `ChoiceGenerators` associated with the current transition + * `getCurrentChoiceGenerator(id)` - returns last registered `ChoiceGenerator` of cascade with specified *id* + * `getCurrentChoiceGenerator(id,cgType)` - our workhorse: last registered `ChoiceGenerator` of cascade with specified *id* and *cgType* (which can be a supertype of the actual one) + * etc. + +How does the system detect if a `ChoiceGenerator` is cascaded or not? Very simple - within `SystemState.setNextChoiceGenerator(cg)`, we just check if `SystemState` already had a registered next `ChoiceGenerator`, and if so, we set a cascaded attribute for this one. Other than that, we just maintain normal linear `ChoiceGenerator` linkage, which is accessible through `ChoiceGenerator.getPreviousChoiceGenerator()`. If you want to iterate through a cascade yourself, use the `ChoiceGenerator.getCascadedParent()` method, which returns `null` if there is none. Just be aware of that the last registered `ChoiceGenerator` (i.e. what `SystemState.getChoiceGenerator()` returns) does *not* have the cascaded attribute set (i.e. `ChoiceGenerator.isCascaded()` returns `false`). \ No newline at end of file diff --git a/docs/devel/coding_conventions.md b/docs/devel/coding_conventions.md new file mode 100644 index 0000000..fe629e9 --- /dev/null +++ b/docs/devel/coding_conventions.md @@ -0,0 +1,41 @@ +# Coding Conventions # +JPF is an open system. In order to keep the source format reasonably consistent, we strive to keep the following minimal set of conventions + + * Two space indentation (no tabs) + * Opening brackets in same line (class declaration, method declaration, control statements) + * No spaces after opening '(', or before closing ')' + * Method declaration parameters indent on column + * All files start with copyright and license information + * All public class and method declarations have preceding Javadoc comments + * We use *camelCase* instead of *underscore_names* for identifiers + * Type names are upper case + +The following code snippet illustrates these rules. + +~~~~~~~~ {.java} +/* + * + */ + +/** + * this is my class declaration example + */ + +public class MyClass { + + /** + * this is my public method example + */ + public void foo (int arg1, int arg2, + int arg3) { + if (bar) { + .. + } else { + .. + } + } + .. +} +~~~~~~~~ + +We consider modularity to be of greater importance than source format. With its new configuration scheme, there is no need to introduce dependencies of core classes towards optional extensions anymore. If you add something that is optional, and does not seamlessly fit into an existing directory, keep it separate by adding new directories. The core JPF classes should not contain any additional dependencies to external code. diff --git a/docs/devel/create_project.md b/docs/devel/create_project.md new file mode 100644 index 0000000..1eeb9b0 --- /dev/null +++ b/docs/devel/create_project.md @@ -0,0 +1,91 @@ +# Creating a New JPF Module # + +So what do you have to do to create a new JPF module? For a quick shortcut to setting up *most* things, use the `create_project` script of the [jpf-template module](wiki:projects/jpf-template). + +However, jpf-template cannot do everything for you, so see below for more information on how to finish setting up your new project. + +Several steps are involved: + +### 1. get familiar with the JPF configuration ### +You need to understand how your project will be looked up and initialized during JPF startup, and the place to learn that is the [JPF configuration](../user/config) page. Once you know what *[site properties](../install/site-properties)* and *project properties* are, you can proceed. + +### 2. get familiar with the standard JPF project layout ### +Although this is mostly convention, and you can deviate if you really need to, please try hard not to. + +You can get the details from the [JPF Runtime Modules](modules) page, but the essence is that each project has two (possible) major build artifacts: + + * `jpf-.jar` - executed by the host (platform) VM (contains main classes and peers) + * `jpf--classes.jar` - executed by JPF (contains modeled classes) + +Consequently, your sources are kept in `src/main`, `src/peers`, `src/classes`, `src/annotations`, `src/tests` and `src/examples`. You might only have some of these, but please provide regression tests so that people can check if your project works as expected. + +All 3rd party code that is required at runtime goes into a `lib` directory. + +We keep potential annotations separate (and provide additional `jpf--annotations.jar`) so that external projects (systems under test) can use them without relying on all JPF classes to be in their `classpath`. The idea is that this jar does not contain any code which could alter the system under test behavior if you execute it outside of JPF. + + + +### 3. create a jpf.properties file ### +Within the root directory of each JPF module a project properties file is needed which is named `jpf.properties`. It contains the path settings the host VM and JPF need to know about at runtime. It looks like this: + +~~~~~~~~ {.bash} +# standard header + = ${config_path} + +# classpath elements for the host VM (java) +.native_classpath = build/.jar;lib/... + +# classpath elements for JPF +.classpath = build/-classes.jar;... + +# sources JPF should know about when creating traces etc. +.sourcepath = src/classes;... +~~~~~~~~ + +You can add other JPF properties, but be aware of that this is always processed during JPF startup if you add your module to the `extensions` list in your [site.properties](../install/site-properties), and might conflict with other JPF modules. For this reason you should only add your module to `extensions` if you know it will always be used. + + +### 4. create your build.xml ### +Our build process is [Ant](http://ant.apache.org/) based, hence we need a `build.xml` file. The standard targets are + + * `clean` + * `compile` + * `build` (the default, creates the jars and hence depends on compile) + * `test` (run JUnit regression tests, depends on build) + * `dist` (creates a binary-only distribution) + +If you stick to the general layout, you can use a template like the one attached to this page (of course you need to replace ``). + +Please note how `site.properties` and `jpf.properties` can be used from within the `build.xml` (Ant understands a subset of the JPF property syntax), which means you don't have to explicitly add the jars of other JPF components you depend on (at least jpf-core). You can reference them symbolically like this: + +~~~~~~~~ {.xml} + + + .. + + + + + + ... + + + + + + + + ... +~~~~~~~~ + +### 5. add your module to your site.properties ### +This is optional, you only need to do this if you want to be able to run your JPF module outside its own directory. If so, add an entry to your [site properties file](../install/site-properties) that looks like this: + +~~~~~~~~ {.bash} +... + = +... +~~~~~~~~ + +### 6. publish your repository ### +You can publish this wherever you want ([sourceforge](http://sourceforge.net), [bitbucket](http://bitbucket.org), [google code](http://code.google.com), or [github](http://github.com) are suitable free site supporting Mercurial), or ask us to host it on the JPF server. If you decide to use a 3rd party hosting service, please let us/the JPF community know about it (e.g. by posting to the mailing list at [java-pathfinder@googlegroups.com](https://groups.google.com/forum/#!forum/java-pathfinder). \ No newline at end of file diff --git a/docs/devel/design.md b/docs/devel/design.md new file mode 100644 index 0000000..60e0fd3 --- /dev/null +++ b/docs/devel/design.md @@ -0,0 +1,52 @@ +# JPF Top-level Design # + +JPF was designed around two major abstractions: (1) the *VM*, and (2) the *Search* component. + +## Virtual Machine (VM) ## + +The VM is the state generator. By executing bytecode instructions, the VM generates state representations that can be + + * checked for equality (if a state has been visited before) + * queried (thread states, data values etc.) + * stored + * restored + +The main VM parameterizations are classes that implement the state management (matching, storing, backtracking). Most of the execution scheme is delegated to `SystemState`, which in turn uses `Scheduler` to generate scheduling sequences of interest. + +There are three key methods of the VM employed by the Search component: + + * `forward` - generate the next state, report if the generated state has a successor. If yes, store on a backtrack stack for efficient restoration. + * `backtrack` - restore the last state on the backtrack stack + * `restoreState` - restore an arbitrary state (not necessarily on the backtrack stack) + +![Figure: JPF top-level design](../graphics/jpf-abstractions.svg){align=center width=720} + +## Search Strategy ## + +At any state, the Search component is responsible for selecting the next state from which the VM should proceed, either by directing the VM to generate the next state (`forward`), or by telling it to backtrack to a previously generated one (`backtrack`). The Search component works as a driver for the VM. + +The Search component can be configured to check for certain properties by evaluating property objects (e.g. `NotDeadlockedProperty`, `NoAssertionsViolatedProperty`). + +The object encapsulating this component includes a search method which implements a strategy used to traverse the state space. The state space exploration continues until it is completely explored, or a property violation is found. + The Search component can be configured to use different strategies, such as depth-first search (`DFSearch`), and priority-queue based search that can be parameterized to do various search types based on selecting the most interesting state out of the set of all successors of a given state (`HeuristicSearch`). + +## Package Structure ## + +The implementation of the JPF core is partitioned into the following packages: + +### `gov.nasa.jpf` ### +The main responsibility of this package is configuration and instantiation of the core JPF objects, namely the Search and VM. The configuration itself is encapsulated by the `Config` class, which contains various methods to create objects or read values from a hierarchy of property files and command line options (see Configuring JPF Runtime Options). Beyond the configuration, the JPF object has little own functionality. It is mainly a convenience construct to start JPF from inside a Java application without having to bother with its complex configuration. + +### `gov.nasa.jpf.vm` ### +This package constitutes the main body of the core code, including the various constructs that implement the Java state generator. Conceptually, the major class is VM, but again this class delegates most of the work to a set of second level classes that together implement the major functionality of JPF. These classes can be roughly divided into three categories: + +(1) class management - classes are encapsulated by `ClassInfo` which mostly includes invariant information about fields and methods captured by `FieldInfo` and `MethodInfo`, respectively. + +(2) object model - all object data in JPF is stored as integer arrays encapsulated by `Fields` objects. The execution specific lock state of objects is captured by `Monitor` instances. `Fields` and `Monitor` instances together form the objects, which are stored as `ElementInfo`. The heap contains a dynamic array of `ElementInfo` objects where the array indices being used as object reference values + +(3) bytecode execution - the execution of bytecode instructions is performed through a collaboration of `SystemState` and `ThreadInfo`, which is also delegated to policy objects implementing the partial order reduction (POR). It starts with the `VM` object calling `SystemState.nextSuccessor()`, which descends into `ThreadInfo.executeStep()` (together, these two methods encapsulate the on-the-fly POR), which in turn calls `ThreadInfo.executeInstruction()` to perform the bytecode execution. +The actual execution is again delegated to bytecode specific Instruction instances that per default reside in a sub-package `gov.nasa.jpf.vm.bytecode` (the set of bytecode classes to use can be configured via a `InstructionFactory` class which allows the user to define a different execution semantics) + +### `gov.nasa.jpf.search` ### +This package is relatively small and mainly contains the `Search` class, which is an abstract base for search policies. The major method that encapsulates the policy is `Search.search()`, which is the VM driver (that calls the methods`forward`, `backtrack` and `restore`). This package also contains the plain-vanilla depth-first search policy `DFSearch`. +More policies can be found in the sub-package `gov.nasa.jpf.search.heuristic`, which uses a `HeuristicSearch` class in conjunction with configurable heuristic objects to prioritize a queue of potential successor states. diff --git a/docs/devel/eclipse_plugin_update.md b/docs/devel/eclipse_plugin_update.md new file mode 100644 index 0000000..35f663f --- /dev/null +++ b/docs/devel/eclipse_plugin_update.md @@ -0,0 +1,36 @@ +## Hosting an Eclipse plugin update site ## + +The first step is to create the local version of the update site. For example, chapter 18, section 3 of "Eclipse Plug-ins, 3rd edition" will explain how to do this. + +> **Tip:** do not attempt to put the update site in the code repository. + +The plugin and feature files are treated like binaries and bad things will happen. Here is a sample update site for the mango plugin. + +![Local Site](../graphics/localsite.jpg){align=center width=430} + +Now you will re-create this directory structure within the wiki. For the purpose of this discussion, let's pin down the jpf site: + +~~~~~~~~ {.bash} +JPFHOME=http://babelfish.arc.nasa.gov/trac/jpf +~~~~~~~~ + +Now chose a home directory, say `HOME`. For the mango plugin, + +~~~~~~~~ {.bash} +HOME=wiki/projects/jpf-mango +~~~~~~~~ + +Whatever choice of `HOME` you make, the update site you advertise to the world will be `JPFHOME/raw-attachment/HOME/update/`. + + +The `raw-attachment` segment is the *trick* that makes everything work out. The next step is to create the directory structure for the mirrored update site. Within `JPFHOME/HOME`, create a link to `JPFHOME/HOME/update`. Now go to the update page and add the attachments artifacts.jar, content.jar, and site.xml from your local update site. Create links within `JPFHOME/HOME/update` to `JPFHOME/HOME/update/features` and `JPFHOME/HOME/update/plugins`. + +Attach your feature jar to the features page, and your plugin jar to the plugins page. That's all there is to it. + +> **Tip:** when updating your update site, be sure to sync your plugin and feature with new, higher, revision numbers. Now rebuild the local site. Delete all the corresponding attachments in the wiki, and repopulate with the updated versions. + +> **Bonus tip:** Once everything is working, you can delete the link to the update site. This will prevent your visitors from accidentally going to an uninteresting page. You can always access this page directly from the browser by entering `JPFHOME/HOME/update`. + + + + diff --git a/docs/devel/embedded.md b/docs/devel/embedded.md new file mode 100644 index 0000000..0ddd1c3 --- /dev/null +++ b/docs/devel/embedded.md @@ -0,0 +1,27 @@ +# Embedded JPF # +JPF can also be used embedded, i.e. called from another Java application. A basic code sequence to start JPF looks like this: + +~~~~~~~~ {.java} +import gov.nasa.jpf.JPF; +import gov.nasa.jpf.Config; + +void runJPF (String[] args) { + .. + MyListener listener = new MyListener(..); + + // [optionally] if you pass through command line args, + // 'null' any consumed args not to be JPF-processed + listener.filterArgs( args); + .. + + Config config = JPF.createConfig( args); + // set special config key/value pairs here.. + + JPF jpf = new JPF( config); + jpf.addListener( listener); + jpf.run(); + .. +} +~~~~~~~~ + +Of course, you can also call `gov.nasa.jpf.JPF.main(args)` from within your application, if you don't need to control JPF's configuration or process it's output. diff --git a/docs/devel/index.md b/docs/devel/index.md new file mode 100644 index 0000000..8394c9c --- /dev/null +++ b/docs/devel/index.md @@ -0,0 +1,23 @@ +# JPF Developer Guide # + +From the previous two sections, you have learned that JPF has one recurring, major theme: it is not a monolithic system, but rather a configured collection of components that implement different functions like state space search strategies, report generation and much more. Being adaptive is JPF's answer to the scalability problem of software model checking. + +This not only makes JPF a suitable system for research, but chances are that if are you serious enough about JPF application, you sooner or later end up extending it. This section includes the following topics which describe the different mechanisms that can be used to extend JPF. + + * [Top-level design](design) + * Key mechanisms, such as + - [ChoiceGenerators](choicegenerator) + - [Partial order reduction](partial_order_reduction) + - [Slot and field attributes](attributes) + * Extension mechanisms, such as + - [Listeners](listener) + - [Search Strategies](design) + - [Model Java Interface (MJI)](mji) + - [Bytecode Factories](bytecode_factory) + * Common utility infrastructures, such as + - [Logging system](loggin) + - [Reporting system](report) + * [Running JPF from within your application](embedded) + * [Writing JPF tests](jpf_tests) + * [Coding conventions](coding_conventions) + * [Hosting an Eclipse plugin update site](eclipse_plugin_update) \ No newline at end of file diff --git a/docs/devel/jpf_tests.md b/docs/devel/jpf_tests.md new file mode 100644 index 0000000..a445c5a --- /dev/null +++ b/docs/devel/jpf_tests.md @@ -0,0 +1,148 @@ +# Writing JPF Tests # + +As a complex runtime system for (almost) arbitrary Java programs, it goes without saying that JPF needs a lot of regression tests. You can find these under the `src/tests` directories in (hopefully) all JPF projects. All tests follow the same scheme, which is motivated by the need to run tests in a number of different ways: + + 1. as part of the Ant-based build system, i.e. from build.xml + 1. as explicitly invoked JUnit tests + 1. by directly running JPF on the test application (i.e. without JUnit, either as a JPF `shell` or via RunTest.jar) + 1. by running the test application on a normal JVM + +The rationale for this is to support various levels of inspection and debugging. + +Each test conceptually consists of a test driver (e.g. executed under JUnit) which starts JPF from within its `@Test` annotated methods, and a class that is executed by JPF in order to check the verification goals. For convenience reasons, jpf-core provides infrastructure that enables you to implement both parts in the same class. This can be confusing at first - **the test class is used to start JPF on itself**. + +![Figure: Unit Testing in JPF](../graphics/new-testing.svg){align=center width=870} + +The `main()` method of `TestJPF` derived classes always look the same and can be safely copied between tests: + +~~~~~~~~ {.java} +public static void main(String[] testMethods){ + runTestsOfThisClass(testMethods); +} +~~~~~~~~ + +This method serves two purposes. First, it is used to start the test outside JUnit, either on all `@Test` annotated instance methods, or just on the ones which names are provided as arguments. Second, it serves as the entry point for JPF when it executes the class. In this case, `TestJPF` takes care of invoking JPF on the test class and providing the name of the test method this was executed from. + +Other than that, test classes just consist of (almost) normal `@Test` annotated JUnit test methods, which all share the same structure + +~~~~~~~~ {.java} +import org.junit.Test; + +@Test public void testX () { + if (verifyNoPropertyViolation(JPF_ARGS){ + .. code to verify by JPF + } +} +~~~~~~~~ + +The trick is the call to `verifyNoPropertyViolation()`, or any of the other `verifyXX()` methods of `TestJPF`. If executed by the host VM, i.e. from JUnit, it starts JPF on the same class and the containing method, and returns `false`. This means the corresponding `if` block is **not** executed by the host VM. + +When JPF is invoked, the argument to the main() method is set to the method name from which JPF got invoked, which causes `runTestsOfThisMethod()` to execute exactly this method again, but this time under JPF. Instead of re-executing the same `TestJPF.verifyX()` method again (and becoming infinitely recursive), we use a native peer `JPF_gov_nasa_jpf_util_test_TestJPF` which intercepts the `verifyX()` call and simply returns true, i.e. this time *only* the `if` block gets executed. + +The rest of the host VM executed `TestJPF.verifyX()` checks the results of the JPF run, and accordingly throws an `AssertionError` in case it does not correspond to the expected result. The most common goals are + + * `verifyNoPropertyViolation` - JPF is not supposed to find an error + * `verifyPropertyViolation` - JPF is supposed to find the specified property violation + * `verifyUnhandledException` - JPF is supposed to detect an unhandled exception of the specified type + * `verifyAssertionError` - same for AssertionErrors + * `verifyDeadlock` - JPF is supposed to find a deadlock + +Each of these methods actually delegate running JPF to a corresponding method whose name does not start with 'verify..'. These workhorse methods expect explicit specification of the JPF arguments (including SUT main class name and method names), but they return JPF objects, and therefore can be used for more sophisticated JPF inspection (e.g. to find out about the number of states). + +`TestJPF` also provides some convenience methods that can be used within test methods to find out which environment the code is executed from: + + * `isJPFRun()` - returns true if the code is executed under JPF + * `isJUnitRun()` - returns true if the code is executed under JUnit by the host VM + * `isRunTestRun()` - returns true if the code is executed by RunTest.jar + +Here is an example of a typical test method that uses some of these features: + +~~~~~~~~ {.java} + @Test public void testIntFieldPerturbation() { + + if (!isJPFRun()){ // run this outside of JPF + Verify.resetCounter(0); + } + + if (verifyNoPropertyViolation("+listener=.listener.Perturbator", + "+perturb.fields=data", + "+perturb.data.class=.perturb.IntOverUnder",... + "+perturb.data.delta=1")){ + // run this under JPF + System.out.println("instance field perturbation test"); + + int d = data; // this should be perturbated + System.out.println("d = " + d); + + Verify.incrementCounter(0); + + } else { // run this outside of JPF + assert Verify.getCounter(0) == 3; + } + } +~~~~~~~~ + +## Running JPF tests from command line ## +To run JPF tests from the command line, use the RunTest.jar either from `jpf-core/build`, or the one that is distributed with your project containing the tests (`tools/RunTest.jar` for JPF projects). This is an executable jar that expects the test class and (optional) method test names as arguments. If no method names are provided, all `@Test` annotated methods are executed. Most projects have a convenience script `bin/test` to execute RunTest.jar. + +~~~~~~~~ {.bash} +> bin/test gov.nasa.jpf.test.mc.data.PerturbatorTest testIntFieldPerturbation + +......................................... testing testIntFieldPerturbation + running jpf with args: +listener=.listener.Perturbator +perturb.fields=data +perturb.data.class=.perturb.IntOverUnder +perturb.data.field=gov.nasa.jpf.test.mc.data.PerturbatorTest.data +perturb.data.delta=1 gov.nasa.jpf.test.mc.data.PerturbatorTest testIntFieldPerturbation +JavaPathfinder v5.x - (C) RIACS/NASA Ames Research Center + + +====================================================== system under test +application: gov/nasa/jpf/test/mc/data/PerturbatorTest.java +arguments: testIntFieldPerturbation + +====================================================== search started: 9/10/10 7:03 PM +instance field perturbation test +d = 43 +d = 42 +... +====================================================== search finished: 9/10/10 7:03 PM +......................................... testIntFieldPerturbation: Ok + +......................................... execution of testsuite: gov.nasa.jpf.test.mc.data.PerturbatorTest SUCCEEDED +.... [1] testIntFieldPerturbation: Ok +......................................... tests: 1, failures: 0, errors: 0 +~~~~~~~~ + +## Running JPF tests under JUnit ## + +This is the preferred way to execute JPF regression tests, which is usually done from an Ant build.xml script containing a standard target such as + +~~~~~~~~ {.xml} + ... + + ... + + + + + ... + + + + + + + + + +~~~~~~~~ + +Most JPF projects have build.xml files you can use as examples. + +Please note this means that you should not have any inner classes, interfaces, annotation types etc. with a name ending with `"Test"` since JUnit would interpret these as test cases and most likely complain about missing constructors and `main()` methods. + +## Debugging tests ## + +Typically, JPF tests are only executed from within an IDE if they fail and need to be debugged. + +Under NetBeans, this can be done by selecting the test class, and then executing the *Debug File* command from the context menu. This will pop up a dialog that lets you enter a specific test method to debug. This method requires a properly set up ide-file-target.xml, which comes with most JPF projects. + +Under Eclipse, you can select the test class and then execute **Debug As..** -> **Java Application**. diff --git a/docs/devel/listener.md b/docs/devel/listener.md new file mode 100644 index 0000000..98af48c --- /dev/null +++ b/docs/devel/listener.md @@ -0,0 +1,332 @@ +# Listeners # +Listeners are perhaps the most important extension mechanism of JPF. They provide a way to observe, interact with and extend JPF execution with your own classes. Since listeners are dynamically configured at runtime, they do not require any modification to the JPF core. Listeners are executed at the same level like JPF, so there is hardly any limit of what you can do with them. + +![Figure 1: JPF Listeners](../graphics/listener-overview.svg){align=center width=800} + +The general principle is simple: JPF provides an observer pattern implementation that notifies registered observer instances about certain events at the search level and the VM level. These notifications cover a broad spectrum of JPF operations, from low level events like `instructionExecuted` to high level events like `searchFinished`. Each notification is parameterized with the corresponding source (either the `Search` or the `VM` instance), which can be then used by the notified listener to obtain more information about the event and the JPF's internal state. + +Configuration is usually done with the `listener` property, either from the command line, or a .jpf property file. Listeners can also be associated with annotations, to be automatically loaded whenever JPF encounters such an annotation. Applications can use the `@JPFConfig` annotation to explicitly specify JPF listeners. Lastly, if JPF is used in an embedded mode, listeners can be registered with an API. + + +## Listener Types ## + + +There are two basic listener interfaces, depending on corresponding event sources: `SearchListeners` and `VMListeners`. Since these interfaces are quite large, and listeners often need to implement both, we also provide "adapter" classes, i.e. implementors that contain all required method definitions with empty method bodies. Concrete listeners that extend these adapters therefore only have to override the notification methods they are interested in. + +The adapter classes are used for the majority of listener implementations, especially since they also support two other interfaces/extension mechanisms that are often used in conjunction with `Search` and `VMListeners`: + + 1. `Property` - to define program properties + 2. `PublisherExtension` - to produce output within [the JPF reporting system](report) + +`ListenerAdapter` is the bare adapter implementation for `SearchListener`, `VMListener` and `PublisherExtension`. This is what is mostly used to collect information during JPF execution (e.g. `CoverageAnalyzer` and `DeadlockAnalyzer`). + +`PropertyListenerAdapter` is used in case the listener implements a program property, i.e. it can terminate the search process. A prominent example of this category is `PreciseRaceDetector`. + +![Figure 2: Listener Types](../graphics/listeners.svg){align=center width=800} + +Choosing the right type for your listener is important, since JPF automatically registers listeners (and properties) based on this type. You can bypass and directly implement single listener interfaces, but then you also have to do the proper registrations. + +Usually, the notification alone is not enough, and the listener needs to acquire more information from JPF. For this purpose, we provide either the `Search` or the `VM` instance as notification arguments, and the listener has to use these as "Facades" to query or interact JPF. It therefore matters to implement the listener within the right package. + + +## SearchListener ## + + +`SearchListener` instances are used to monitor the state space search process, e.g. to create graphical representations of the state-graph. They provide notification methods for all major Search actions. + +~~~~~~~~ {.java} +package gov.nasa.jpf.search; +public interface SearchListener extends JPFListener { + void searchStarted (Search search); + void stateAdvanced (Search search); // got next state + void stateProcessed (Search search); // state is fully explored + void stateBacktracked (Search search); // state was backtracked one step (same path) + void stateStored (Search search); // somebody stored the state + void stateRestored (Search search); // previously generated state was restored (any path) + void propertyViolated (Search search); // JPF encountered a property violation + void searchConstraintHit (Search search); // e.g. max search depth + void searchFinished (Search search); +}} +~~~~~~~~ + + +For the standard depth first search (`gov.nasa.jpf.search.DFSearch`), listener implementations can assume the following notification model: + + +![Figure 3: Depth first listener notifications](../graphics/DFSListener.svg){align=center width=500} + +The most frequently used notifications are: + +`stateAdvanced` - to store additional, backtrackable state information in an associative array + +`stateBacktracked` - to restore additional state information + +`searchFinished` - to process listener results + + +## VMListener ## + + +This is a fat interface, reflecting various VM operations + +~~~~~~~~ {.java} +package gov.nasa.jpf.jvm; +public interface VMListener extends JPFListener { + //--- basic bytecode execution + void executeInstruction (JVM vm); // JVM is about to execute the next instruction + void instructionExecuted (JVM vm); // JVM has executed an instruction + + //--- thread operations (scheduling) + void threadStarted (JVM vm); // new Thread entered run() + void threadBlocked (JVM vm); // thread waits to acquire a lock + void threadWaiting (JVM vm); // thread is waiting for signal + void threadNotified (JVM vm); // thread got notified + void threadInterrupted (JVM vm); // thread got interrupted + void threadTerminated (JVM vm); // Thread exited run() + void threadScheduled (JVM vm); // new thread was scheduled by JVM + + //--- class management + void classLoaded (JVM vm); // new class was loaded + + //--- object operations + void objectCreated (JVM vm); // new object was created + void objectReleased (JVM vm); // object was garbage collected + void objectLocked (JVM vm); // object lock acquired + void objectUnlocked (JVM vm); // object lock released + void objectWait (JVM vm); // somebody waits for object lock + void objectNotify (JVM vm); // notify single waiter for object lock + void objectNotifyAll (JVM vm); // notify all waiters for object lock + + void gcBegin (JVM vm); // start garbage collection + void gcEnd (JVM vm); // garbage collection finished + + void exceptionThrown (JVM vm); // exception was thrown + + //--- ChoiceGenerator operations + void choiceGeneratorSet (JVM vm); // new ChoiceGenerator registered + void choiceGeneratorAdvanced (JVM vm); // new choice from current ChoiceGenerator + void choiceGeneratorProcessed (JVM vm); // current ChoiceGenerator processed all choices +} +~~~~~~~~ + + +The most commonly used methods are the instruction notifications: + +`executeInstruction` - is called before a bytecode instruction gets executed by the VM. The listener can even use this to skip and/or replace this instruction, which is useful for non-invasive instrumentation. + +`instructionExecuted` - is the post-execution notification, which is suitable to keep track of execution results (method invocations, assigned field values, branch results etc.) + + +## Example ## + +The following example is a slightly abbreviated form our race detector. The basic idea is simple: every time we encounter a new scheduling point (i.e. new `ThreadChoiceGenerator` object) that is due to a field access on a shared object, we check if any of the other runnable threads is currently accessing the same field on the same object. If at least one operation is a `putfield`, we have a potential race. + +The example shows three aspects that are quite typical: + + 1. listeners often use only a small number of notification methods + + 2. they often do not require a huge amount of code (most expensive operations are performed by the `VM` and the `Search` objects) + + 3. sometimes you have to dig deep into JPF internal constructs, to extract things like `ThreadInfo`, `FieldInfo` and `ChoiceGenerator` instances + +~~~~~~~~ {.java} +public class PreciseRaceDetector extends PropertyListenerAdapter { + FieldInfo raceField; + ... + //--- the Property part + public boolean check(Search search, JVM vm) { + return (raceField == null); + } + + //--- the VMListener part + public void choiceGeneratorSet(JVM vm) { + ChoiceGenerator cg = vm.getLastChoiceGenerator(); + + if (cg instanceof ThreadChoiceFromSet) { + ThreadInfo[] threads = ((ThreadChoiceFromSet)cg).getAllThreadChoices(); + ElementInfo[eiCandidates = new ElementInfo[threads.length](]); + FieldInfo[fiCandidates = new FieldInfo[threads.length](]); + + for (int i=0; i= 0){ // yes, we have multiple accesses on the same object/field + Instruction otherInsn = threads[idx].getPC(); + if (isPutInsn(otherInsn) || isPutInsn(insn)) { + raceField = ((FieldInstruction)insn).getFieldInfo(); + .. + return; + } + } else { + eiCandidates[i] = ei; + fiCandidates[i] = fi; + } + } + } + } + } + } + + public void executeInstruction (JVM jvm) { + if (raceField != null) { // we're done, report as quickly as possible + ThreadInfo ti = jvm.getLastThreadInfo(); + ti.breakTransition(); + } + } +} +~~~~~~~~ + +## Instantiation ## + +Explicit instantiation of a listener (e.g. from a JPF shell) can be done in any way. If the listener is specified as a JPF property, it's class either needs to have a default constructor, or a constructor that takes a single `gov.nasa.jpf.Config` argument. The `Config` object that is passed into this constructor by JPF is the same that was used for the initialization of JPF itself. This is the preferred method if the listener has to be parameterized. In case of the `PreciseRaceDetector` example, this can be used to filter relevant fields with regular expressions: + +~~~~~~~~ {.java} +public class PreciseRaceDetector extends PropertyListenerAdapter { + ... + StringSetMatcher includes = null; + StringSetMatcher excludes = null; + + public PreciseRaceDetector (Config conf) { + includes = StringSetMatcher.getNonEmpty(conf.getStringArray("race.include")); + excludes = StringSetMatcher.getNonEmpty(conf.getStringArray("race.exclude")); + } + ... + public void choiceGeneratorSet(JVM vm) { + ... + FieldInfo fi =.. + if (StringSetMatcher.isMatch(fi.getFullName(), includes, excludes)) + ... + } +~~~~~~~~ + + +## Configuration ## + +Listener configuration can be done in a number of ways: via JPF properties from the command line or a .jpf file, via JPF APIs from a JPF shell (a program invoking JPF), or from the system under test by using Java annotations (i.e. without code modification). + +Since listeners are executed by the host VM, they have to be in the `CLASSPATH` (`jpf-core.native_classpath` property). + + +### command line ### + + +the *listener* property can be used to specify a colon separated list of listener class names: + +~~~~~~~~ {.bash} +bin/jpf ... +listener=x.y.MyFirstListener,x.z.MySecondListener ... +~~~~~~~~ + + +### .jpf property file ### + + +If you have several listeners and/or a number of other JPF options, it is more convenient to add the `listener` property to a .jpf file: + +~~~~~~~~ {.bash} +# Racer-listener.jpf - JPF mode property file to detect data races in jpftest.Racer +target = jpftest.Racer +listener=gov.nasa.jpf.tools.PreciseRaceDetector +~~~~~~~~ + + +### Autoload Annotations ### + + +Consider your system under test is marked up with a Java annotation that represent properties. For example, you can use the `@NonNull` annotation to express that a method is not allowed to return a `null` value: + +~~~~~~~~ {.java} +import gov.nasa.jpf.NonNull; + ... + @NonNull X computeX (..) { + //.. some complex computation + } + ... +~~~~~~~~ + +You can use .jpf property files (or the command line, if you love to type) to tell JPF that it should automatically load and register a corresponding listener (e.g. `NonNullChecker`) if it encounters such a `@NonNull` annotation during class loading: + +~~~~~~~~ {.bash} +.. +listener.autoload = gov.nasa.jpf.NonNull,... +listener.gov.nasa.jpf.NonNull = gov.nasa.jpf.tools.NonNullChecker +... +~~~~~~~~ + + +### @JPFConfig annotation (SuT) ### + + +You can also explicitly direct JPF to load the listener from within your application by using the `@JPFConfig` annotation: + +~~~~~~~~ {.java} +import gov.nasa.jpf.JPFConfig; +.. +// set JPF properties via properties at class load time +@JPFConfig ({"listener+=.tools.SharedChecker", ..}) +public class TestNonShared implements Runnable { + ... +} +~~~~~~~~ + +However, this is not recommended outside JPF tests - the application would run, but not compile without JPF. + + +### Verify API (SuT) ### + + +A less often used method is to set listeners is to use the `gov.nasa.jpf.vm.Verify` API from within your application. With this, you can control the exact load time of the listener (but be aware of backtracking). With this, the above example would become + +~~~~~~~~ {.java} +import gov.nasa.jpf.vm.Verify; +.. +public class TestNonShared implements Runnable { + ... + public static void main (String[] args){ + + // set JPF properties programmatically + Verify.setProperties("listener+=.tools.SharedChecker", ...); + .. + } +} +~~~~~~~~ + +This method should only be used in special cases (models written explicitly for JPF verification), since it does not run outside JPF. + + +### JPF API (embedded mode) ### + + +If JPF is explicitly started from within another application, listeners can be instantiated at will and configured via the `JPF.addListener(..)` API: + +~~~~~~~~ {.java} +MyListener listener=new MyListener(..); +.. +Config config = JPF.createConfig( args); +JPF jpf = new JPF( config); +jpf.addListener(listener); +jpf.run(); +.. +~~~~~~~~ + +Most listeners tend to fall into three major categories: + +1. system class (e.g. for logging) - is usually configured via the default.properties. +2. complex properties - is configured with an application specific mode property file. +3. JPF debugging - is specified via the command line (`+key=value` overrides). diff --git a/docs/devel/logging.md b/docs/devel/logging.md new file mode 100644 index 0000000..3993fdf --- /dev/null +++ b/docs/devel/logging.md @@ -0,0 +1,31 @@ +# The JPF Logging API # +There is one simple rule: do not use `System.out` or `System.err` for any permanent logging + + +Of course we all do this temporarily during debugging, but it really shouldn't stay in the code. The logging infrastructure is quite easy to use. Just declare a static `Logger` instance with an appropriate id (either package or logging topic) at the top of your class, and then use the `Logger` API to create output: + +~~~~~~~~ {.java} +... +import java.util.logging.Level; +import java.util.logging.Logger; + +package x.y.z; + +class MyClass .. { + static Logger log = JPF.getLogger("x.y.z"); + ... + log.severe("there was an error"); + ... + log.warning("there was a problem"); + ... + log.info("something FYI"); + ... + if (log.isLoggable(Level.FINE)){ // (1) don't create garbage + log.fine("this is some detailed info about: " + something); + } + ... +} +~~~~~~~~ + +Note that there is only one instance for each `Logger` ID, i.e. you can have a corresponding static field in all your relevant classes, and don't have to share the fields. Another aspect that is mostly important for the lower log levels (e.g. `FINE`) is that you should't concatenate log messages in operations that occur frequently, since the corresponding `StringBuilder` instances can cause performance degradations even if the log level is not set (the arguments still get evaluated). In this case, encapsulate the logging in `log.isLoggable(level){..}` blocks. + diff --git a/docs/devel/mercurial.md b/docs/devel/mercurial.md new file mode 100644 index 0000000..b1b3051 --- /dev/null +++ b/docs/devel/mercurial.md @@ -0,0 +1,56 @@ +# Mercurial in 5 Minutes # + +[Mercurial](http://www.selenic.com/mercurial) is a *distributed version control system* (DVCS) of the same category such as the likes of [Git](http://git-scm.com/) or [Bazaar](http://bazaar.canonical.com/en/). If you know nothing else about DVCS, this means mostly one thing - **all repositories are created equal**. There is no such thing as a different repository format for public and private repositories. All repositories (that are synchronized) have the same, stored history information. + +Yes, this means you can finally synchronize your working repos with more than one "master" repository, e.g. with several local ones, closed workgroup repos, and a public master repo (that just happens to be designated as such). + +Each Mercurial repository consists of an (optional) working copy of your files, and a `.hg` directory in your repo root dir that holds all the version control info. Be careful not to delete the `.hg` dir, otherwise your repo is reduced to just a snapshot of your current working files. + +A central concept of DVCS is the *change set* - think of it as the diff of all files that have been changed when you do a commit. This is what DVCS store (e.g. Mercurial in the `.hg` dir) and compare between different repositories. One implication of this is that you can't do partial commits like in CVS or SVN (e.g. by just committing changes within a certain subdirectory). You always have to execute the Mercurial commands in the top dir of the repository you are working in. + +If you have previously worked with CVS or SVN, another difference you have to wrap your head around is that there are commands that work locally, and commands that interact with the remote repo. __The `commit` and `update` commands are only local__. The `push` and `pull` commands synchronize your local repo with an external one (like commit and update did in CVS/SVN). + +Here are the main commands to interact with Mercurial: + +![](mercurial.png) + +**hg clone ** - this is the first command that clones an external repository (either from `file:///...` or `http://...` URLs). It creates both a working copy and the `.hg` directory (with contents) + +**hg init** - is what you do if you create a local repository for which there is no external one yet. Just create your files, `cd` into the top directory, and execute the command (which will create the `.hg` for you) + +**hg pull [-u] ** - updates the repo you are currently in from the provided URL. Note that your working copy is only updated if you use the `-u` option + +**hg incoming ** - is the little brother of `pull`. It just tells you if there are changesets in the remote repository you would pull + +**hg status** - tells you if there are uncommitted changes in your working copy that have to be committed to the local `.hg` directory before you can `push` or `pull` + +**hg diff** - does a bit more, it also shows you a diff file with the uncommitted changes + +**hg add ** - adds a file to the repo + +**hg remove ** - removes a file from the repo + +**hg addremove** - adds all new files of the working copy that are not in the repository yet, and removes all which are not in the working copy anymore + +**hg commit** - saves changes in your working copy to your local `.hg`. Do this early and often, this is now just a local operation that doesn't change anything outside the repo you are working with + +**hg update** - would update your working copy from your local `.hg`. It is rarely used if you pull with the `-u` option + +**hg push ** - pushes the relevant changesets of your local `.hg` back to the external repo with the provided URL. Make sure you have no uncommitted changes (Mercurial would refuse to push), and - in case the external repo is shared - that you pulled/merged all changesets of the external repo before you push + +**hg outgoing ** - is the dry run version of a push, it tells you if there are changesets that would have to be pushed + +**hg revert** - reverts your working copy to a previous version stored in your local `.hg` + +**hg heads** - tells you if there are branches in your repo, which usually happens if you pull from a changed external repo while having un-pushed local changes that are committed + +**hg merge** - gets rid of multiple heads. Make sure to get rid of these by merging as soon as you detect them, it only gets more difficult with more external and local changes. Once there are collisions, you are back to the CVS/SVN merge mess + +You can always obtain more information by executing +~~~~~~~~ +#!sh +> hg help [command] +~~~~~~~~ +If you don't list a command, all available ones will be displayed. + +Commands that refer to external repos take URLs such as `http://babelfish.arc.nasa.gov/hg/jpf/jpf-core` as arguments. diff --git a/docs/devel/mji.md b/docs/devel/mji.md new file mode 100644 index 0000000..817cdd1 --- /dev/null +++ b/docs/devel/mji.md @@ -0,0 +1,214 @@ +# Model Java Interface (MJI) # +## Purpose ## + +Even if it is just a Java application (i.e. solely consists of Java classes), JPF can be viewed as a Java Virtual Machine (JVM) in itself. The consequence is that (*.class) class files, and even the same files at times, are processed in two different ways in a JVM running JPF + + * as ordinary Java classes managed and executed by the host JVM (standard Java library classes, JPF implementation classes) + * as "modeled" classes managed and processed (verified) by JPF + +Class lookup in both layers is based on the CLASSPATH environment variable / command line parameter, but this should not obfuscate the fact that we have to clearly distinguish between these two modes. In particular, JPF (i.e. the "Model" layer) has its own class and object model, which is completely different and incompatible to the (hidden) class and object models of the underlying host JVM executing JPF + +![Figure 1: JPF Layers](../graphics/jpf-layers.svg){align=center width=560} + +Each standard JVM supports a so called Java Native Interface (JNI), that is used to delegate execution from the Java level (i.e. JVM controlled bytecode) down into the (platform dependent) native layer (machine code). This is normally used to interface certain functionalities to the platform OS / architecture (e.g. I/O or graphics). + +Interestingly enough, there exists a analogous need to lower the "execution" level in JPF, from JPF controlled bytecode into JVM controlled bytecode. According to this analogy, the JPF specific interface is called Model Java interface (MJI). + +Even though MJI offers a wide range of applications, there are three major usages for delegating bytecode execution into the host JVM: + + 1. Interception of native methods - without a abstraction lowering mechanism, JPF would be forced to completely ignore native methods, i.e. would fail on applications relying on the side effects of such methods, which is not acceptable (even if many native methods indeed can be ignored if we restrict the set of verification targets) + + 2. Interfacing of JPF system level functionality - some system level functions of standard library classes (esp. java.lang.Class, java.lang.Thread) have to be intercepted even if they are not native because they have to affect the JPF internal class, object and thread model (etc. loading classes, creating / starting threads). It should be noted that MJI can also be used to extend the functionality of JPF without changing its implementation. + +3. State space reduction - by delegating bytecode execution into the non-state-tracked host JVM, we can cut off large parts of the state space, provided that we know the corresponding method side effects are not relevant for property verification (e.g. `System.out.println(..)`) + +Besides these standard usages, there exist more exotic applications like collecting information about JPF state space exploration and making it available both to JPF and the verification target. + + +## MJI Components ## + + +The basic functionality of MJI consists of a mechanism to intercept method invocations, and delegate them by means of Java reflection calls to dedicated classes. There are two types of classes involved, residing at different layers: + + * Model Classes - these classes execute by the VM of JPF, which might be completely unknown to the host JVM + * Native Peers - these classes, implemented by `NativePeer` subclasses, contain the implementations of the methods to intercept, and to execute by the host JVM + +As part of the JPF implementation, MJI automatically takes care of determining which method invocations have to be intercepted by looking up the corresponding native peer methods + +![Figure 2: MJI Functions](../graphics/mji-functions.svg){align=center width=600} + +This would not be very useful without being able to access the JPF object model (or other JPF intrinsics), from inside the native peer methods. Instead of requiring all native peers implementation to reside in a JPF internal package, there exists an interface class `MJIEnv` that provide access to the JPF internal structure in a controlled way. `NativePeer` classes residing in `gov.nasa.jpf.vm` (i.e. the same package as `MJIEnv`) can reach all internal JPF features. Outside this package, the available API in `MJIEnv` is mostly restricted to the access JPF object (getting and setting values). + +![Figure 3: MJI Call Sequence](../graphics/mji-call.svg){align=center width=580} + +Before a native peer method can be used, JPF has to establish the correspondence between the model class and the native peer. This takes place at load time of the model class. MJI uses a special name mangling scheme to lookup native peers, using the model class package name and class name to deduce the native peer class name. + +![Figure 3: MJI name mangling](../graphics/mji-mangling.svg){align=center width=560} + +Since the model class package is encoded in the native peer name, the package of the native peer can be chosen freely. In analogy to JNI, native peers methods names include the signature of the model method by encoding its parameter types. If there is no potential ambiguity, i.e. mapping from native peer methods to model class methods is unique, signature encoding is not required. + +Each native peer, which is an instance of a `NativePeer` subclass, is associated with exactly one `ClassInfo` instance. +All the native peer methods to be intercepted have to be `public` and annotated with `gov.nasa.jpf.annotation.MJI`. +Moreover, MJI requires them to have two parameters: + + * An instance of `MJIEnv` which can be used to access JPF internal constructs + * An integer which is a handle for the corresponding JPF `this` object (or the `java.lang.Class` object in case of a static method) including the method to be intercepted + +See [Mangling for MJI](mji/mangling) for more details and examples of mangling. + +Going beyond the JNI analogy, MJI can also be used to intercept + + * non-native methods (i.e. the lookup process is driven by the methods found in the native peer, not the `native` attributes in the model class. This can be particularly useful in case the class is used from both as a model class and a JVM class (e.g. `gov.nasa.jpf.vm.Verify`), using a method body that directly refers to the native peer + * class initialization (the corresponding native peer method has to be named `$clinit(MJIEnv env, int clsRef)`) + * constructors (the corresponding native peer method has to be named `$init__(MJIEnv env,int objRef, )` and the normal signature mangling rules apply) + + +It is important to note that type correspondence does NOT include references. All references (object types) on the JPF side are transformed in handles (int values) on the JVM side. The passed in `MJIEnv` parameter has to be used to convert/analyze the JPF object. Since MJI per default uses the standard Java reflection call mechanism, there is a significant speed penalty (lookup, parameter conversion etc.), which again is a analogy to JNI. + +Even if it is not directly related to MJI, it should be mentioned that some JPF specific model classes cannot be loaded via the CLASSPATH (e.g. `java.lang.Class`), since they contain JPF based code that is not compatible with the host JVM (e.g. relying on native methods that refer to JPF functionality). Such classes should be kept in separate directories / jars that are specified with the JPF command line option `-jpf-bootclasspath` or `-jpf-classpath`. This is mostly the case for system classes. On the other hand, model classes don't have to be JPF specific. It is perfectly fine to provide a native peer for a standard Java class (e.g. `java.lang.Character`), if only certain methods from that standard class needs to be intercepted. Native peers can contain any number of non-"native" methods and fields, but those should not be annotated with `@MJI` to avoid lookup problems. + +## Tools ## + +To ease the tedious process of manually mangle method names, MJI includes a tool to automatically create skeletons of native peers from a given Model class, called `GenPeer`. The translation process uses Java reflection, i.e. the model class needs to be in the CLASSPATH and is specified in normal dot notation (i.e. not as a file). + +![Figure 4: The GenPeer tool](../graphics/genpeer.svg){align=center width=470} + +There exist a number of command line options that can be displayed by calling `GenPeer` without arguments. `GenPeer` per default writes to stdout, i.e. the output has to be redirected into a file. + +Since method invocation by reflection used to be a slow operation, we previously also had a tool called `GenPeerDispatcher`, which used method signature hash-codes to explicitly dispatch native peer methods. With recent improvements in JVM performance, this tool became obsolete. + + +## Example ## + + +The following example is an excerpt of a JPF regression test, showing how to intercept various different method types, and using `MJIEnv` to access JPF objects. + + +### Model class (JPF side) ### + + +This is executed by JPF, which means it needs to be in JPF's `vm.classpath` setting. + +~~~~~~~~ {.java} +public class TestNativePeer { + static int sdata; + + static { + // only here to be intercepted + } + + int idata; + + TestNativePeer (int data) { + // only here to be intercepted + + } + + public void testClInit () { + if (sdata != 42) { + throw new RuntimeException("native 'clinit' failed"); + } + } + + public void testInit () { + TestNativePeer t = new TestNativePeer(42); + + if (t.idata != 42) { + throw new RuntimeException("native 'init' failed"); + } + } + + native int nativeInstanceMethod (double d, char c, boolean b, int i); + + public void testNativeInstanceMethod () { + + int res = nativeInstanceMethod(2.0, '?', true, 40); + if (res != 42) { + throw new RuntimeException("native instance method failed"); + } + } + + native long nativeStaticMethod (long l, String s); + + public void testNativeStaticMethod () { + long res = nativeStaticMethod(40, "Blah"); + + if (res != 42) { + throw new RuntimeException("native instance method failed"); + + } + } + + native void nativeException (); + + public void testNativeException () { + try { + nativeException(); + } catch (UnsupportedOperationException ux) { + String details = ux.getMessage(); + + if ("caught me".equals(details)) { + return; + } else { + throw new RuntimeException("wrong native exception details: " + + details); + } + } catch (Throwable t) { + throw new RuntimeException("wrong native exception type: " + + t.getClass()); + } + + throw new RuntimeException("no native exception thrown"); + } + } +~~~~~~~~ + + +### Native Peer class (host VM side) ### + + +This is executed by the host VM (i.e. at the same level like JPF itself), so make sure it is in your CLASSPATH. + +~~~~~~~~ {.java} +public class JPF_gov_nasa_jpf_vm_TestNativePeer { + + @MJI + public static void $clinit (MJIEnv env, int rcls) { + env.setStaticIntField(rcls, "sdata", 42); + } + + @MJI + public static void $init__I (MJIEnv env, int robj, int i) { + env.setIntField(robj, "idata", i); + } + + // preferably use full signature mangling + @MJI + public static int nativeInstanceMethod__DCZI__I (MJIEnv env, int robj, + double d, char c, + boolean b, int i) { + if ((d ## 2.0) && (c ## '?') && b) { + return i + 2; + } + return 0; + } + + //..but it also works without, if there is no overloading (don't be lazy!) + @MJI + public static long nativeStaticMethod (MJIEnv env, int rcls, + long l, int stringRef) { + String s = env.getStringObject(stringRef); + if ("Blah".equals(s)) { + return l + 2; + } + return 0; + } + + @MJI + public static void nativeException____V (MJIEnv env, int robj) { + env.throwException("java.lang.UnsupportedOperationException", + "caught me"); + } + } +~~~~~~~~ + diff --git a/docs/devel/mji/mangling.md b/docs/devel/mji/mangling.md new file mode 100644 index 0000000..5e2847a --- /dev/null +++ b/docs/devel/mji/mangling.md @@ -0,0 +1,200 @@ +# Mangling for MJI # +## Mangling Methods ## +Suppose your method looks like + +~~~~~~~~ {.java} +T1 foo(T2 x, T3 y, ...) +~~~~~~~~ + +where the `Ti` are Java types. + +If `T1` is a primitive type or `void`, then the mangled MJI method looks +like + +~~~~~~~~ {.java} +public static T1 foo__MT2MT3...__MT1(...) +~~~~~~~~ + +where the `MTi` are the mangled versions of the `Ti`. +Mangling of types is described in the Mangling Types section below. +Note that `T1` appears twice, once not mangled (`T1`) and once mangled +(`MT1`). The `__` is two consecutive underscores: `_` followed by +`_`. + +As a not-so-special case, if `foo` has no arguments, then the mangled method +will have four consecutive underscores: + +~~~~~~~~ {.java} + `T1 foo()`[[br]] +~~~~~~~~ + +goes to + +~~~~~~~~ {.java} + `public static T1 foo____MT1(...)` +~~~~~~~~ + +If `T1` is not a primitive type, then the mangled `MJI` method looks like + +~~~~~~~~ {.java} + `public static int foo__MT2MT3...__MT1` +~~~~~~~~ + +where the `MTi` are as above. Note that `T1` only appears once in this +case. The method's return type is `int`. As before, a method with no +arguments gets mangled to something with four consecutive underscores. + +Also, the use of generics is ignored when mangling names. + + +## Mangling Constructors ## +Constructors are treated as methods named `$init` with return type `void`. + + +## Mangling Static Initializers ## +Static initializers are treated as methods named `$clinit` with no +arguments and return type `void`. Thus, their MJI versions always +have the mangled signature: + +~~~~~~~~ {.java} +public static void $clinit____V (MJIEnv env, int clsObjRef) +~~~~~~~~ + +or the equivalent unmangled signature: + +~~~~~~~~ {.java} +public static void $clinit (MJIEnv env, int clsObjRef) +~~~~~~~~ + + +## Mangling Types ## + - Convert primitives and `void` as follows + + |Java Type|Mangled Type| + | ------- |:---:| + |`boolean`|`Z`| + |`byte` |`B`| + |`char` |`C`| + |`short` |`S`| + |`int` |`I`| + |`long` |`J`| + |`float` |`F`| + |`double` |`D`| + |`void` |`V`| + + - Convert a non-array reference type `T` in package `x.y` + (e.g. `java.lang.String`) as follows + - `x.y.T` --> `Lx_y_T_2` + - Example: `java.lang.String` --> `Ljava_lang_String_2` + + - Convert an array of primitive type `T` + (e.g. `byte[]`) as follows: + - `T[]` --> `_3MT` where `MT` is the mangled version of `T` + (e.g. for `T=byte`, `MT=B`) + - Example: `byte[]` --> `_3B` + + - Convert an array of reference type `T` in package `x.y` + (e.g. `java.lang.String[]`) as follows: + - `x.y.T[]` --> `_3Lx_y_T_2` + - Example: `java.lang.String[]` --> `_3Ljava_lang_String_2` + + +## Method Examples ## + + `void` return type, single primitive argument: + +~~~~~~~~ {.java} + public static void resetCounter(int id) +--> + public static final void resetCounter__I__V(MJIEnv env, int objref, int id) +~~~~~~~~ + + Primitive return type, no arguments: + +~~~~~~~~ {.java} + public native boolean isArray() +--> + public static boolean isArray____Z(MJIEnv env, int objref) +~~~~~~~~ + + Primitive return type, single primitive argument: + +~~~~~~~~ {.java} + public static double abs(double a) +--> + public static double abs__D__D(MJIEnv env, int clsObjRef, double a) +~~~~~~~~ + + Primitive return type, two primitive arguments: + +~~~~~~~~ {.java} + public static long min(long a, long b) +--> + public static long min__JJ__J(MJIEnv env, int clsObjRef, long a, long b) +~~~~~~~~ + + + `void` return type, arguments include an array of a primitive type: + +~~~~~~~~ {.java} + public native void write (byte[] buf, int off, int len); +--> + public static void write___3BII__V(MJIEnv env, int objref, + int bufRef, int off, int len) +~~~~~~~~ + + + `void` return type, argument is an array of a reference type: + +~~~~~~~~ {.java} + public static void print(String s) +--> + public static void print___3Ljava_lang_String_2__V(MJIEnv env, int clsRef, int argsRef) +~~~~~~~~ + + Array of reference types returned, no arguments: + +~~~~~~~~ {.java} + public native Annotation[] getAnnotations() +--> + public static int getAnnotations_____3Ljava_lang_annotation_Annotation_2(MJIEnv env, int robj) +~~~~~~~~ + Notice there are 5 underscores before the `3L`: two marking the + arguments, two marking the return type, and one from the `_3` + signalling an array. + + Array of reference types using generics returned, no arguments: + +~~~~~~~~ {.java} + public native Class[] getParameterTypes() +--> + public static int getParameterTypes_____3Ljava_lang_Class_2(MJIEnv env, int objref) +~~~~~~~~ + +Note: the use of generics is ignored in the mangling. + + + +## Constructor Examples ## + +Constructors are treated as though they were methods named `$init` +returning `void`, so the method examples above should also be helpful +for constructors. Here are a few more examples. + +In the class `ConsoleOutputStream`: + +~~~~~~~~ {.java} + public ConsoleOutputStream() +--> + public static void $init____V(MJIEnv env, int objref) +~~~~~~~~ + +In the class `AtomicLongFieldUpdater`: + +~~~~~~~~ {.java} + protected AtomicLongFieldUpdater(Class objClass, String fieldName) +--> + public static void $init__Ljava_lang_Class_2Ljava_lang_String_2__V + (MJIEnv env, int objRef, + int tClsObjRef, int fNameRef) +~~~~~~~~ diff --git a/docs/devel/modules.md b/docs/devel/modules.md new file mode 100644 index 0000000..45e84d7 --- /dev/null +++ b/docs/devel/modules.md @@ -0,0 +1,21 @@ +# JPF Runtime Modules # + +JPF is partitioned into separate projects that all follow the same directory layout and build process. Modules can be distributed as source or binary distributions. Binary distributions are just slices through the directory tree of a source distribution that preserve the permanent build artifact, i.e. both distribution forms are runtime-compatible. + +![Figure: JPF Modules](../graphics/jpf-project.svg){align=center width=750} + +The main artifacts are the *.jar files created and stored in the `build` directory. We can divide this into classes that are executed by the host VM (i.e. have to be in JPF's `native_classpath` setting), and classes that are executed by JPF itself (i.e. have to be in JPF's `classpath` setting). The first category includes [listeners](listener) and [native peers](mji), the second one model classes (compiled from `src/classes`) and annotations, i.e. the system under test code. + +The build process is [Ant](http://ant.apache.org/) based, which means every source distribution comes with a build.xml script that implements the basic build targets `clean`, `compile`, `build` and `test`. + +We do not include required 3rd party runtime and build libraries in the project distributions. +The `compile` Ant target uses the standard `javac` command which requires a full JDK installation. `test` generally executes a JUnit based regression test suite. Both JUnit and Ant libraries are also need to be installed. + + + + + + + +For convenience reasons, JPF modules come with corresponding NetBeans and Eclipse configurations, i.e. can be directly opened as projects within these IDEs. + diff --git a/docs/devel/partial_order_reduction.md b/docs/devel/partial_order_reduction.md new file mode 100644 index 0000000..7077a48 --- /dev/null +++ b/docs/devel/partial_order_reduction.md @@ -0,0 +1,67 @@ +# On-the-fly Partial Order Reduction # + +The number of different scheduling combinations is the prevalent factor for the state space size of concurrent programs. Fortunately, for most practical purposes it is not necessary to explore all possible instruction interleavings for all threads. The number of scheduling induced states can be significantly reduced by grouping all instruction sequences in a thread that cannot have effects outside this thread itself, collapsing them into a single transition. This technique is called partial order reduction (POR), and typically results in more than 70% reduction of state spaces. + +JPF employs an on-the-fly POR that does not rely on user instrumentation or static analysis. JPF automatically determines at runtime which instructions have to be treated as state transition boundaries. If POR is enabled (configured via `vm.por` property), a forward request to the VM executes all instructions in the current thread until one of the following conditions is met: + + - the next instruction is scheduling relevant + - the next instruction yields a "nondeterministic" result (i.e. simulates random value data acquisition) + +Detection of both conditions are delegated to the instruction object itself (`Instruction.execute()`), passing down information about the current VM execution state and threading context. If the instruction is a transition breaker, it creates a ChoiceGenerator and schedules itself for re-execution. + +~~~~~~~~ {.java} +executeStep () { + .. + do { + if ((nextPc # executeInstruction()) #= pc) { + break; + } else { + pc = nextPc; + } + .. + } while (pc != null); + .. +} +~~~~~~~~ + +Each bytecode instruction type corresponds to a concrete gov.nasa.jpf.Instruction subclass that determines scheduling relevance based on the following factors: + + * **Instruction Type** - due to the stack based nature of the JVM, only about 10% of the Java bytecode instructions are scheduling relevant, i.e. can have effects across thread boundaries. The interesting instructions include direct synchronization (`monitorEnter`, `monitorexit`, `invokeX` on synchronized methods), field access (`putX`, `getX`), array element access (`Xaload`, `Xastore`), and invoke calls of certain Thread (`start()`, `sleep()`, `yield()`, `join()`) and Object methods (`wait()`, `notify()`). + * **Object Reachability** - besides direct synchronization instructions, field access is the major type of interaction between threads. However, not all putX / getX instructions have to be considered, only the ones referring to objects that are reachable by at least two threads can cause data races. While reachability analysis is an expensive operation, the VM already performs a similar task during garbage collection, which is extended to support POR. + * **Thread and Lock Information** - even if the instruction type and the object reachability suggest scheduling relevance, there is no need to break the current transition in case there is no other runnable thread. In addition, lock acquisition and release (`monitorenter`, `monitorexit`) do not have to be considered as transition boundaries if there they happen recursively - only the first and the last lock operation can lead to rescheduling. + +![Figure 1: Scheduling Relevance Filters](../graphics/por-scheduling-relevance.svg){align=center width=650} + +While JPF uses these informations to automatically deduce scheduling relevance, there exist three mechanisms to explicitly control transition boundaries (i.e. potential thread interleavings) + + 1. `Attributor` - a configurable concrete class of this type is used by JPF during class loading to determine object, method and field attributes of selected classes and class sets. The most important attributes with respect to POR are method atomicity and scheduling relevance levels: (a) never relevant, (b) always scheduling relevant, (c) only relevant in the context of other runnables. (d) only relevant of top-level lock. The default Attributor executes all java code atomically, which is can be too aggressive (i.e. can cause `BlockedAtomicExceptions`). + + 2. `VMListener` - a listener can explicitly request a reschedule by calling `ThreadInfo.yield()` in response of a instruction execution notification. + + 3. `Verify` - a class that serves as an API to communicate between the test application and JPF, and contains `beginAtomic()`, `endAtomic()` functions to control thread interleaving + +The main effort of JPFs POR support relates to extending its precise mark and sweep collector. POR reachability is a subset of collector reachability, hence the mechanism piggybacks on the mark phase object traversal. It is complicated by the fact that certain reference chains exist only in the (hidden) VM implementation layer. For instance, every thread has a reference to its ThreadGroup, and the ThreadGroup objects in turn have references to all included threads, hence - from a garbage collection perspective - all threads within a group are mutually reachable. If the application under test does not use Java reflection and runtime queries like thread enumeration, POR reachability should follow accessibility rules as closely as possible. While JPF's POR does not yet support protected and private access modifiers, it includes a mechanism to specify that certain fields should not be used to promote POR reachability. This attribute is set via the configured Attributor at class load time. + +![Figure 2: Mark Phase of Reachability Analysis](../graphics/por-mark.svg){align=center width=460} + +With this mechanism, calculating POR reachability becomes a straight forward approach that is divided into two phases. Phase 1 non-recursively marks all objects of the root set (mostly static fields and thread stacks), recording the id of the referencing thread. In case an object is reachable from a static field, or from two threads, it's status is set to shared. Phase 2 recursively traverses all heap objects, propagating either a set shared status or the referencing thread id through all reference fields that are not marked as reachability firewalls. Again, if the traversal hits an object that is already marked as referenced by another thread, it promotes the object status to shared, and from there propagates the shared status instead of the thread id. + +To further reduce irrelevant context switches, JPF can check for lock protection to determine if a field access is scheduling relevant. If the property `vm.por.sync_detection` is set to true, JPF looks for potential lock candidates when analyzing `GET_x/SET_x` instructions. The policy of detecting lock candidates is configurable with the property `vm.por.fieldlockinfo.class`, the default `gov.nasa.jpf.jvm.StatisticFieldLockInfo` just defers the decision by recording the set of locks held when executing the field instruction, computing the set intersection at subsequent accesses. If the set does not get empty for a configurable number of field accesses, the field is marked as lock protected, and henceforth not treated as transition boundary. If however the set should afterwards become empty, a warning like + +~~~~~~~~ {.bash} +Warning: unprotected field access of: Event@70.count in thread: "Thread-1" oldclassic.java:107 + sync-detection assumed to be protected by: Event@70 + found to be protected by: {} + >>> re-run with 'vm.por.sync_detection=false' or exclude field from checks <<< +~~~~~~~~ + +is issued, and the field access is again treated as transition breaker. + +The set of fields to be analyzed can be specified with the properties `vm.por.include_fields` and `vm.por.exclude_fields`. Per default, fields of system library classes are not analyzed (this is esp. useful to avoid context switches for global objects like `System.out`). + +Even with all these optimizations, some unwanted transition breakers are likely to remain. This is mostly due to two constraints: + + * JPF only considers reachability, not accessibility + * write once, read multiple conditions cannot be detected a priori for fields that are not final, or inside immutable objects (like `java.lang.String`) + +Especially the last issue might be subject to further enhancements diff --git a/docs/devel/report.md b/docs/devel/report.md new file mode 100644 index 0000000..aecfd6b --- /dev/null +++ b/docs/devel/report.md @@ -0,0 +1,70 @@ +# The JPF Report API # +The JPF report system consists of three major components: + + - the `Reporter` + - any number of format specific `Publisher` objects + - any number of tool-, property-, Publisher-specific `PublisherExtension` objects + +Here is the blueprint: + +![Figure: JPF Report System](../graphics/report.svg){align=center width=800} + +The `Reporter` is the data collector. It also manages and notifies `Publisher` extensions when a certain output phase is reached. The `Publishers` are the format (e.g. text, XML) specific output producers, the most prominent one being the `ConsolePublisher` (for normal, readable text output on consoles). `PublisherExtensions` can be registered for specific `Publishers` at startup time, e.g. from Listeners implementing properties or analysis modes such as `DeadlockAnalyzer`. This is so common that the `ListenerAdapter` actually implements all the required interface methods so that you just have to override the ones you are interested in. + +Configuration is quite easy, and involves only a handful of JPF properties that are all in the report category. The first property specifies the Reporter class itself, but is not likely to be redefined unless you have to implement different data collection modes. + +~~~~~~~~ {.bash} +report.class=gov.nasa.jpf.report.Reporter +~~~~~~~~ + +The next setting specifies a list of Publisher instances to use, using symbolic names: + +~~~~~~~~ {.bash} +report.publisher=console,xml +~~~~~~~~ + +Each of these symbolic names has to have a corresponding class name defined: + +~~~~~~~~ {.bash} +report.console.class=gov.nasa.jpf.report.ConsolePublisher +~~~~~~~~ + +Finally, we have to specify for each symbolic publisher name and output phase what topics should be processed in which order, e.g. + +~~~~~~~~ {.bash} +report.console.property_violation=error,trace,snapshot +~~~~~~~~ + +Again, the order of these topics matters, and gives you complete control over the report format. As usual, please refer to `defaults.properties` for default values. + +Publisher classes can have their own, additional properties. For instance, the `ConsolePublisher` implementation can be further configured with respect to the information that is included in traces (bytecodes, method names etc.), and to redirect output (file, socket). Please refer to the constructor of this class for further details. + +~~~~~~~~ {.bash} +# save report to file +report.console.file=My_JPF_report +~~~~~~~~ + +All of the involved core classes and interfaces reside in the `gov.nasa.jpf.report` package. The most common way to extend the system is to use your own `PublisherExtension` implementation, which involves two steps: + + - implement the required phase and format specific methods + - register the extension for a specific Publisher class + + +The `DeadlockAnalyzer` (which is a listener to analyze concurrency defects) can be used as an example of how to do this: + +~~~~~~~~ {.java} +public class DeadlockAnalyzer extends ListenerAdapter { + ... + public DeadlockAnalyzer (Config config, JPF jpf){ + jpf.addPublisherExtension(ConsolePublisher.class, this); // (1) + ... + } + ... + public void publishPropertyViolation (Publisher publisher) { // (2) + PrintWriter pw = publisher.getOut(); + publisher.publishTopicStart("thread ops " + publisher.getLastErrorId()); + + ... // use 'pw' to generate the output + } +} +~~~~~~~~ diff --git a/docs/graphics/DFSListener.svg b/docs/graphics/DFSListener.svg new file mode 100644 index 0000000..1684827 --- /dev/null +++ b/docs/graphics/DFSListener.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2005-10-21 18:50:44 +0000Canvas 1Layer 1searchStartedsearchFinishedstateAdvancedpropertyViolatedstateBacktrackedsearchConstraintHit diff --git a/docs/graphics/app-types.svg b/docs/graphics/app-types.svg new file mode 100644 index 0000000..f845707 --- /dev/null +++ b/docs/graphics/app-types.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2015-01-05 22:17:29 +0000App TypesLayer 1non-functional properties ■ unhandled exceptions (incl. AssertionError) ■ deadlocks ■ racesrestricted choice types ■ scheduling sequences ■ java.util.Random improved inspection ■ coverage statistics ■ exact object counts ■ execution costsconstraintsbenefitsrestricted application models ■ UML statemachines ■ does not run w/o JPF libraries runtime costs ■ order of magnitude slower ■ state storage memorystandard library support ■ java.net, javax.swing, .. (needs abstraction models) functional (domain) properties ■ built-in into JPF librariesfunctional property impl. costs ■ listeners, MJI knowledgeflexible state space ■ domain specific choices (e.g. UML "enabling events")runtime costs & library support ■ usually not a problem, domain libs can control state spaceruns on anyJVMruns onlyunder JPFlow modeling costs ■ statemachine w/o layout hassle,..initial domain impl. costs ■ domain libs can be tricky "sweet spot"annotate program ■ requirements ■ sequences (UML) ■ contracts (PbC) ■ tests … analyze program ■ symbolic exec → test data ■ thread safety / races *.class*.java@V*.javaJPF unawareprogramsJPF enabledprogramsJPF dependentprograms diff --git a/docs/graphics/attributes.svg b/docs/graphics/attributes.svg new file mode 100644 index 0000000..2aa20a4 --- /dev/null +++ b/docs/graphics/attributes.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-16 18:21:11 +0000Canvas 1Layer 1dup(), push(), pop(), ..------getOperandAttr(idx)setOperandAttr(idx,obj)getLocalAttr(idx)setLocalAttr(idx,obj)int[] localsObject[] localAttrint[] operandsObject[] operandAttrStackFramegetIntValue(idx), ...setIntValue(idx, v), ...------getFieldAttr(idx)setFieldAttr(idx,obj)getObjectAttr()setObjectAttr(obj)int[] valuesObject[] fieldAttrsObject objectAttrFieldslocalsvaluesattributesoperandsslotsfield-valuesattributesputfieldgetfielddup..iload..istore..invokevirtual..return..attributeobjectsetAttr(i,o)getAttr(i)- listener- Instruction- native peerget?Attr(i)set?Attr(i,o)JPF coreJPFextensionattribute APIobject-attrThreadInfoElementInfo diff --git a/docs/graphics/bc-factory.svg b/docs/graphics/bc-factory.svg new file mode 100644 index 0000000..f69c951 --- /dev/null +++ b/docs/graphics/bc-factory.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-16 18:32:22 +0000Canvas 1Layer 1*.classInstruction ifeq(tgt)...«interface»InstructionFactory...Instruction execute()InstructionIFEQIFEQ......Instruction execute (){.. cond = popCondition() if (cond) return jumpTarget else return getNextInsn()setCode(code)factoryInstruction[] codeMethodInfoconcrete execution semanticsabstract execution semanticsconcrete valueexecutionsymbolic valueexecutioninstruction setInstruction execute(){.. if (!firstStepInsn()){ setNextCG(new PCChoiceGenerator()) return this } popCondition() // not interested cond = getCG().getNextChoice() if (cond){... return jumpTarget } else {... return getNextInsn()per bytecodefactory methodsInstruction ifeq(tgt)...gov.nasa.jpf.jvm.bytecodeInstructionFactoryInstruction ifeq(tgt)...gov.nasa.jpf.symbcSymbolicInstructionFactoryInstruction ifeq(int jumpTarget){ return new IFEQ(jumpTarget)ClassInfoClassFileCodeBuilderConfigvm.insn_factory.class=... diff --git a/docs/graphics/cg-impl.svg b/docs/graphics/cg-impl.svg new file mode 100644 index 0000000..07a14cb --- /dev/null +++ b/docs/graphics/cg-impl.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-02 07:14:49 +0000Canvas 1Layer 1initNextTransition(){... curCg = nextCg nextCg = null curCg.advance() ..setExecThread() ...executeTransition(){.. isFirstStepInsn = true while (pc != null) { nextPc = executeInstruction() if (ss.breakTransition()) break else pc = nextPc isFirstStepInsn = falseexecute(){.. if (!ti.isFirstStepInsn()) { ChoiceGenerator cg = ..createMonitorEnterCG(..) if (cg != null){ ss.setNextChoiceGenerator(cg) return this // repeat } ei.lock(ti) return getNextPc(ti);execute()InstructioninitNextTransition()breakTransition()setNextChoiceGenerator()nextCgcurCgSystemStatehasMoreChoices()advance()ChoiceGeneratorgetNextChoice()threadSetThreadCGgetNextChoice()doubleSetDoubleCG......executeTransition()executeInstruction()isFirstStepInsn(){pc, nextPc}ThreadInfoMonitorEnterInvoke.....MethodInfoNativePeere.g. JPF_gov_nasa_jpf_vm_Verify.getBoolean(env)top half: executed on first invocationoptionally sets next CG and reexecutesbottom half: executed on revisit (orif no CG created because of policy)does semantic action based oncurrent CGs choicescheduling choicesdata acquisition choices123top halfbottomhalfif (!ti.isFirstStepInsn()){ cg = new BooleanCG() ss.setNextChoiceGenerator(cg) env.repeatInvocation() ..} else { cg = ss.getChoiceGenerator() return ((BooleanCG)cg).getNextChoice()}breakTransition(){... return nextCg != null diff --git a/docs/graphics/cg-motivation.svg b/docs/graphics/cg-motivation.svg new file mode 100644 index 0000000..e8c750c --- /dev/null +++ b/docs/graphics/cg-motivation.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2010-02-22 05:27:10 +0000Canvas 1Layer 1T ± Δ.. double v = Verify.getDouble("velocity"); ..velocity.class = gov.nasa.jpf.jvm.choice.DoubleThresholdGeneratorvelocity.threshold = 13250velocity.delta = 500application code(test driver)configuration (e.g. mode property file)C = { T-Δ, T, T+ Δ }Verify.getBoolean()Verify.getInt(0,4)Verify.getDouble(1.0,1.5)C = { true, false }C = { 0, 1, 2, 3, 4 }✓?potentially large sets with lots of uninteresting values??no finite value set without heuristicsC = { ∞ }e.g. "Threshold" heuristicChoice Generators+Configurable Heuristic Choice ModelsJPF internal object to store and enumerate a set of choicesconfigurable classes tocreate ChoiceGenerator instanceshasMoreChoices()advance()getNextChoice() → xchoiceSet: {x}xChoiceGenerator diff --git a/docs/graphics/cg-ontology.svg b/docs/graphics/cg-ontology.svg new file mode 100644 index 0000000..fab55e3 --- /dev/null +++ b/docs/graphics/cg-ontology.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2010-02-22 02:58:46 +0000Canvas 1Layer 1TransitionStateChoiceScheduling ChoiceData Choiceboolean b = Verify.getBoolean();double d = Verify.getDouble("MyHeuristic");..synchronized (..) {..}wait (..)x = mySharedObject..Control Choiceif (<cond>) ..INVOKECG.setInvocations(..).. diff --git a/docs/graphics/cg-sequence.svg b/docs/graphics/cg-sequence.svg new file mode 100644 index 0000000..5e0ff92 --- /dev/null +++ b/docs/graphics/cg-sequence.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2006-05-05 17:02:45 +0000Canvas 1Layer 1......get_field...monitor_enter...get_fieldmonitor_enter...ChoiceGeneratorTjTj+1Tj+2CGkCGlsetNextCGgetNextChoiceTransitionc1kc2kc3kSkc1kc2k{{}},==Statebacktrackadvancec2k,c1l...,execute{Instruction}Sl diff --git a/docs/graphics/choicegen-example.svg b/docs/graphics/choicegen-example.svg new file mode 100644 index 0000000..675ec8d --- /dev/null +++ b/docs/graphics/choicegen-example.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2006-05-03 17:51:17 +0000Canvas 1Layer 1T ± Δ.. double v = Verify.getDouble("velocity"); ..velocity.class = DoubleThresholdvelocity.threshold = 13250velocity.delta = 500application code(test driver)configuration (e.g. mode property file)C = { T-Δ, T, T+ Δ }Verify.getBoolean()Verify.getInt(0,4)Verify.getDouble(1.0,1.5)C = { true, false }C = { 0, 1, 2, 3, 4 }✓?potentially large sets with lots of uninteresting values??no finite value set without heuristicsC = { ∞ }e.g. "DoubleThresholdChoice"Choice Generators+Configurable Heuristic Choice ModelsJPF internal object to store and enumerate a set of choicesconfigurable classes tocreate ChoiceGenerator instanceshasMoreChoices()advance()getNextChoice() → xchoiceSet: {x}xChoiceGenerator diff --git a/docs/graphics/genpeer.svg b/docs/graphics/genpeer.svg new file mode 100644 index 0000000..6887428 --- /dev/null +++ b/docs/graphics/genpeer.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-04 01:29:55 +0000Canvas 1Layer 1GenPeerpackage x.y.z;class MyClass { ... native String foo (int i, String s);}class JPF_x_y_z_MyClass { ... @MJI public static int foo__ILjava_lang_String__2 (MJIEnv env, int objRef, int i, int sRef) { int ref = MJIEnv.NULL; // <2do> fill in body return ref; }}"java gov.nasa.jpf.GenPeer x.y.z.MyClass > JPF_x_y_z_MyClass.java" diff --git a/docs/graphics/interleavings.svg b/docs/graphics/interleavings.svg new file mode 100644 index 0000000..4dfa19e --- /dev/null +++ b/docs/graphics/interleavings.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-11-19 20:18:08 +0000Canvas 1Layer 1.........12P1P2PNn1n2...AtomicInstructionsThreads12I1∑niIM......nN.........Interleavings(∑ n )!∏ (n !)Ni=1iNi=1iM = diff --git a/docs/graphics/jpf-abstractions.svg b/docs/graphics/jpf-abstractions.svg new file mode 100644 index 0000000..b636c6f --- /dev/null +++ b/docs/graphics/jpf-abstractions.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-11-26 21:24:31 +0000Canvas 1Layer 1search ()VM vmSearchforward ()backtrack ()restoreState ()VMsearch ()DFSearchrun ()search, vm, configJPFexecuteTransition ()executeInstruction ()ThreadInfoinitializeNextTransition()executeNextTransition()SystemStateClassInfoMethodInfoFieldInfoElementInfoFieldsMonitorStaticsbytecode executiontype + codemgntobjectmodelgov.nasa.jpfgov.nasa.jpf.searchsearch ()HeuristicSearchgov.nasa.jpf.vmgov.nasa.jpf.search.heuristicgov.nasa.jpf.vm.bytecodeexecute ()Instruction.........search ()BFSHeuristic...while (notDone) { ..vm.forward(); ..vm.backtrack(); if (!properties.check()){ reportError(); break; ...search.class=...vm.class=...push (), pop() ...StackFrameConfigHeap diff --git a/docs/graphics/jpf-basic.svg b/docs/graphics/jpf-basic.svg new file mode 100644 index 0000000..fdfae11 --- /dev/null +++ b/docs/graphics/jpf-basic.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-11-19 18:37:23 +0000Canvas 1Layer 1JPF*.classreport*.jpfSystem under Test(Java bytecode)Verification ResultJPF ConfigurationProperties to Verify diff --git a/docs/graphics/jpf-intro-new.svg b/docs/graphics/jpf-intro-new.svg new file mode 100644 index 0000000..56fc211 --- /dev/null +++ b/docs/graphics/jpf-intro-new.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2009-04-10 01:07:23 +0000Canvas 1Layer 1------------------------------------ error path..Step #14 Thread #1 oldclassic.java:95 event2.waitForEvent(); oldclassic.java:37 wait();------------------------------------ thread stacksThread: Thread-0 at java.lang.Object.wait(Object.java:429) at Event.waitForEvent(oldclassic.java:37) ..======================== 1 Error Found: DeadlockJPFCorebytecodesetlistener/propertypublisher/ -extchoicegeneratorserializer/restorerannotation (optional) in-sourceproperty specdomainframeworkmodellibraryapplicationSuTexecutionenvironmentsearchstrategyJavavirtualmachinebytecodereportJPFendseenerror-pathproperty violationhost - JVMJPF distribution...nativepeer......extensions*.jpfJPF configurationreportstandardJava libraries*.jar*.jar diff --git a/docs/graphics/jpf-layers.svg b/docs/graphics/jpf-layers.svg new file mode 100644 index 0000000..ada4957 --- /dev/null +++ b/docs/graphics/jpf-layers.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-02 21:48:18 +0000Canvas 1Layer 1platform OShost JVMnative librarieslibrary classesJPF (Java application)modeled classesrt.jarJNIMJI*.classsystem under teststandard Java installationCLASSPATHModel layerJava layerNative layer"Java Native Interface""Model Java Interface" diff --git a/docs/graphics/jpf-project.svg b/docs/graphics/jpf-project.svg new file mode 100644 index 0000000..790b51b --- /dev/null +++ b/docs/graphics/jpf-project.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2009-09-09 23:36:00 +0000Canvas 1Layer 1jpf-Xsrcbuildbuild.xmljpf.propertiesX.jarX-classes.jarX-annotations.jarmainpeersclassesannotationstestsexampleslibtoolsbinRunJPF.jarRunAnt.jarjpfantnbprojectproject.xmlide-file-targets.xml.classpathmainpeersclassesannotationstestsexampleseclipserun-jpf.launchJPF project properties file(runtime def: native_classpath, classpath, sourcepath)host-VM executed classes (listeners, infrastructure etc.)host-VM executed library classes (MJI native peers)JPF executed library classes →sourcepathJPF processed Java annotationsregression testsdemos →sourcepathAnt build script (compile, build, test, clean)temporary build artifacts (classfiles)main host-VM executed project jar (main,peers →native_classpath)JPF executed library jar (classes,annotations →classpath)separate anotations jar (for JPF external SUT exec)required runtime jars →native_classpathbuild toolsant.jar, junit.jar, ...bcel.jar, antlr.jar, ..(example) 3rd party jarsbuild artifactspermanent build artifacts(example) 3rd party jarsJPF startup jar (executable)JPF build jar (executable)scriptsJPF startup script (→RunJPF.jar)JPF build script (→RunAnt.jar)Eclipse project configurationproject sourcesproject root directorybinary distributionNetBeans project configurationNetBeans file actions (JPF execution)Eclipse launch configs (JPF execution)IDE supportcompilebuildtest diff --git a/docs/graphics/listener-overview.svg b/docs/graphics/listener-overview.svg new file mode 100644 index 0000000..8a58bd9 --- /dev/null +++ b/docs/graphics/listener-overview.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-02 07:42:37 +0000Canvas 1Layer 1SearchVMJPFSystem under testlistenersexecuted by JPFexecuted by host JVMsearch event notificationsexecution event notificationsconfigured- classLoaded (vm)- threadScheduled (vm)- threadNotified (vm) ...- executeInstruction (vm)- instructionExecuted (vm) ...- objectCreated (vm) ...- exceptionThrown(vm) ...- choiceGeneratorAdvanced (vm) ...- stateAdvanced (search)- stateBacktracked (search)- propertyViolated (search)- searchFinished (search) ...- +listener=<listener-class>- @JPFConfig(..)- listener.autoload=<annotations>- jpf.addListener(..) ...≪SearchListener≫≪VMListener≫ diff --git a/docs/graphics/listeners.svg b/docs/graphics/listeners.svg new file mode 100644 index 0000000..681d1ad --- /dev/null +++ b/docs/graphics/listeners.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2009-04-08 19:52:28 +0000Canvas 1Layer 1«interface»JPFListenerexecuteInstruction(vm)instructionExecuted(..)threadStarted(..)objectCreated(..)choiceGeneratorSet(..)choiceGeneratorAdvanced(..). . .«interface»VMListenersearchStarted(search)stateAdvanced(..)stateBacktracked(..)propertyViolated(..)searchFinished(..). . .«interface»SearchListenercheck(search,vm)getErrorMessage()«interface»Propertycheck(search,vm) {}. . .GenericPropertyinstructionExecuted(vm) {}searchStarted(search) {}. . .ListenerAdapterpublishStart(publisher)publishFinished(..). . .«interface»PublisherExtensioninstructionExecuted(vm) {}searchStarted(search) {}. . .PropertyListenerAdapter diff --git a/docs/graphics/mji-call.svg b/docs/graphics/mji-call.svg new file mode 100644 index 0000000..d5db418 --- /dev/null +++ b/docs/graphics/mji-call.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-24 04:08:50 +0000Canvas 1Layer 1package x.y.z;class C { ... native int foo (int p);}class JPF_x_y_z_C { ... public static int foo__I__I (MJIEnv env, int thisRef, int p) { int d = env.getIntField(thisRef, "data"); .. }}...int a = c.foo(3);...aload_1icont_3invokevirtual ..executeMethod (ThreadInfo ti..){ MJIEnv env = ti.getMJIEnv(); Object[] args = getArguments(); .. mth.invoke(peerCls, args); ..}ClassInfo (..){ peerCls = loadNativePeer(..); ..}executeMethod()peerClsClassInfoexecuteMethod()methodsNativePeergetXField(..)setXField(..)...threadInfoMJIEnvenvThreadInfoJPFclassloadingJPFmethodinvocationJPFobjectaccessJPF (model) classJVM (Java) classJava reflection callreflection diff --git a/docs/graphics/mji-functions.svg b/docs/graphics/mji-functions.svg new file mode 100644 index 0000000..bac9b5c --- /dev/null +++ b/docs/graphics/mji-functions.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-24 04:01:26 +0000Canvas 1Layer 1class JPF_x_y_z_MyClass { public static int foo__ILjava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int objRef, int i, int sRef) { String s = env.getStringObject(sRef); .. int ref = env.newString(..); return ref; }}package x.y.z;class MyClass { .. native String foo (int i, String s);}MJIEnvJPF objectsJava objectsNativePeerJPF executedhost VM executed- method lookup- parameter conversion- invocation- field access- object conversion- JPF intrinsics access"Model" Class"NativePeer" ClassMJI - "Model Java Interface" diff --git a/docs/graphics/mji-mangling.svg b/docs/graphics/mji-mangling.svg new file mode 100644 index 0000000..7e59270 --- /dev/null +++ b/docs/graphics/mji-mangling.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-02 21:54:02 +0000Canvas 1Layer 1package x.y;class MyClass { native int foo (int i, String s);}class JPF_x_y_MyClass { public static int foo__ILjava_lang_String_2 (MJIEnv env, int objref, int i, int sRef) {..}}Model ClassNative Peer Classmodel parameters(refs become 'int')MJI parametersJNI conformant manglingbooleanbytecharshortintlongfloatdoubleZBCSIJFD'_'';''['_1_2_3<type> [][<type>x.y.ZLx_y_Z_2<func> (..)<func>__<signature> diff --git a/docs/graphics/new-testing.svg b/docs/graphics/new-testing.svg new file mode 100644 index 0000000..4254ad1 --- /dev/null +++ b/docs/graphics/new-testing.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-05 00:34:03 +0000Canvas 1Layer 1@Test public void testX() { if (verifyNoPropertyViolation()) { String s = "one" + " two"; assert "one two".equals(s); }}boolean verifyNoPropertyViolation (String... jpfArgs) { ... args = append(jpfArgs, caller.getClassName(), caller.getMethodName()); .. JPF jpf = createAndRunJPF(args); ... errors = jpf.getSearchErrors(); if (!errors.isEmpty()) throw new AssertionError(..); ... return false; // -> don't execute test block}boolean verifyNoPropertyViolation(..){ return true;}start()JPFShellrunTestsOfThisClass()createAndRunJPF()...verifyNoPropertyViolation()verifyPropertyViolation()verifyUnhandledException()verifyAssertionError()...TestJPFtestX()...MyJPFProjectTestjpf-coretested JPF projectverifyNoPropertyViolation()verifyPropertyViolation()verifyUnhandledException()verifyAssertionError()JPF_.._TestJPFnative peercode verified by JPFexecuted by JPF whenrunning testexecuted outside JPF (starting JPF on test) diff --git a/docs/graphics/por-mark.svg b/docs/graphics/por-mark.svg new file mode 100644 index 0000000..f47b060 --- /dev/null +++ b/docs/graphics/por-mark.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-12-02 07:35:36 +0000Canvas 1Layer 1XX1XX12Xstatic fieldsT1T2root setheapphase 1phase 21 & 2 : referencing thread numberX : shared diff --git a/docs/graphics/por-scheduling-relevance.svg b/docs/graphics/por-scheduling-relevance.svg new file mode 100644 index 0000000..45c2886 --- /dev/null +++ b/docs/graphics/por-scheduling-relevance.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-11 18:17:44 +0000Canvas 1Layer 1executed bytecode instructionfield insnsync insninvoke insnsync mththreading callscheduling relevant insn typeother runnable threadsrecursive locksshared objectslock protected accessscheduling relevant instruction (registeres a ThreadChoiceGenerator)data racesdeadlocks(lock races)tracking of access threadslock distance & statisticsThread. start(), yield() sleep(), join()Object.wait(),notify()configuredclass/mthdattributesGETFIELDPUTFIELDGETSTATICPUTSTATICxALOADxASTOREMONITORENTERMONITOREXITINVOKEVIRTUALINVOKESTATIC diff --git a/docs/graphics/properties.svg b/docs/graphics/properties.svg new file mode 100644 index 0000000..ad56b87 --- /dev/null +++ b/docs/graphics/properties.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2011-05-11 18:07:23 +0000Canvas 1Layer 1jpf.home = ${user.home}/projects/jpfjpf-core = ${jpf.home}/jpf-corejpf-awt = ${jpf.home}/awtjpf-shell = ${jpf.home}/jpf-shelljpf-aprop = ......extensions = ${jpf-core},${jpf-shell}jpf-core = ${config_path}jpf-core.native_classpath=\ ${jpf-core}/build/jpf.jar;\ ... ${jpf-core}/lib/bcel.jar;jpf-core.classpath=\ build/jpf-classes.jarjpf-core.test_classpath=\ build/testsjpf-core.sourcepath=\ src/classes...jpf-awt-shell = ${config_path}@using = jpf-awtjpf-awt-shell.native_classpath=...jpf-awt-shell.classpath=......target = RobotManagertarget_args = ...@using = jpf-aprop@import = ./my.propertiesshell = .shell.basicshell.BasicShelllistener = .aprop.listener.SharedChecker...1. site properties2. project properties3. application properties4. command line~/.jpf/site.properties<project>/jpf.properties<project>/.../*.jpf> bin/jpf [-log][-show] {+log.info=..} .../RobotManager.jpf all jpf.properties inorder of extensionsjpf.properties in current directory- project locations- pre-loaded projects- project class paths- project dependencies- system-under-test- listeners, shells- debuggingcommand line property arguments...applicationpropertiessite properties diff --git a/docs/graphics/report.svg b/docs/graphics/report.svg new file mode 100644 index 0000000..cad3324 --- /dev/null +++ b/docs/graphics/report.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2010-09-10 23:02:45 +0000Canvas 1Layer 1JPF()addPublisherExtension()setPublisherTopics()reporterJPF..reporter = config.getInstance("report.class", Reporter.class,..);..searchStarted()propertyViolated()searchFinished()publishersReporterpublishStart()getOut()extensionstopicsoutPublisherpublishStart()publishTransition()publishPropertyViolation()publishFinished()<<PublisherExtension>>........for (Publisher p : publishers){ p.openChannel(); .. p.publishStart();.. public void publishStart() { for (String topic : startTopics) { if ("jpf".equals(topic)){ publishJPF(); ... for (PublisherExtension e : extensions) { e.publishStart(this); } ...out.println("JPF version" + ..);publishJPF()...ConsolePublisherpublishFinished()...DeadlockAnalyzerPrintWriter out = publisher,getOut();printTraceAnalysis(out);data collectionpublisher managementdata formattingtopic managementoutput channel managementproperty/listenerspecific output topicsreport.class=.report.Reporterreport.publisher=console,..report.console.class=.report.ConsolePublisherreport.console.start=jpf,..JPF configuration(e.g. jpf.properties or *.jpf files) diff --git a/docs/graphics/states-mc.svg b/docs/graphics/states-mc.svg new file mode 100644 index 0000000..8d9f5fd --- /dev/null +++ b/docs/graphics/states-mc.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2009-09-06 18:37:27 +0000Canvas 1Layer 1☠model checking:all program state are explored until none left or defect foundbacktrack≡≡≡match✘ diff --git a/docs/graphics/states-testing.svg b/docs/graphics/states-testing.svg new file mode 100644 index 0000000..12e5396 --- /dev/null +++ b/docs/graphics/states-testing.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-11-19 20:33:35 +0000Canvas 1Layer 1☠based on input set {d}only one pathexecuted at a time✔testing:{d} diff --git a/docs/graphics/sw-model-checking-2.svg b/docs/graphics/sw-model-checking-2.svg new file mode 100644 index 0000000..a0575f7 --- /dev/null +++ b/docs/graphics/sw-model-checking-2.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2015-01-05 22:19:29 +0000Canvas 1Layer 1a=0b=0b=1b=2c=0c=0c=0/0starta=1b=0b=1b=2c=-1c=1/0c=1✘12345✔✔6 diff --git a/docs/graphics/sw-model-checking.svg b/docs/graphics/sw-model-checking.svg new file mode 100644 index 0000000..1fd0a54 --- /dev/null +++ b/docs/graphics/sw-model-checking.svg @@ -0,0 +1,3 @@ + + + Produced by OmniGraffle 6.1 2014-11-19 20:40:12 +0000Canvas 1Layer 1Random random = new Random() int a = random.nextInt(2)int b = random.nextInt(3)int c = a/(b+a -2)①②③④a=0b=0b=1b=2c=0c=0c=0/0starta=1b=0b=1b=2c=-1c=1/0c=1✔ diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..a40d030 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,66 @@ +## Welcome to the Java™Pathfinder System ## + +This is the main page for Java™ Pathfinder (JPF). JPF is an extensible software model checking framework for Java™ bytecode programs. The system was developed at the [NASA Ames Research Center](http://arc.nasa.gov), open sourced in 2005, and is freely available on this server under the [Apache-2.0 license](http://www.apache.org/licenses/LICENSE-2.0). + + +This page is our primary source of documentation, and is divided into the following sections. + + --- + + * [Introduction](intro/index) -- a brief introduction into model checking and JPF + * [What is JPF?](intro/what_is_jpf) + * [Testing vs. Model Checking](intro/testing_vs_model_checking) + - [Random value example](intro/random_example) + - [Data race example](intro/race_example) + * [JPF key features](intro/classification) + + --- + + * [How to obtain and install JPF](install/index) -- everything to get it running on your machine + - [System requirements](install/requirements) + - Downloading [binary snapshots](install/snapshot) and [sources](install/repositories) + - [Creating a site properties file](install/site-properties) + - [Building, testing, and running](install/build) + - Installing the JPF plugins + - [Eclipse](install/eclipse-plugin) + - [NetBeans](install/netbeans-plugin) + + --- + + * [How to use JPF](user/index) -- the user manual for JPF + - [Different applications of JPF](user/application_types) + - [JPF's runtime components](user/components) + - [Starting JPF](user/run) + - [Configuring JPF](user/config) + - [Understanding JPF output](user/output) + - [Using JPF's Verify API in the system under test](user/api) + + --- + + * [Developer guide](devel/index) -- what's under the hood + * [Top-level design](devel/design) + * Key mechanisms, such as + - [ChoiceGenerators](devel/choicegenerator) + - [Partial order reduction](devel/partial_order_reduction) + - [Slot and field attributes](devel/attributes) + * Extension mechanisms, such as + - [Listeners](devel/listener) + - [Search Strategies](devel/design) + - [Model Java Interface (MJI)](devel/mji) + - [Bytecode Factories](devel/bytecode_factory) + * Common utility infrastructures, such as + - [Logging system](devel/logging) + - [Reporting system](devel/report) + * [Running JPF from within your application](devel/embedded) + * [Writing JPF tests](devel/jpf_tests) + * [Coding conventions](devel/coding_conventions) + * [Hosting an Eclipse plugin update site](devel/eclipse_plugin_update) + + --- + + * [JPF core project](jpf-core/index) -- description and link to jpf-core + + --- + + * [Related research and publications](papers/index) + diff --git a/docs/install/build.md b/docs/install/build.md new file mode 100644 index 0000000..9e8d3d6 --- /dev/null +++ b/docs/install/build.md @@ -0,0 +1,112 @@ +# Building, Testing, and Running # + +If you downloaded binary snapshots, you don't have anything to build (except of creating/updating you [site.properties](./site-properties) file). + +## Building JPF ## + +If you have cloned the project repositories you are interested in (which at least includes [jpf-core](../jpf-core/index)), you can build and test each of them by means of their included [Ant](http://ant.apache.org) `build.xml` scripts. Note that you have to install Ant and JUnit separately, e.g. following directions [here](../install/requirements). + + +### Using the command line ### + +~~~~~~~~ {.bash} +> cd jpf-core +> ant test + +... lots of output, at the end you should see something like: +BUILD SUCCESSFUL +Total time: 2 minutes 31 seconds +~~~~~~~~ + +### Within NetBeans ### + + 1. run **File/Open Project..** from the application menu, entering the JPF project you just downloaded (e.g. "jpf-core") + 1. select the project that appears in our project pane (e.g. "jpf-core") + 1. run **Build** from the project context menu + +### Within Eclipse ### + +* Ensure that the `JAVA_HOME` environment variable points to the jdk1.6xxx directory. If it is empty or points to a JRE then errors such as **javac not found** maybe seen. If you do not want the system Java settings to point to jdk1.6xxx, you can also set project specific settings in eclipse. + +* If you eclipse settings are set to **Build Automatically** then the project after being cloned will be built. + +* To build a particular project in the Project menu select **Build Project**. All the dependencies for the project will be built automatically. + +#### Project Specific JDK settings within Eclipse #### +1. In Eclipse go to **Project** -> **Properties** + +2. Select **Builders** + +3. Pick **Ant_Builder** -> click **Edit** + +4. Click on the **JRE** tab + +5. Select **Separate JRE** -> **Installed JREs** + +6. On Windows and Unix-based systems pick JDK1.6xxx. If it is not listed under the installed JREs, click on **Add**, browse your file system to where JDK1.6xxx resides and select. On OSx systems pick the JVM 1.6.0. + + +## Running JPF ## + +### Using the command line ### + + +~~~~~~~~ {.bash} +> cd jpf-core +> java -jar build/RunJPF.jar src/examples/Racer.jpf +JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center +..... +====================================================== statistics +elapsed time: 0:00:00 +states: new=9, visited=1, backtracked=4, end=2 +search: maxDepth=5, constraints=0 +choice generators: thread=8, data=0 +heap: gc=8, new=291, free=32 +instructions: 3112 +max memory: 79MB +loaded code: classes=73, methods=1010 + +====================================================== search finished: 1/12/10 2:30 PM +~~~~~~~~ + +### Using eclipse plugin ### + + 1. Right click on a .jpf file. Examples can be found in the src\examples directory in jpf-core + 1. If the eclipse plugin is correctly installed, a Verify option will appear. + 1. Select the Verify option and the verification process of the system specified in the .jpf file begins + +Note that the Application.jpf file essentially replaces previous uses of eclipse launch configurations. The required element of a .jpf file is the `target=MAIN_CLASS` where `MAIN_CLASS` is the class containing main method of the system under test. Any other configurations that need to be specified can be added here. for example `listener=gov.nasa.jpf.tools.SearchMonitor`. + +Specify `classpath=PATH_TO_BIN_DIRECTORY` to add the class files for the program under test to JPF's class path. Windows users will need to use the double-backslash notation in specifying paths in the .jpf file. An example .jpf file for the Windows platform is included below for convenience: + +~~~~~~~~ {.bash} +target=mutex.DekkerTestMain +report.console.property_violation=error,trace,snapshot +listener=gov.nasa.jpf.listener.EndlessLoopDetector +classpath=C:\\Users\\fred\\Documents\\ch02-mutex\\bin +sourcepath=C:\\Users\\fred\\Documents\\ch02-mutex\\src,C:\\Users\\Fred\\Documents\\ch02-mutex\\src-test +~~~~~~~~ + +The .jpf file not only indicates the `target` and `classpath`, but it also turns on error reporting with trace generation (`report.console.property_violation`) and configures the source path (`sourcepath`). Note that multiple source directories are specified using the comma separator. + +### Using eclipse Run Configuration ### + + 1. Select a .jpf file by clicking on it in the Package Explorer + 1. Click **Run** -> **Run Configurations** -> **run-JPF-core**. It is important the correct .jpf file is selected when the configuration is run. + +#### Windows users #### +After a fresh install of jpf-core you may see the following when trying to use the Eclipse Run-jpf-core configuration: + +~~~~~~~~ +java.lang.NoClassDefFoundError: gov/nasa/jpf/Main +Caused by: java.lang.ClassNotFoundException: gov.nasa.jpf.Main + at java.net.URLClassLoader$1.run(Unknown Source) + at java.security.AccessController.doPrivileged(Native Method) + at java.net.URLClassLoader.findClass(Unknown Source) + at java.lang.ClassLoader.loadClass(Unknown Source) + at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) + at java.lang.ClassLoader.loadClass(Unknown Source) +Exception in thread "main" +~~~~~~~~ + +In this particular case, the error was generated after the initial build after the clone had completed. To resolve the issue, **refresh the Eclipse workspace** (F5 or right click Refresh). After the refresh, the Run-jpf-core configuration should work as described above. diff --git a/docs/install/eclipse-jpf.md b/docs/install/eclipse-jpf.md new file mode 100644 index 0000000..bae977d --- /dev/null +++ b/docs/install/eclipse-jpf.md @@ -0,0 +1,24 @@ +# eclipse-jpf # + +This is a plugin to launch JPF on selected application property files (*.jpf) from within Eclipse. This plugin is the Eclipse analog to netbeans-jpf. This plugin is minimal by design and serves mostly to start an external JPF process from within Eclipse. + +To this end, the plugin adds a "Verify.." popup menu item for *.jpf files that are selected in the package explorer window. + +Depending on the selected application property file, output will appear either in the eclipse console view or a jpf-shell. + +The site.properties location can be entered in the "JPF Preferences" pane within the normal Eclipse Preferences window. The default location is `$HOME/.jpf/site.properties`. + + +This project is *not* a normal JPF project, i.e. it does not follow the usual JPF directory structure and artifacts. This is an Eclipse plugin project that builds into a jar file (attached) that installs into Eclipse as a plugin. Of course that means you need an Eclipse installation that includes the Plugin Development Environment (PDE) in order to build this project. + +### Repository ### +The eclipse-jpf source repository is located on http://babelfish.arc.nasa.gov/hg/jpf/eclipse-jpf + +### Installation ### +If you have the eclipse PDE installed, the preferred way is to get the eclipse-jpf sources from the repository, build via the eclipse plugin Export Wizard into the /dropins folder and restart eclipse. + +If you don't have the eclipse PDE, you can either install this plugin via "Eclipse/Help/Install New Software..." by entering the the eclipse-jpf update site URL: + + http://babelfish.arc.nasa.gov/trac/jpf/raw-attachment/wiki/projects/eclipse-jpf/update + +or download the attached eclipse-jpf_.jar file and move it into your /dropins folder. In both cases, you need to restart eclipse in order to load the plugin. Note however that this might not be the latest eclipse-jpf version and it might or might not work with your eclipse. \ No newline at end of file diff --git a/docs/install/eclipse-plugin.md b/docs/install/eclipse-plugin.md new file mode 100644 index 0000000..2bcbb3a --- /dev/null +++ b/docs/install/eclipse-plugin.md @@ -0,0 +1,15 @@ +# Installing the Eclipse JPF plugin # + +Note that this is assuming the latest Eclipse and Java versions, which is Eclipse 4.3.x and Java 7 at the time of this writing. Older versions might or might not work. +There are three different ways to install the plugin, which are listed in the order of preference if you want to ensure that you are using the latest plugin version: + +### Build from sources ### +If you have the Eclipse Plugin Development Environment installed (PDE -comes with standard Eclipse distribution), the preferred way is to download the [eclipse-jpf](./eclipse-jpf) sources from the repository, build the plugin into your /dropins/plugins directory, and restart Eclipse. This ensures you are using the latest version of the plugin, and the build process will tell you if your Eclipse is compatible. + +### Install from attached plugin jar ### +Alternatively, you can download one of the attached eclipse-jpf_.jar files, place it into your /dropins/plugins directory, and restart Eclipse. + +### Install from update site ### +The most convenient, but least up-to-date way to install eclipse-jpf is to use the Eclipse/Help/Install New Software... dialog, by entering the the eclipse-jpf update site URL: + + http://babelfish.arc.nasa.gov/trac/jpf/raw-attachment/wiki/projects/eclipse-jpf/update diff --git a/docs/install/eclipse-plugin/update.md b/docs/install/eclipse-plugin/update.md new file mode 100644 index 0000000..18ccf75 --- /dev/null +++ b/docs/install/eclipse-plugin/update.md @@ -0,0 +1 @@ +This is the target location for the eclipse-jpf update site. \ No newline at end of file diff --git a/docs/install/eclipse-plugin/update/features.md b/docs/install/eclipse-plugin/update/features.md new file mode 100644 index 0000000..f22f5b8 --- /dev/null +++ b/docs/install/eclipse-plugin/update/features.md @@ -0,0 +1 @@ +Nothing to see here, just a place holder to upload the eclipse-jpf feature. \ No newline at end of file diff --git a/docs/install/eclipse-plugin/update/plugins.md b/docs/install/eclipse-plugin/update/plugins.md new file mode 100644 index 0000000..180eefa --- /dev/null +++ b/docs/install/eclipse-plugin/update/plugins.md @@ -0,0 +1 @@ +Nothing to see here, just a place holder to upload the eclipse-jpf plugin. \ No newline at end of file diff --git a/docs/install/index.md b/docs/install/index.md new file mode 100644 index 0000000..b7f40b8 --- /dev/null +++ b/docs/install/index.md @@ -0,0 +1,19 @@ +# How to Obtain and Install JPF # + +The JPF core and most of its extensions are pure Java applications, so they are not many platform requirements other than sufficient memory and a reasonably fast machine. Use of IDEs is optional, but most JPF modules include out-of-the-box configuration files for both Eclipse and Netbeans. + +You can obtain JPF sources from the [Mercurial](http://mercurial.selenic.com/wiki/) repositories, but it is not recommended to clone this directory itself (you most likely would get old sub-repository revisions). You need at least the core of JPF, [jpf-core](../jpf-core/index) which can be built with [Ant](http://ant.apache.org) from the command line, or directly opened as a [NetBeans](http://www.netbeans.org) or [Eclipse](http://www.eclipse.org) project. + +The JPF core project already come with its configuration file, but you have to create a per-site [site.properties](site-properties) file. + +If you use the JPF shells (graphical JPF front-ends), you might also want to install the corresponding NetBeans or Eclipse adapter plugins, although shells are standalone Java (swing) applications that can also be used without an IDE. + +Here are the details: + + - [System requirements](requirements) + - [Downloading binary snapshots](snapshot) + - [Downloading sources from the Mercurial repositories](repositories) + - [Creating a site properties file](site-properties) + - [Building, testing, and running](build) + - [Installing the Eclipse plugin](eclipse-plugin) + - [Installing the NetBeans plugin](netbeans-plugin) \ No newline at end of file diff --git a/docs/install/netbeans-jpf.md b/docs/install/netbeans-jpf.md new file mode 100644 index 0000000..539e0df --- /dev/null +++ b/docs/install/netbeans-jpf.md @@ -0,0 +1,10 @@ +# netbeans-jpf # + +This is a plugin to launch JPF on selected application properties (*.jpf) files from within NetBeans. No worries, this is a minimal plugin that mainly starts an external process (JPF), so it doesn't muck with your NetBeans views. + +The main functions are + + - start the JPF shell in an external process + - wait for editor positioning requests from the JPF shell, and show the corresponding source lines + +Why is this named differently than all the other projects? Because it is a different kind of project: this is *not* a normal JPF project, i.e. it is not a freeform NetBeans project with the usual JPF directory structure and artifacts. It is a NetBeans module, and it's main artifact is a *.nbm file in the build directory. \ No newline at end of file diff --git a/docs/install/netbeans-plugin.md b/docs/install/netbeans-plugin.md new file mode 100644 index 0000000..c5360a4 --- /dev/null +++ b/docs/install/netbeans-plugin.md @@ -0,0 +1,11 @@ +# Installing the NetBeans JPF plugin # + 1. Download and install [jpf-core](../jpf-core/index), e.g. from the [Mercurial repository](../install/repositories) + 2. -------------- take a break --------------- + 3. Download the `gov-nasa-jpf-netbeans-runjpf.nbm` file from [here](http://babelfish.arc.nasa.gov/trac/jpf/attachment/wiki/install/netbeans-plugin/gov-nasa-jpf-netbeans-runjpf.nbm). + 4. From within Netbeans go to **Tools**->**Plugins** (Alt+T followed by Alt+g) + 5. Select the **Downloaded** tab + 6. Click on **Add Plugins...** (Alt+A) + 7. Select the `gov-nasa-jpf-netbeans-runjpf.nbm` file that was downloaded in step 3 + 8. Select **install** + 9. Agree to the License agreement + 10. Restart Netbeans \ No newline at end of file diff --git a/docs/install/repo_shell.md b/docs/install/repo_shell.md new file mode 100644 index 0000000..e5609b1 --- /dev/null +++ b/docs/install/repo_shell.md @@ -0,0 +1,74 @@ +# Checkout and Build from Shell Prompt (Unix) # + +While there is a CVS repository on the JPF Sourceforge site, it is not in use anymore. The current version is kept in the Subversion repository. + + We will shift to a distributed version control system (Mercurial or Git) soon + + +# SVN # + +This is not a general introduction of [nor do we cover details of [[https://sourceforge.net/svn/?group_id=136825|Subversion on Sourceforge]((SVN),)(http://subversion.tigris.org|Subversion]]). To obtain the current JPF version, execute the following command from a shell prompt: + +~~~~~~~~ {.bash} +>svn checkout https://javapathfinder.svn.sourceforge.net/svnroot/javapathfinder/trunk +~~~~~~~~ + +To update later-on, enter from within one of the javapathfinder directories + + +~~~~~~~~ {.bash} +>svn update +~~~~~~~~ + +To commit (in case you are a project member and have a sourceforge account), use + + +~~~~~~~~ {.bash} +>svn commit -m "commit message" +~~~~~~~~ + +In order to build and test JPF from the commandline, you need Ant and JUnit. If you do not want to use the scripts and versions that are provided with JPF, make sure you have set up your *CLASSPATH* to contain both tools. As of Ant 1.6.5 and JUnit 4.1, this involves the following environment settings: + + +~~~~~~~~ {.bash} +>export PATH=$PATH:/bin +>export CLASSPATH=/lib/ant.jar:/junit-4.1.jar +~~~~~~~~ + +~~~~~~~~ + for your convenience, we have added all required external libraries +and scripts to the *build-tools* directory, so you do not have to install +any of the external components. +~~~~~~~~ +Now you can proceed as described in section Building JPF from a Command Line. For the impatient reader, this is mainly one command + + +~~~~~~~~ {.bash} +>cd javapathfinder-trunk +>build-tools/bin/ant run-tests + +Buildfile: build.xml + +init: + [mkdir] Created dir: /users/pcmehlitz/projects/javapathfinder-trunk/build + ... +compile-jpf: + [javac] Compiling 543 source files to /users/pcmehlitz/projects/javapathfinder-trunk/build/jpf + ... +run-tests: + [echo] --- running Junit tests from build/test.. + [junit] Running TestJavaLangObjectJPF + [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.876 sec + ... +BUILD SUCCESSFUL +Total time: 2 minutes 25 seconds +~~~~~~~~ + +or (especially for non-Unix folk) + + +~~~~~~~~ {.bash} +>java RunAnt run-tests +~~~~~~~~ + +which should compile the whole system and runs the regression test suite with the provided Ant and JUnit versions. \ No newline at end of file diff --git a/docs/install/repositories.md b/docs/install/repositories.md new file mode 100644 index 0000000..7d43566 --- /dev/null +++ b/docs/install/repositories.md @@ -0,0 +1,68 @@ +# JPF Source Repository Access # + +JPF sources are kept as [Mercurial](http://www.selenic.com/mercurial) repositories within the http://babelfish.arc.nasa.gov/hg/jpf directory. You need to clone the subrepositories (e.g. http://babelfish.arc.nasa.gov/hg/jpf/jpf-core) that you are interested in, **not** the root directory ../hg/jpf itself (which most likely will give you old subrepo revisions). + +We provide anonymous, public read access. If you want to push your changes back to the repository, and you are not a NASA Ames employee, you need to [obtain a JPF contributor account](wiki:about/account). + +Mercurial is a [Distributed Version Control System](http://betterexplained.com/articles/intro-to-distributed-version-control-illustrated/) (DVCS), like Git. If you are not familiar with this, it means "all repositories are created equal", and you have to read up a bit. The foremost authority is ["Mercurial: The Definite Guide"](http://hgbook.red-bean.com/). + +For the inpatient, we also provide a short [Mercurial primer](../devel/mercurial). + +## Command Line Access ## + +To check out the jpf-core use the mercurial command `clone`: + +~~~~~~~~ {.bash} +> cd ~/projects + +> hg clone http://babelfish.arc.nasa.gov/hg/jpf/jpf-core +destination directory: jpf-core +requesting all changes +... +added 71 changesets with 2045 changes to 1694 files +updating working directory +683 files updated, 0 files merged, 0 files removed, 0 files unresolved +~~~~~~~~ + +The same process can be repeating by substituting `jpf-core` with the [project](../projects/index) you are interested in. You can install the projects wherever you want, but you have to remember where you installed them for the subsequent [site.properties](../install/site-properties) configuration. + +To update your local repository, change to its directory and do `pull` (don't forget the `-u` option, or your working directories will not get updated) + +~~~~~~~~ {.bash} +> cd ~/projects/jpf-core +> hg pull -u +~~~~~~~~ + +If you want - and are allowed - to push back your changes, you use **`https://`**`babelfish.arc.nasa.gov/hg/jpf/` as the URL, which will require entering your user-name and password. Before pushing the changes you have to commit the changes from your working directory to your local repository. + +~~~~~~~~ {.bash} +> cd ~/projects/jpf-core +> hg commit -m "this commits to the local repository" +~~~~~~~~ + +The changes now can be pushed to the central repository using the following command + +~~~~~~~~ {.bash} +> hg push https://babelfish.arc.nasa.gov/hg/jpf/jpf-core +~~~~~~~~ + +## Mercurial Support within NetBeans ## + +There is no need to install any plugins, NetBeans is distributed with Mercurial support. + + +## Mercurial Plugin for Eclipse ## + +To work within Eclipse + +* Download and install the [MercurialEclipse](http://javaforge.com/project/HGE) plugin, which at the time of this writing is available from the update site: http://cbes.javaforge.com/update (the usual Eclipse spiel: **Help** -> **Install New Software...** -> **add site**, enter the update URL above) + +* In the eclipse menu: **File** -> **Import** -> **Mercurial** -> **Clone repository using Mercurial** -> **Next** + +* In the repository location, URL, specify http://babelfish.arc.nasa.gov/hg/jpf/jpf-core + +* Check the box for 'Search for .project files in clone and use them to create projects' + +* Click on **Finish** + +The steps listed above will clone the repository in your workspace. Right clicking on the project will show a 'Team' option that allows to perform all the version control operations. diff --git a/docs/install/requirements.md b/docs/install/requirements.md new file mode 100644 index 0000000..ccec451 --- /dev/null +++ b/docs/install/requirements.md @@ -0,0 +1,79 @@ +# System Requirements # + +## Java ## +Most of the JPF components, including the [jpf-core](../jpf-core/index), are pure Java applications. The minimal version is Java SE 8 (if you have to use JDK 1.7 or JDK 1.6 you have to check out the 'java-7' and 'java-1.6' branches of our repository, respectively), we generally advise to use the latest stable Java version that is available for your platform. You can find out about your java by running the following statement from the command line. + +~~~~~~~~ {.bash} +> java -version +java version "1.8.0_20" +... +~~~~~~~~ + +JPF is a resource hungry application. We recommend at least 2Gb of memory, and generally use a `-Xmx1024m` setting when launching Java. The disk footprint for most JPF projects is fairly small, the jpf-core takes about 40M when fully expanded with sources, compiled classes and jar files. The binary distribution (jar files) takes less than 1.5M. + +Some JPF projects do require 3rd party native executables (like DLLs) that are platform specific. Please refer to the specific project pages for details. + +### Java specifics for Windows ### +Make sure you have the JDK installed, otherwise there is no javac compiler available. + +In order to build JPF from a Windows Command Prompt (executing `ant.bat` from inside the respective JPF project directory), you have to set the `JAVA_HOME` environment variable. + +### Java specifics for OS X ### +On Mac OS X 10.10, Java 1.7 is default, but `/Applications/Utilities/Java Preferences.app` can change the setting. In some cases, it may be necessary to manually change the symlink that determines which version is default: + +~~~~~~~~ {.bash} +sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/Current +sudo ln -s 1.8 /System/Library/Frameworks/JavaVM.framework/Versions/Current +~~~~~~~~ + +## Mercurial (Version Control System) ## +If you want to download the JPF source repositories, you need to install the [Mercurial](http://mercurial.selenic.com/wiki/) distributed version control system on your machine, which requires [Python](http://www.python.org). If you are using a Windows machine, you can install [TortoiseHg](http://tortoisehg.bitbucket.org/), which provides a Windows Explorer extension and includes Python. + +On some Mac OS X systems, it may be necessary to set the `LC_ALL` and `LANG` environment variables for Mercurial to work correctly. + +in `~/.bashrc`: + +~~~~~~~~ {.bash} +export LC_ALL=en_US.UTF-8 +export LANG=en_US.UTF-8 +~~~~~~~~ + +in `~/.cshrc`: + +~~~~~~~~ {.bash} +setenv LC_ALL en_US.UTF-8 +setenv LANG en_US.UTF-8 +~~~~~~~~ + + +If you already have Eclipse installed, and want to download the source repositories from within the IDE, you need the [MercurialEclipse](http://javaforge.com/project/HGE) plugin, which you can install from this update-site: http://cbes.javaforge.com/update + +Note that NetBeans comes with Mercurial support by default. + + +## Apache Ant ## + +Although you can also build from Eclipse, we use [Apache Ant](http://ant.apache.org) as our primary build system. **Ant is no longer included in the jpf-core distribution** so you have to install it separately. Currently (as of Ant 1.9.3), this involves + + * getting Ant binaries e.g. from http://www.apache.org/dist/ant/binaries/ + * setting the `ANT_HOME` environment variable to the directory where you unpacked the binaries + * adding `ANT_HOME/bin` to your `PATH` environment variable + + +## JUnit ## + +Our Ant script (build.xml) includes a `test` target which uses [JUnit](http://junit.org) to run regression tests. **JUnit is no longer included in the jpf-core distribution**. For JUnit-4.11 installation involves the following steps + + * get junit-.jar and hamcrest-core-.jar, e.g. from the links on https://github.com/junit-team/junit/wiki/Download-and-Install + * add both jars to your `CLASSPATH` environment variable + + +## JPF IDE plugins ## + +JPF components come with project configurations for both [NetBeans](http://www.netbeans.org) and [Eclipse](http://www.eclipse.org), so you might want to use your favorite IDE. Since the JPF build process is [Ant](http://ant.apache.org)-based, NetBeans is generally a better fit because it is Ant-based and can make direct use of your JPF site configuration. + +If you want to install the [Eclipse plugin](./eclipse-jpf), you need an Eclipse version >= 3.5 (Galileo) **running under JavaSE-1.8**. Please see the [Installing the Eclipse JPF plugin](./eclipse-plugin) page for details. + +If you want to go with Eclipse and have to rebuild the JPF [Eclipse plugin](./eclipse-jpf), make sure you install the Eclipse Plugin Development Environment (PDE) from the respective Eclipse server. + +If you want to use the [NetBeans plugin](./netbeans-jpf), the minimal NetBeans version is 6.5. \ No newline at end of file diff --git a/docs/install/site-properties.md b/docs/install/site-properties.md new file mode 100644 index 0000000..691fa4d --- /dev/null +++ b/docs/install/site-properties.md @@ -0,0 +1,32 @@ +# Creating a site.properties file # + +The site.properties file tells JPF at startup time where to look for installed projects, so that it can add classpaths accordingly without you having to type off your fingers. It is a normal [Java properties](http://en.wikipedia.org/wiki/.properties) file, which supports a few additional things like key expansion. + +While you can tell JPF at startup time where to look for `site.properties`, we recommend using the default location, which is **`/.jpf/site.properties`**. If you don't know what value the standard Java system property `user.home` has on your machine, please run the attached Java program. On Unix systems, this is your home directory. + +Assuming that you installed your JPF projects under `/projects/jpf`, a typical `site.properties` looks like this: + +~~~~~~~~ {.bash} +# JPF site configuration + +jpf-core = ${user.home}/projects/jpf/jpf-core + +# numeric extension +jpf-numeric = ${user.home}/projects/jpf/jpf-numeric + +# annotation-based program properties extension +jpf-aprop = ${user.home}/projects/jpf/jpf-aprop + +extensions=${jpf-core},${jpf-aprop} + +#... and all your other installed projects +~~~~~~~~ + +If you are a Windows user, and you want to enter absolute pathnames, don't use unquoted backslashes '\' since the `java.util.Properties` parser would interpret these as special chars (like `"\n"`). You can use ordinary slashes '/' instead. To avoid drive letters, use system properties like `${user.home}`. + + +A sample site.properties file is attached to this page. Note that the "`${..}`" terms are automatically expanded by JPF, i.e. you do not have to enter explicit paths. + +Each installed project is defined by a "` = `" key/value pair. The project name is usually the same as the repository name. + +Note that we don't require anymore that all projects are in the extensions list, **but** jpf-core (or wherever your JPF core classes are) now needs to be in there. In fact, you probably want to have only `jpf-core` in `extensions`, and use the `@using ` for the other ones from either your project properties (jpf.properties, for project dependencies) or - usually - from your application properties (*.jpf) files. See [JPF configuration](../user/config) for details. \ No newline at end of file diff --git a/docs/install/snapshot.md b/docs/install/snapshot.md new file mode 100644 index 0000000..d7839c1 --- /dev/null +++ b/docs/install/snapshot.md @@ -0,0 +1,14 @@ +# Downloading Binary Snapshots # + + +Available binary snapshots are attached as *.zip archives to the [jpf-core](../jpf-core/index) page. Just click the on the download link and tell your browser where to store them on disk, which you need to remember for your subsequent [site.properties](../install/site-properties) configuration. We recommend putting all JPF modules under a single parent directory that holds the site.properties file: + +~~~~~~~~ {.bash} +jpf/ + site.properties + jpf-core/ + jpf-symbc/ + … +~~~~~~~~ + +Many JPF modules are still fast moving, so we recommend using the source repositories to stay up-to-date. Our policy is to only push changes to this server which pass all regression tests \ No newline at end of file diff --git a/docs/intro/classification.md b/docs/intro/classification.md new file mode 100644 index 0000000..667e755 --- /dev/null +++ b/docs/intro/classification.md @@ -0,0 +1,25 @@ +# JPF Key Features # + +By now, it should be clear that JPF is not just a model checker: it is a JVM that can be used for model checking. However, if you are familiar with formal methods, you might want to know what kind of model checking methods and features are supported. + +Some of the basic model checking traits are: + +* **Explicit State** model checking is JPF's standard mode of operation. It means JPF keeps track of concrete values of local variables, stackframes, heap objects and thread states. Other than the intentionally different scheduling behavior, JPF should produce the same results like a normal JVM. Of course it is slower (it is a JVM running on top of a JVM, doing a lot of additional work). + +* **Symbolic Execution** means that JPF can perform program execution with symbolic values obtained from how a certain variable was used along the current path of execution (e.g. `x>0 && x<43`). Moreover, JPF can even mix concrete and symbolic execution, or switch between them. Please see the Symbolic Pathfinder project documentation for details. + +* **State Matching** is a key mechanism to avoid unnecessary work. The execution state of a program mainly consists of heap and thread-stack snapshots. While JPF executes, it checks every new state if it already has seen an equal one, in which case there is no use to continue along the current execution path, and JPF can backtrack to the nearest non-explored non-deterministic choice. What variables contribute to state matching, and how state matching is performed can be controlled by the user. + +* **Backtracking** means that JPF can restore previous execution states, to see if there are unexplored choices left. For instance, if JPF reaches a program end state, it can walk backwards to find different possible scheduling sequences that have not been executed yet. While this theoretically can be achieved by re-executing the program from the beginning, backtracking is a much more efficient mechanism if state storage is optimized. + +* **Partial Order Reduction** is what JPF employs to minimize context switches between threads that do not result in interesting new program states. This is done on-the-fly, i.e. without prior analysis or annotation of the program, by examining which instructions can have inter-thread effects. While this is fast, it cannot handle the “diamond case”, since it cannot look ahead of the current execution. + +JPF's flexibility is achieved by an architecture that provides a large number of extension points, of which the most important ones are: + + * search strategies - to control in which order the state space is searched + * listeners - to monitor and interact with JPF execution (e.g. to check for new properties) + * native peers - to model libraries and execute code at the host VM level + * bytecode factories - to provide different execution models (like symbolic execution) + * publishers - to generate specific reports + +In general, flexibility through configuration is JPF's answer to the scalability problem of software model checking. \ No newline at end of file diff --git a/docs/intro/index.md b/docs/intro/index.md new file mode 100644 index 0000000..8fcec1f --- /dev/null +++ b/docs/intro/index.md @@ -0,0 +1,17 @@ +# Introduction # +JPF started as a software model checker, but nowadays, JPF is a runtime system with many different execution modes and extensions which go beyond model checking. All the various modes of JPF, while serving different purposes, used to verify Java programs by + + * detecting and explaining defects + * collecting "deep" runtime information like coverage metrics + * deducing interesting test vectors and creating corresponding test drivers + * and many more... + +Although JPF is mostly associated with software model checking, it can be applied in variety of ways. People often confuse this with testing, and indeed JPF's notion of model checking can be close to systematic testing. Below we use a simple example that illustrates the differences. + +Here is the outline of this section: + + * [What is JPF?](what_is_jpf) + * [Testing vs. Model Checking](testing_vs_model_checking) + * [Random value example](random_example) + * [Data race example](race_example) + * [JPF key features](classification) diff --git a/docs/intro/race_example.md b/docs/intro/race_example.md new file mode 100644 index 0000000..bb7074b --- /dev/null +++ b/docs/intro/race_example.md @@ -0,0 +1,105 @@ +# Example: Data Race # + +That's nice, but of course we also could have provoked the error in our random value example by using explicit loops instead of the `Random.nextInt()` calls, i.e. by explicitly enumerating all possible `a` and `b` values in our program. This would be typically done in a program that is a dedicated test driver, in a process which is called *systematic testing*. However, the program we want to verify might not be a test driver, and we might not even have the sources so that we could modify it accordingly. + +But the real show stopper for systematic testing lies within the instructions representing choices: at the application level, we might neither be aware of that there are choices, what the choice values are, nor be able to explicitly pick them. + +To demonstrate this point, let us look at a little concurrency example using two threads of execution. Quite obviously, the program produces different results depending on if line (2) or (4) gets executed first. But assuming we can't control what happens in (1) and (2), this time we cannot explicitly enumerate the choices - they are made by the system scheduler, i.e. outside of our application. + +~~~~~~~~ {.java} +public class Racer implements Runnable { + + int d = 42; + + public void run () { + doSomething(1000); // (1) + d = 0; // (2) + } + + public static void main (String[] args){ + Racer racer = new Racer(); + Thread t = new Thread(racer); + t.start(); + + doSomething(1000); // (3) + int c = 420 / racer.d; // (4) + System.out.println(c); + } + + static void doSomething (int n) { + // not very interesting.. + try { Thread.sleep(n); } catch (InterruptedException ix) {} + } +} +~~~~~~~~ + +Chances are, we don't encounter this defect at all during normal testing: + +~~~~~~~~ {.bash} +> java Racer +10 +> +~~~~~~~~ + +Not so with JPF. Being a real virtual machine, there is nothing we can't control. And being a different kind of a Java virtual machine, JPF recognizes that 'racer' is an object that is shared between two threads, and hence executes all possible statement sequences / scheduling combinations in which this object can be accessed. This time, we give the complete output, which also shows the trace (the execution history) that lead to the defect found by JPF: + +~~~~~~~~ {.bash} +> bin/jpf Racer +JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center +====================================================== system under test +application: /Users/pcmehlitz/tmp/Racer.java + +====================================================== search started: 5/24/07 12:32 AM +10 +10 + +====================================================== error #1 +gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty +java.lang.ArithmeticException: division by zero + at Racer.main(Racer.java:20) + +====================================================== trace #1 +------------------------------------------------------ transition #0 thread: 0 +gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main} + [insn w/o sources](282) + Racer.java:15 : Racer racer = new Racer(); + Racer.java:1 : public class Racer implements Runnable { + [insn w/o sources](1) + Racer.java:3 : int d = 42; + Racer.java:15 : Racer racer = new Racer(); + Racer.java:16 : Thread t = new Thread(racer); + [insn w/o sources](51) + Racer.java:16 : Thread t = new Thread(racer); + Racer.java:17 : t.start(); +------------------------------------------------------ transition #1 thread: 0 +gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main,Thread-0} + Racer.java:17 : t.start(); + Racer.java:19 : doSomething(1000); // (3) + Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} + [insn w/o sources](2) + Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} + Racer.java:7 : } + Racer.java:20 : int c = 420 / racer.d; // (4) +------------------------------------------------------ transition #2 thread: 1 +gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {main,>Thread-0} + Racer.java:10 : doSomething(1000); // (1) + Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} + [insn w/o sources](2) + Racer.java:6 : try { Thread.sleep(n); } catch (InterruptedException ix) {} + Racer.java:7 : } + Racer.java:11 : d = 0; // (2) +------------------------------------------------------ transition #3 thread: 1 +gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {main,>Thread-0} + Racer.java:11 : d = 0; // (2) + Racer.java:12 : } +------------------------------------------------------ transition #4 thread: 0 +gov.nasa.jpf.jvm.choice.ThreadChoiceFromSet {>main} + Racer.java:20 : int c = 420 / racer.d; // (4) + +====================================================== search finished: 5/24/07 12:32 AM +> +~~~~~~~~ + +Looking at the output created by our test program, we see the result `"10"` printed twice, but that doesn't confuse us anymore. From our first example, we know this simply means that JPF first tried two scheduling sequences that normally terminated the program without provoking the defect, before finally picking the one that causes the error. + +It still might be a bit confusing that the printed trace contains some source lines twice. Ignoring the details of its choice generation mechanism, this is caused by JPF executing bytecode instructions, not source lines, and a single source line can easily get translated into a number of bytecode instructions. This would go away if we configure JPF so that it reports the executed bytecode, but at the cost of much larger trace that is harder to read. What is more interesting is that JPF tells us about the thread choices it made in each transition (the lines starting with `gov.nasa.jpf.jvm.ThreadChoice..`). diff --git a/docs/intro/random_example.md b/docs/intro/random_example.md new file mode 100644 index 0000000..3499e9f --- /dev/null +++ b/docs/intro/random_example.md @@ -0,0 +1,95 @@ +# Example: `java.util.Random` # + +We start with a simple example that uses java.util.Random. Consider the following program that obtains two random values in (2) and (3), and then performs some computation (4) with them. + +~~~~~~~~ {.java} +import java.util.Random; + +public class Rand { + public static void main (String[] args) { + Random random = new Random(42); // (1) + + int a = random.nextInt(2); // (2) + System.out.println("a=" + a); + + //... lots of code here + + int b = random.nextInt(3); // (3) + System.out.println(" b=" + b); + + int c = a/(b+a -2); // (4) + System.out.println(" c=" + c); + } +} +~~~~~~~~ + + +## Testing ## + +Executing this program with a normal Java VM yields something like the following output. If we don't provide an explicit seed when creating the Random object in (1), the result is going to differ between runs, but every run will choose just a single `a` and `b` value (i.e. print just a single `"a=.."` and `"b=.."` line. + +~~~~~~~~ {.java} +> java Rand +a=1 + b=0 + c=-1 +> +~~~~~~~~ + +Let's look at a graphical representation of all the ways our program could be executed, and how it actually was executed in our test run. The nodes of the graph represent *program states*, and the edges *transitions* the execution could take from a certain state. + +![Figure 1: Random example](../graphics/sw-model-checking.svg){align=center width=700} + +## Model Checking ## + +Enter JPF - not much different results if we start JPF as a plain 'java' replacement. The only difference is that it (a) takes longer to complete, and (b) tells us something about a "search", which hints on that something more than in our test run is going on + +~~~~~~~~ {.bash} +> bin/jpf Rand +JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center +====================================================== system under test +application: /Users/pcmehlitz/tmp/Rand.java + +====================================================== search started: 5/23/07 11:48 PM +a=1 + b=0 + c=-1 + +====================================================== results +no errors detected + +====================================================== search finished: 5/23/07 11:48 PM +> +~~~~~~~~ + +What is this "search" supposed to mean? Looking at source line (4) we realize that there is a potential problem: for certain `a` and `b` values, this expression can cause a division by zero `ArithmeticException`. Depending on the random seed used in (1), it's quite possible we would never encounter this case if we run (i.e. test) the program with a normal JVM. + +Re-enter JPF - but this time we tell it to not only consider single values for `a` and `b`, but look at all possible choices: + +~~~~~~~~ {.bash} +> bin/jpf +cg.enumerate_random=true Rand +JavaPathfinder v4.1 - (C) 1999-2007 RIACS/NASA Ames Research Center +====================================================== system under test +application: /Users/pcmehlitz/tmp/Rand.java + +====================================================== search started: 5/23/07 11:49 PM +a=0 + b=0 + c=0 + b=1 + c=0 + b=2 + +====================================================== error #1 +gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty +java.lang.ArithmeticException: division by zero + at Rand.main(Rand.java:15) +.... +> +~~~~~~~~ + +What has happened? By specifying "+vm.enumerate_random=true" we told JPF to consider all possible values for expressions (2) and (3). JPF starts with `"a=0"`, then picks `"b=0"`, which yields a valid `"c=0"` value. But instead of terminating like a normal VM, JPF recognized that there are more choices left, so it backtracks to (3) and picks `"b=1"`. Again, no problem here with computing `"c=0"`. Back to (3), JPF now tries `"b=2"`, which of course spells disaster for our little program when executing (4), as can be seen by the following error report. + +Here is a graphical representation of this search process. It should be noted that JPF per default only runs up to the point where it finds an error or there are no more choices left to explore. But if we would somehow fix the `"a=0,b=2"` case, JPF would still find the `"a=1,b=1"` case in the next run, since it systematically tries all choices. No matter what error it finds, JPF also keeps the complete trace (execution path) how it got to this error (denoted by the red arrows), which means we don't have to debug the program to find out. + +![Figure 2: Random example](../graphics/sw-model-checking-2.svg){align=center width=450} diff --git a/docs/intro/testing_vs_model_checking.md b/docs/intro/testing_vs_model_checking.md new file mode 100644 index 0000000..56b41d5 --- /dev/null +++ b/docs/intro/testing_vs_model_checking.md @@ -0,0 +1,28 @@ +# Testing vs. Model Checking # + +So what JPF does is test our program for defects? No, it usually does more, at least when used as a model checker. How does testing differ from model checking? + +Software testing is an empirical set of techniques where you execute your program with a number of inputs in order to find out if it behaves correctly. This comes with two parts that involve the right choices: test input and test oracle. + +![Figure 1: Testing](../graphics/states-testing.svg){align=center} + +Testing techniques differ on how we choose the input (random, "interesting" problem domain values like corner cases etc.), and on how much knowledge about the SUT and its execution environment we assume (black/grey/white box), which especially affects how we can define and check correct behavior. This involves a lot of educated guesses, or as Edsger Dijkstra has put it: "program testing can at best show the presence of errors but never their absence". We usually compensate this by performing "enough" tests - which would be the next guess. Testing complex systems can easily turn into finding a needle in a haystack. If you are a good tester, you make the right guesses and hit the defect that is inevitably there. If not, don't worry - your users will find it later. + +![Figure 2: Model checking](../graphics/states-mc.svg){align=center} + +[Model Checking](http://en.wikipedia.org/wiki/Model_checking) as a [Formal Method](http://en.wikipedia.org/wiki/Formal_methods) does not depend on guesses. At least as the theory goes, if there is a violation of a given specification, model checking will find it. Model checking is supposed to be a rigorous method that exhaustively explores all possible SUT behaviors. + +To illustrate this, look at the [Random value example](random_example), which shows how testing differs from model checking if we have a program that uses a sequence of random values: the test always processes just one set of values at a time, and we have little control over which ones. Model checking doesn't stop until it has checked all data combinations or has found an error. + +With the random example, we can at least see the choices in our program. Consider a concurrent program, such as [Data race example](race_example) - do you know where the operating system switches between threads? All we know is that different scheduling sequences can lead to different program behavior (e.g. if there are data races), but there is little we can do in our tests to force scheduling variation. There are program/test spec combinations which are "untestable". Being a virtual machine, our software model checker doesn't suffer the same fate - it has complete control over all threads of our program, and can execute all scheduling combinations. + +![Figure 3: Threads interleaving](../graphics/interleavings.svg){align=center width=550} + +That is the theory. In reality "all possible" can be a pretty large number - too large for existing computing resources or our patience. Just assume the number of different scheduling sequences of a program consisting of N threads P,,1,, .. P,,N,, that each have n,,i,, atomic instruction sequences. + +For 2 threads with 2 atomic sections each this gives us 6 different scheduling combinations. For 8 sections the result is 12870, 16 sections yield 601080390 - that is why it is called *state explosion*. Software model checking has a scalability problem, even more so than model checking of hardware, since programs usually have a lot more states. + +There are several things we can do. First, we can optimize the model checker, which is simply an engineering feat. Next, we can find program states which are equivalent with respect to the properties we are checking, which can be done with various degrees of abstractions and value representations. Last, we can try to get to the defect first, before we run out of time or memory. But this is where the boundary between testing and model checking becomes blurred, as it involves things like heuristics about interesting input values or system behaviors, and these heuristics tend to drop reachable program states. + +JPF does all of the above to curb the state space explosion, and most things are configured instead of hardwired, so you don't depend on built-in heuristics. But no matter how much we shrink the state space, JPF can still observe a lot more about the program execution than normal tests (i.e. we can be more precise with our oracles), and it still knows about the execution history in case we find a defect, which is always just the first part - we also need to understand it so that it can be fixed eventually. + diff --git a/docs/intro/what_is_jpf.md b/docs/intro/what_is_jpf.md new file mode 100644 index 0000000..e8a5ce2 --- /dev/null +++ b/docs/intro/what_is_jpf.md @@ -0,0 +1,44 @@ +# What is JPF? # + +That depends on how you configure it. +First and foremost, there is no single, monolithic JPF - it is a runtime configured combination of different components. The project *jpf-core* is the essential component that constitutes the core structure of JPF. +Here we explain what *jpf-core* is. + + +## The Core : a VM that supports Model Checking ## + +![Figure 1: High level view of JPF](../graphics/jpf-basic.svg){align=center width=400} + +The JPF core is a Virtual Machine (VM) for Java™ bytecode. That means that JPF is a program which executes the system under test (SUT). The VM of JPF is able to handle bytecode instructions that are created by a standard Java compiler. While execution semantics of Java bytecodes are clearly defined in [Sun's Java virtual machine specifications](http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html/), we have little hardwired semantics in JPF - the VM instruction set is represented by a set of classes that can be replaced. +JPF is a special VM. JPF itself is written in Java, so it is not as fast as your normal Java. That implies that JPF is VM which is running on top of another VM. + +As JPF executes the SUT, it checks for certain properties which are given to JPF as input. Some of the properties that can be checked by JPF are unhandled exceptions, deadlocks, and user-defined assertions which are used to test properties of the code's behavior. +JPF gets back to you with a report that says if the properties hold and/or which verification artifacts have been created by JPF for further analysis (like test cases). + +JPF (theoretically) explores *all* potential executions in a systematic way. In contrast, an ordinary JVM executes the code in only one possible way. +Basically, JPF can identify points, which represent *execution choices*, in your program from which the execution could proceed differently. Then it systematically explores all of them. +Typical execution choices are different scheduling sequences or random values, but JPF allows you to introduce your own type of choices such as user input or state machine events. + +The number of paths can grow out of hand, and it usually will. This is known as the most challenging problem in software model checking referred to as *state space explosion problem*. +JPF uses different ways to mitigate this problem. The first line of defense employed by JPF is *state matching*: each time JPF reaches a choice point, it checks if it has already seen a similar program state, in which case it can safely abandon this path, *backtrack* to a previous choice point that has still unexplored choices, and proceed from there. That's right, JPF can restore program states, which is like telling a debugger "go back 100 instructions". + +So what are these features used for? Normally to find defects in the SUT, but what kind of defects? By now you know the answer: it depends on how you configure JPF. By default, the core checks for properties that can be identified by the VM without you having to specify them: deadlocks and unhandled exceptions (which also covers Java `assert` expressions). We call these *non-functional* properties, and no application should violate them. But JPF doesn't stop there - you can define your own properties, which is mostly done with so called *listeners*, little "plugins" that let you closely monitor all actions taken by JPF, like executing single instructions, creating objects, reaching a new program state and many more. An example of a property implemented in the form of a listener is a race detector, which identifies unsynchronized access to shared variables in concurrent programs (the JPF core comes with two of them). + +One additional feature that comes in handy in case JPF finds a defect is the complete execution history that leads to the defect, including every executed bytecode instruction. We call this a program *trace*, and it is invaluable to find out what really caused the defect. Think of a deadlock - usually there is not much you can directly deduce from a snapshot of call stacks. + +All this explains why JPF is called "a debugger toolbox on steroids": first it automatically executes your program in all possible ways to find defects you don't even know about yet, then it explains you what caused these defects. + +## Caveat : not a lightweight tool ## + +Of course that is the ideal world. In reality, this can require quite a lot of configuration and even some programming. JPF is not a "black box" tool like a compiler, and the learning curve can be steep. What makes this worse is that JPF cannot execute *native code* which is implemented in a language other than Java but invoked from Java applications. +Not because it doesn't know how to do that, but because it often doesn't make sense: native code like system calls to write to a file cannot easily be reverted - JPF would loose its capability to match or backtrack program states. But of course there is a remedy, and it is configurable: *native peers* and *model classes*. Native peers are classes that hold methods that are executed in lieu of real native methods. This code is executed by the real Java VM, not JPF, hence it can also speed up things. Model classes are simple replacements of standard classes, like `java.lang.Thread` that provide alternatives for native methods which are fully observable and backtrackable. + +If you are familiar with Java implementations, you know about the humongous proportions of the included libraries, and hence it is obvious that we cannot handle all of them, at least not yet. There is no theoretical limit, and implementing missing library methods is usually pretty easy, but you should be prepared to encounter `UnsatisfiedLinkErrors` and such if you let JPF loose on large production systems. Notorious white spots are `java.io` and `java.net`, but there are people working on it. Who knows, maybe you are interested to join the effort - JPF is open sourced and there is nothing you can't see. We now have more than two dozen major collaborators in industry, government and academia around the world. + +So what makes it worthwhile to invest in JPF? After all, it is a heavyweight tool, not a quick and simple bug finder. First, if you are looking for a research platform to try out your new software verification ideas, chances are you can get along with JPF in a fraction of time compared to native production VMs, which are typically optimized towards speed and care little about extensibility or observability. + +The second answer is that - as of this writing - there are bugs *only* JPF can find (before the fact, that is), and there are more and more Java applications that cannot afford to learn about these bugs after the fact. JPF is a tool for mission critical applications, where failure is not an option. No surprise it was started by NASA. + + + diff --git a/docs/jpf-core/AssertionProperty.md b/docs/jpf-core/AssertionProperty.md new file mode 100644 index 0000000..21c49e8 --- /dev/null +++ b/docs/jpf-core/AssertionProperty.md @@ -0,0 +1,88 @@ +# AssertionProperty # + +This listener adds some special capabilities for `java.lang.AssertionError` processing: + + * report `AssertionErrors` that are otherwise carelessly caught in `... catch (Throwable t) {..}` clauses + * ignore AssertionErrors if `ap.go_on` is set + +`AssertionErrors` differ a bit from other exceptions - they should never be handled, and they usually represent functional properties (as opposed to non-functionals like `NullPointerExceptions` and `ArithmeticExceptions`). Consequently, it can be regarded as an error if an `AssertionError` is swallowed by a 'catch-all', and it is at least an option to ignore an unhandled `AssertionError`, e.g. to see what non-functional defects - if any - it might cause downstream. + +### Example 1: catch-all ### + +~~~~~~~~ {.java} +public class CatchAll { + public static void main(String[] args){ + try { + int d = 42; + //.. some stuff + assert d > 50 : "d below threshold"; + int x = d - 50; + //.. some more stuff + } catch (Throwable t) { // bad + // ..I'm careless + } + } +} +~~~~~~~~ + +Checked with: + +~~~~~~~~ {.bash} +>jpf +listener=.listener.AssertionProperty CatchAll +~~~~~~~~ + +Produces: + +~~~~~~~~ +JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center +====================================================== system under test +application: CatchAll.java + +====================================================== search started: 10/13/09 1:33 PM + +====================================================== error #1 +gov.nasa.jpf.listener.AssertionProperty +d below threshold +... +~~~~~~~~ + + +### Example 2: go-on ### + +~~~~~~~~ {.java} +public class GoOn { + public static void main (String[] args){ + int d = 42; + // lots of computations... + assert d > 50 : "d below threshold"; + int x = Math.max(0, d - 50); + // lots of more computations... + int y = 42000 / x; + } +} +~~~~~~~~ + +Checked with + +~~~~~~~~ {.bash} +>jpf +listener=.listener.AssertionProperty +ap.go_on GoOn +~~~~~~~~ + +Produces: + +~~~~~~~~ {.bash} +JavaPathfinder v5.0 - (C) 1999-2007 RIACS/NASA Ames Research Center + +====================================================== system under test +application: GoOn.java + +====================================================== search started: 10/13/09 1:59 PM +WARNING - AssertionError: d below threshold + at GoOn.main(GoOn.java:5) + +====================================================== error #1 +gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty +java.lang.ArithmeticException: division by zero + at GoOn.main(GoOn.java:8) +... +~~~~~~~~ diff --git a/docs/jpf-core/ErrorTraceGenerator.md b/docs/jpf-core/ErrorTraceGenerator.md new file mode 100644 index 0000000..0edf13c --- /dev/null +++ b/docs/jpf-core/ErrorTraceGenerator.md @@ -0,0 +1,32 @@ +## Error Trace Generator ## + +This is a listener to output a lightweight error trace. It prints the instructions at POR boundaries or points where there are multiple choices. An example is shown below. + +~~~~~~~~ + +====================### Lightweight Error Trace ###======================= + + +Length of Error Trace: 35 +--------------------------------------------------- Thread1 + Event.wait_for_event(oldclassic.java:79) + wait(); +--------------------------------------------------- Thread2 + SecondTask.run(oldclassic.java:129) + if (count == event2.count) { // ditto +--------------------------------------------------- Thread2 + SecondTask.run(oldclassic.java:127) + event1.signal_event(); // updates event1.count +--------------------------------------------------- Thread2 + SecondTask.run(oldclassic.java:133) + count = event2.count; // ditto +--------------------------------------------------- Thread1 + FirstTask.run(oldclassic.java:103) + event1.wait_for_event(); +--------------------------------------------------- Thread1 + +~~~~~~~~ + +Configuration: **+listener=gov.nasa.jpf.listener.ErrorTraceGenerator** + +Note the Error trace generator does not have the same memory bottlenecks as **report.console.property_violation=trace** that stores every bytecode instruction executed along the path from the start of the program to the error state. The error trace generator dynamically recreates the counterexample by tracing back to the start from the error state. The head of the error trace (list shown in the example) represents the last instruction in the error trace while the tail represents the first instruction. \ No newline at end of file diff --git a/docs/jpf-core/ExceptionInjector.md b/docs/jpf-core/ExceptionInjector.md new file mode 100644 index 0000000..4ab7766 --- /dev/null +++ b/docs/jpf-core/ExceptionInjector.md @@ -0,0 +1,105 @@ +# ExceptionInjector # + +The ExceptionInjector is a listener that can throw user configured exceptions at arbitrary program locations. The main purpose is to ease the testing of exception handler code that would otherwise hard to reach, e.g. because it is not clear if/how an exception could be thrown in 3rd party code. + +## Properties ## + +~~~~~~~~ {.bash} +**ei.exception** = ;... \ + + := '@' \ + + := [[string-literal]('(') ')'] \ + + := ':'line | '.'[ [[BR](':'line])] +~~~~~~~~ + +Relative line numbers count from the first executable statement in the method body. They are mostly used to have tests that are more robust against changes in the target source file. + +If a method is given without a line offset, the exception is thrown before executing INVOKE instructions that call the specified method. + +If a line is specified (either absolute or method-body relative), the exception is thrown before executing the associated bytecode at this line. + +If more than one exception specification is given, these need to be separated by semicolons ';' (commas cannot be used because they can appear within argument type lists of the target method). + +Method argument types have to be specified the same way as they are reported by 'javap', i.e. with fully qualified type names in dot notation (e.g. "`foo(java.lang.String,int[])`"). Return types can be omitted. + +`ei.throw_first` [`boolean`] - if true, throw exception on first bytecode instruction associated with the given (absolute or relative) source line. If false, throw on last associated bytecode instruction + + +## Examples ## + +### (1) throw exception on absolute line 42 in xyz.MyClass: ### + +The application property file + +~~~~~~~~ {.bash} +target = yxz.MyClass +ei.exception = ArithmeticException@xyz.MyClass:42 +~~~~~~~~ +on file +~~~~~~~~ {.java} +1: package x.y.z; + .. + public class MyClass { + .. + try { + .. +42: int z = x / y; + .. + } catch (ArithmeticException ax){ + // the handler code to test + } + .. +~~~~~~~~ + +will throw an ArithmeticException on line 42 regardless of the 'x' and 'y' values. + +### (2) throw a `Zapp("gotcha")` exception on (relative) line 2 in method body `xyz.MyClass.foo()` ### + +The application property file + +~~~~~~~~ {.bash} +target = yxz.MyClass +ei.exception = Zapp("gotcha")@xyz.MyClass.foo(int[]):2 +~~~~~~~~ +on file +~~~~~~~~ {.java} + package x.y.z; + .. + public class MyClass { + .. + void foo (int[] whatever) { + // some comment (doesn't count for line offsets) ++0: int n = .. // first statement line in foo() ++1: // some more comment (does count for line offsets) ++2: doSomething(n); // can throw a Zapp exception + .. +~~~~~~~~ +will throw a Zapp("gotcha") exception on relative line 2 of method body xyz.MyClass.foo(). Note that the line offset counts from the first executable statement line within foo(). + + +### (3) throw an `IOException` when calling `File.createTempFile()` ### +The application property file + +~~~~~~~~ {.bash} +target = yxz.MyClass +ei.exception = java.io.IOException@java.io.File.createTempFile(java.lang.String,java.lang.String) +~~~~~~~~ + +will throw an exception on the first call of File.createTempFile(), regardless of where this occurs and what the parameters to the call are + +~~~~~~~~ {.java} +1: package x.y.z; + .. + public class MyClass { + .. + try { + .. + File tmp = File.createTempFile(prefix,suffix); + .. + } catch (IOException iox) { + // the handler code to test + } + .. +~~~~~~~~ diff --git a/docs/jpf-core/IdleFilter.md b/docs/jpf-core/IdleFilter.md new file mode 100644 index 0000000..03c6e98 --- /dev/null +++ b/docs/jpf-core/IdleFilter.md @@ -0,0 +1,99 @@ +# IdleFilter # + +The `gov.nasa.jpf.listener.IdleFilter` is a listener that can be used to close state spaces with loops. Consider a simple "busy waiting" loop + +~~~~~~~~ {.java} +for (long l=0; l<10000000; l++); +~~~~~~~~ + +While not a good thing to do in general, it is benign if executed in a normal VM. For JPF, it causes trouble because it adds a lot of useless steps to the stored path, and slows down execution considerably. + +In addition, people who expect JPF to match states can get surprised by programs like + +~~~~~~~~ {.java} +while (true){ + // no transition break in here +} +~~~~~~~~ +not being state matched, and hence not terminating (it wouldn't terminate in a normal VM either). + +`IdleFilter` is a little tool to deal with such (bad) loops. It counts the number of back-jumps it encounters within the same thread and stackframe, and if this number exceeds a configured threshold it takes one of the following actions: + + * warn - just prints out a warning that we have a suspicious loop + * break - breaks the transition at the back-jump `goto` instruction, to allow state matching + * prune - sets the transition ignored, i.e. prunes the search tree + * jump - skips the back-jump. This is the most dangerous action since you better make sure the loop does not contain side-effects your program depends on. + + +### Properties ### +Consequently, there are two options: + + * `idle.max_backjumps = \` : max number of back-jumps that triggers the configured action (default 500) + * `idle.action = warn|break|prune|jump` : action to take when number of back-jumps exceeds threshold + +### Examples ### + +**(1)** The test program + +~~~~~~~~ {.java} +... +public void testBreak () { + int y = 4; + int x = 0; + + while (x != y) { // JPF should state match on the backjump + x = x + 1; + if (x > 3) { + x = 0; + } + } +} +~~~~~~~~ + +would never terminate under JPF or a host VM. Running it with + +~~~~~~~~ {.bash} +> bin/jpf +listener=.listener.IdleFilter +idle.action=break ... +~~~~~~~~ + +does terminate due to state matching and produces the following report + +~~~~~~~~ {.bash} +... +====================================================== search started: 4/8/10 4:14 PM +[WARNING] IdleFilter breaks transition on suspicious loop in thread: main + at gov.nasa.jpf.test.mc.basic.IdleLoopTest.testBreak(gov/nasa/jpf/test/mc/basic/IdleLoopTest.java:42) +... +====================================================== results +no errors detected +~~~~~~~~ + +----- +**(2)** The following program would execute a long time under JPF + +~~~~~~~~ {.java} +... +public void testJump () { + for (int i=0; i<1000000; i++){ + //... + } + + System.out.println("Ok, jumped past loop"); +} +~~~~~~~~ + +If we run it with + +~~~~~~~~ {.bash} +> bin/jpf +listener=.listener.IdleFilter +idle.action=jump ... +~~~~~~~~ + +JPF comes back quickly with the result + +~~~~~~~~ {.bash} +====================================================== search started: 4/8/10 4:20 PM +[WARNING] IdleFilter jumped past loop in: main + at gov.nasa.jpf.test.mc.basic.IdleLoopTest.testJump(gov/nasa/jpf/test/mc/basic/IdleLoopTest.java:74) +Ok, jumped past loop +... +~~~~~~~~ diff --git a/docs/jpf-core/index.md b/docs/jpf-core/index.md new file mode 100644 index 0000000..28fda0e --- /dev/null +++ b/docs/jpf-core/index.md @@ -0,0 +1,43 @@ +# jpf-core # +This is the basis for all JPF projects, i.e. you always need to install it. jpf-core contains the basic VM and model checking infrastructure, and can be used to check for concurrency defects like deadlocks, and unhandled exceptions like `NullPointerExceptions` and `AssertionErrors`. + + +## Repository ## +The Mercurial repository is on http://babelfish.arc.nasa.gov/hg/jpf/jpf-core + +## Properties ## +jpf-core supports two rather generic properties, which are configured by default: + + * `gov.nasa.jpf.jvm.NoUncaughtExceptionsProperty` + * `gov.nasa.jpf.jvm.NotDeadlockedProperty` + +There is no need to parameterize any of them. `NoUncaughtExceptionsProperty` covers all `Throwable` objects that are not handled within the application, i.e. would terminate the process. + +Some of the listeners (like `PreciseRaceDetector`) are `ListenerAdapter` instances, i.e. work as more specific Property implementations. + +## Listeners ## +jpf-core includes a variety of [listeners](../devel/listener) that fall into three major categories: + + * program properties + * execution monitoring + * execution control + +Some of the main listeners are + + * [AssertionProperty](./AssertionProperty) + * [IdleFilter](./IdleFilter) + * [ExceptionInjector](./ExceptionInjector) + +## Properties ## +jpf-core uses many JPF properties, you can find most of them in the `defaults.properties` file. The following ones are of interest for users + + * `listener` - a comma separated list of class names representing listeners that should be automatically instantiated and registered during JPF startup + * `listener.autoload` - a comma separated list of annotation types. If JPF encounters such an annotation in one of the analyzed classes at runtime, it automatically loads and registered the associated listener + * `listener.` - class name of the listener associated with `` + * `vm.insn_factory.class` - class name of a [`BytecodeInstructionFactory`](../devel/bytecode_factory), e.g. to switch to the symbolic execution mode or to use specific bytecode implementations for checking numeric properties + * `vm.halt_on_throw (true|false)` - tells JPF if it should try to find a handler if it encounters an exception in the analyzed program (useful to avoid masking exceptions within handlers) + * [`cg.randomize_choices`](../user/config/random) `(random|path|def)` - tells JPF if it should randomize the order of choices for each [`ChoiceGenerator`](../devel/choicegenerator), to avoid degenerated searches (e.g. always indexing with the main thread in scheduling choices). + * `report.console.property_violation` - comma separated list of topics that should be printed by JPF if it detects an error. Possible values include + - `error` error description + - `snapshot` thread stacks + - `trace` instruction/statement trace (can be long and memory-expensive) \ No newline at end of file diff --git a/docs/papers/chicago-author-date.csl b/docs/papers/chicago-author-date.csl new file mode 100644 index 0000000..595235f --- /dev/null +++ b/docs/papers/chicago-author-date.csl @@ -0,0 +1,549 @@ + + diff --git a/docs/papers/index.md b/docs/papers/index.md new file mode 100644 index 0000000..87fb93a --- /dev/null +++ b/docs/papers/index.md @@ -0,0 +1,133 @@ +# Related Publications # + +JPF has been both a research target and a system in use for a number of years. A broad collection of papers and reports is available, including the following (incomplete) list + +> **Notes:** some of the older papers now have mostly historical relevance. JPF has undergone a lot of changes since 2000. If you need more recent information, especially about the design and usage of current +JPF versions, please consult the documentation. + + +--- +bibliography: ./references.bib +csl: ./chicago-author-date.csl +... + +## Core Papers ## + +@visser:2003 + +@lerda:2001 + +## JPF Infrastructure and Features ## + +@shafiei:breugel:2014 + +@nshafiei:2012 + +@kulikov:2010 + +## Testing and Symbolic Execution ## + +@indradeep:2013 + +@person:2008 + +@pasareanu:2008 + +@visser:2004 + +@pasareanu:2004 + +@artho:2003 + +@khurshid:2003 + +## Heuristic Search ## + +@groce:2004 + +@groce:2002 + +@groce:visser:2002 + +## Verification of Networked Software ## + +@shafiei:2014 + +@artho:2011 + +@artho:2009 + +@artho:2008 + +## Explaining Counter Examples ## + +@grove:2003 + +## Applying Java PathFinder ## + +@shafiei:2013 + +@stergiopoulos:2012 + +@mehlitz:2008 + +@penix:2005 + +@giannakopoulou:2004 + +@brat:2004 + +@bordini:2003 + + +## Misc ## + +@havelund:2007 + +@mansouri:2007 + +@havelund:2002 + +@pasareanu:dwyer:2003 + +@brat:2001 + +@visser:park:2000 + +@havelund:2000 + +@havelund:1999 + +@havelund:skakkebaek:1999 + +@havelund:Pressburger:1998 + +## Papers from Darko Marinov's group ## + +@gligoric:2010 + +@gligoric:jagannath:2010 + +@lauterburg:2010 + +@sobeih:2010 + +@lauterburg:2009 + +@gligoric:2009 + +@damorim:2008 + +@lauterburg:2008 + +@gvero:2008 + +@damorim:2007 + +@zhou:2007 + +@damorim:2006 + +@damorim:pacheco:2006 + +## References ## \ No newline at end of file diff --git a/docs/papers/references.bib b/docs/papers/references.bib new file mode 100644 index 0000000..698195f --- /dev/null +++ b/docs/papers/references.bib @@ -0,0 +1,636 @@ +@article{visser:2003, + author = {Visser, Willem and Havelund, Klaus and Brat, Guillaume and Park, Seungjoon and Lerda, Flavio}, + title = "{M}odel {C}hecking {P}rograms", + journal = {Automated Software Engineering}, + volume = {10}, + number = {2}, + month = {April}, + year = {2003}, + pages = {203--232}, + publisher = {Kluwer Academic Publishers}, + url = "http://dl.acm.org/citation.cfm?id=641186" + } + +@inproceedings{lerda:2001, + author = {Lerda, Flavio and Visser, Willem}, + title = {Addressing Dynamic Issues of Program Model Checking}, + booktitle = {Proceedings of the 8th International SPIN Workshop on Model Checking of Software}, + year = {2001}, + pages = {80--102}, + publisher = {Springer}, + url = "http://dl.acm.org/citation.cfm?id=380921.380931", +} + +@inproceedings{khurshid:2003, + author = {Sarfraz Khurshid and Corina S. P\v{a}s\v{a}reanu and Willem Visser}, + title = {Generalized Symbolic Execution for Model Checking and Testing}, + booktitle = {Proceedings of the Ninth International Conference on Tools and Algorithms for the Construction and Analysis of Systems}, + year = {2003}, + pages = {553--568}, + publisher = {Springer}, + url = "http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.8.8862" +} + +@article{visser:2004, + author = {Visser, Willem and P\v{a}s\v{a}reanu, Corina S. and Khurshid, Sarfraz}, + title = {Test Input Generation with Java PathFinder}, + journal = {Proceedings of International Symposium on Software Testing and Analysis}, + volume = {29}, + number = {4}, + month = jul, + year = {2004}, + pages = {97--107}, + publisher = {ACM}, + url = "http://dl.acm.org/citation.cfm?id=1007526", +} + +@article{pasareanu:2004, +year={2004}, +volume={2989}, +series={Lecture Notes in Computer Science}, +title={Verification of Java Programs Using Symbolic Execution and Invariant Generation}, +url={http://link.springer.com/chapter/10.1007%2F978-3-540-24732-6_13#}, +publisher={Springer}, +author={Păsăreanu, Corina S. and Visser, Willem}, +pages={164-181}, +} + +@inproceedings{person:2008, + author = {Person, Suzette and Dwyer, Matthew B. and Elbaum, Sebastian and P\v{a}s\v{a}reanu, Corina S.}, + title = {Differential Symbolic Execution}, + booktitle = {Proceedings of the 16th {ACM} {SIGSOFT} International Symposium on Foundations of Software Engineering}, + year = {2008}, + pages = {226--237}, + url = {http://doi.acm.org/10.1145/1453101.1453131}, + publisher = {ACM}, + } + +@inproceedings{pasareanu:2008, + author = {Corina S. P\v{a}s\v{a}reanu and + Peter C. Mehlitz and + David H. Bushnell and + Karen Gundy{-}Burlet and + Michael R. Lowry and + Suzette Person and + Mark Pape}, + title = {Combining unit-level symbolic execution and system-level concrete + execution for testing {NASA} software}, + booktitle = {Proceedings of the {ACM} {SIGSOFT} International Symposium on Software + Testing and Analysis}, + pages = {15--26}, + year = {2008}, + url = {http://doi.acm.org/10.1145/1390630.1390635}, +} + +@inproceedings{pasareanu:2007, + author = {Corina S. P\v{a}s\v{a}reanu and + Willem Visser}, + title = {Symbolic Execution and Model Checking for Testing}, + booktitle = {Hardware and Software: Verification and Testing, Third International + Haifa Verification Conference}, + pages = {17--18}, + year = {2007}, + url = {http://dx.doi.org/10.1007/978-3-540-77966-7_5}, +} + +@inproceedings{artho:2003, + author = {Cyrille Artho and + Doron Drusinsky and + Allen Goldberg and + Klaus Havelund and + Michael R. Lowry and + Corina S. P\v{a}s\v{a}reanu and + Grigore Rosu and + Willem Visser}, + title = {Experiments with Test Case Generation and Runtime Analysis}, + booktitle = {Abstract State Machines, Advances in Theory and Practice}, + pages = {87--107}, + year = {2003}, + url = {http://dx.doi.org/10.1007/3-540-36498-6_5}, +} + +@article{groce:2004, + author = {Alex Groce and + Willem Visser}, + title = {Heuristics for model checking Java programs}, + journal = {International Journal on Software Tools for Technology Transfer}, + volume = {6}, + number = {4}, + pages = {260--276}, + year = {2004}, + url = {http://dx.doi.org/10.1007/s10009-003-0130-9}, +} + +@inproceedings{groce:2002, + author = {Alex Groce and + Willem Visser}, + title = {Model checking Java programs using structural heuristics}, + booktitle = {Proceedings of International Symposium on Software Testing and Analysis}, + pages = {12--21}, + year = {2002}, + url = {http://doi.acm.org/10.1145/566172.566175}, +} + +@inproceedings{groce:visser:2002, + author = {Alex Groce and + Willem Visser}, + title = {Heuristic Model Checking for Java Programs}, + booktitle = {Proceedings of the 9th International SPIN Workshop on Model Checking of Software}, + pages = {242--245}, + year = {2002}, + url = {http://dx.doi.org/10.1007/3-540-46017-9_21}, +} + +@inproceedings{artho:2011, + author = {Leungwattanakit, Watcharin and Artho, Cyrille and Hagiya, Masami and Tanabe, Yoshinori and Yamamoto, Mitsuharu}, + title = {Model checking distributed systems by combining caching and process checkpointing}, + booktitle = {Proceedings of the 26th IEEE/ACM International Conference on International Conference on Automated Software Engineering}, + year = {2011}, + pages = {103--112}, + publisher = {IEEE}, +month={November}, + address = {Lawrence, KS, USA}, + url = {​http://staff.aist.go.jp/c.artho/papers/checkpointing.pdf}, +} + +@inproceedings{artho:2009, + author = {Artho, Cyrille and Leungwattanakit, Watcharin and Hagiya, Masami and Tanabe, Yoshinori and Yamamoto, Mitsuharu}, + title = {Cache-Based model Checking of Networked Applications: From Linear to Branching Time}, + booktitle = {Proceedings of the 27th International Conference on Automated Software Engineering}, + year = {2009}, +month = {November}, + pages = {447--458}, + publisher = {IEEE}, + address = {Auckland, New Zealand}, + url = {​http://staff.aist.go.jp/c.artho/papers/ase-2009.pdf}, +} + +@inproceedings{artho:2008, +author={Artho, Cyrille and Leungwattanakit, Watcharin and Hagiya, Masami and Tanabe, Yoshinori}, +title={Efficient Model Checking of Networked Applications}, +year={2008}, +volume={11}, +series={Lecture Notes in Business Information Processing}, +booktitle = {Proceedings of the 46th International Conference on Objects, Components, Models and Patterns}, +publisher={Springer}, +pages={22--40}, +address={Zurich, Switzerland}, +month={June/July}, +url = {http://staff.aist.go.jp/c.artho/papers/tools-2008.pdf} +} + +@inproceedings{grove:2003, + author = {Alex Groce and + Willem Visser}, + title = {What Went Wrong: Explaining Counterexamples}, + booktitle = {Proceedings of the 10th International SPIN Workshop on Model Checking of Software}, + pages = {121--135}, + year = {2003}, + url = {http://dx.doi.org/10.1007/3-540-44829-2_8}, + publisher = {Springer}, + address = {Portland}, +} + +@article{penix:2005, + author = {John Penix and + Willem Visser and + Seungjoon Park and + Corina S. P\v{a}s\v{a}reanu and + Eric Engstrom and + Aaron Larson and + Nicholas Weininger}, + title = {Verifying Time Partitioning in the {DEOS} Scheduling Kernel}, + journal = {Formal Methods in System Design}, + volume = {26}, + number = {2}, + pages = {103--135}, + year = {2005}, + url = {http://dx.doi.org/10.1007/s10703-005-1490-4}, +} + +@article{brat:2004, + author = {Guillaume P. Brat and + Doron Drusinsky and + Dimitra Giannakopoulou and + Allen Goldberg and + Klaus Havelund and + Michael R. Lowry and + Corina S. Pasareanu and + Arnaud Venet and + Willem Visser and + Richard Washington}, + title = {Experimental Evaluation of Verification and Validation Tools on Martian + Rover Software}, + journal = {Formal Methods in System Design}, + volume = {25}, + number = {2-3}, + pages = {167--198}, + year = {2004}, + url = {http://dx.doi.org/10.1023/B:FORM.0000040027.28662.a4}, +} + +@inproceedings{bordini:2003, + author = {Rafael H. Bordini and + Michael Fisher and + Carmen Pardavila and + Willem Visser and + Michael Wooldridge}, + title = {Model Checking Multi-Agent Programs with {CASP}}, + booktitle = {Proceedings of Computer Aided Verification}, + pages = {110--113}, + year = {2003}, + url = {http://dx.doi.org/10.1007/978-3-540-45069-6_10}, +} + +@inproceedings{giannakopoulou:2004, + author = {Dimitra Giannakopoulou and + Corina S. Pasareanu and + Jamieson M. Cobleigh}, + title = {Assume-Guarantee Verification of Source Code with Design-Level Assumptions}, + booktitle = {26th International Conference on Software Engineering {(ICSE} 2004), + 23-28 May 2004, Edinburgh, United Kingdom}, + pages = {211--220}, + year = {2004}, + url = {http://doi.ieeecomputersociety.org/10.1109/ICSE.2004.1317443}, +} + +@inproceedings{mehlitz:2008, + author = {Peter Mehlitz}, + title = {Trust Your Model - Verifying Aerospace System Models with Java Pathfinder}, + booktitle = {Aerospace Conference, 2008 IEEE}, + pages = {1--11}, + year = {2008}, + url = {http://ti.arc.nasa.gov/m/pub-archive/1402/1402%20(Mehlitz).pdf}, +} + +@inproceedings{stergiopoulos:2012, + author = {Stergiopoulos, George and Tsoumas, Bill and Gritzalis, Dimitris}, + title = {Hunting Application-level Logical Errors}, + booktitle = {Proceedings of the 4th International Conference on Engineering Secure Software and Systems}, + year = {2012}, + address = {Eindhoven, The Netherlands}, + pages = {135--142}, + url = {http://dx.doi.org/10.1007/978-3-642-28166-2_13}, + publisher = {Springer}, +} + +@article{mansouri:2007, + author = {Masoud Mansouri-Samani and John Penix and Lawrence Markosian}, + title = {Assume-Guarantee Verification of Source Code with Design-Level Assumptions}, + journal = {Software Assurance Research Program (SARP), NASA IV&V publication}, + year = {2007}, + pages = {203--232}, + publisher = {Kluwer Academic Publishers}, + url = {http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20080015887.pdf}, + } + + @article{havelund:2002, + author = {Klaus Havelund and Willem Visser}, + title = {Program Model Checking as a New Trend}, + journal = {International Journal on Software Tools for Technology Transfer (STTT)}, + volume = {4}, + number = {1}, + month = {October}, + year = {2002}, + url = {http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20030003734.pdf}, +} + +@article{pasareanu:dwyer:2003, + author = "C. P\v{a}s\v{a}reanu and M. Dwyer and W. Visser.", + title = "{Finding Feasible Abstract Counter-Examples}", + journal = "International Journal on Software Tools for Technology Transfer (STTT)", + year = "2003", + volume = "5", + number = "1", + month = "November", + url = "http://ti.arc.nasa.gov/m/profile/pcorina/papers/tacas_sttt01.ps" +} + +@inproceedings{brat:2001, + author = {Guillaume Brat and Willem Visser}, + title = {Combining Static Analysis and Model Checking for Software Analysis}, + booktitle = {Proceedings of the 15th IEEE International Conference on Automated Software Engineering}, + year = {2001}, + address = {San Diego, USA}, + month = {November}, + url = {http://dl.acm.org/citation.cfm?id=872568}, +} + +@inproceedings{visser:park:2000, + author = {Willem Visser and Seungjoon Park and John Penix}, + title = {Using Predicate Abstraction to Reduce Object-Oriented Programs for Model Checking}, + booktitle = {Proceedings of the 3rd ACM SIGSOFT Workshop on Formal Methods in Software Practice}, + year = {2000}, + pages = {3--12}, + month = {August}, + url = "http://ti.arc.nasa.gov/m/tech/rse/publications/papers/SIGSOFT00/fmsp00.pdf", +} + +@article{havelund:2000, + author = {Klaus Havelund and + Thomas Pressburger}, + title = {Model Checking {Java} Programs using {Java} PathFinder}, + journal = {International Journal on Software Tools for Technology Transfer (STTT)}, + volume = {2}, + number = {4}, + pages = {366--381}, + year = {2000}, + url = {http://www.havelund.com/Publications/jpf-sttt.ps.Z}, +} + +@inproceedings{havelund:1999, + author = {Klaus Havelund}, + title = {Java PathFinder, {A} Translator from Java to Promela}, + booktitle = {Theoretical and Practical Aspects of {SPIN} Model Checking}, + month = {July}, + year = {1999}, + url = {http://www.havelund.com/Publications/jpf1-spin-99.pdf}, +} + +@inproceedings{havelund:skakkebaek:1999, + author = {Klaus Havelund and + Jens U. Skakkeb{\ae}k}, + title = {Applying Model Checking in Java Verification}, + booktitle = {Theoretical and Practical Aspects of {SPIN} Model Checking, 5th and + 6th International {SPIN} Workshops}, + pages = {216--231}, + year = {1999}, + url = {http://www.havelund.com/Publications/jpf-fm99.ps.Z}, +} + +@article{havelund:2007, + author = {Klaus Havelund}, + title = {Java PathFinder User Guide}, + booktitle = {Unpublished Report}, + year = {1999}, + url = {​http://www.havelund.com/Publications/jpf-manual.ps.Z}, +} + +@article{havelund:Pressburger:1998, + author = {Klaus Havelund and Thomas Pressburger}, + title = {Java PathFinder, A Translator from Java to Promela}, + booktitle = {Unpublished Report}, + year = {1998}, + url = {​​http://www.havelund.com/Publications/jpf1-report-99.pdf}, +} + +@inproceedings{gligoric:2010, + author = {Milos Gligoric and + Tihomir Gvero and + Vilas Jagannath and + Sarfraz Khurshid and + Viktor Kuncak and + Darko Marinov}, + title = {Test generation through programming in {UDITA}}, + booktitle = {Proceedings of the 32nd {ACM/IEEE} International Conference on Software + Engineering}, + address = {Cape Town, South Africa}, + month = {May}, + pages = {225--234}, + year = {2010}, + url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL10UDITA.pdf}, +} + +@inproceedings{gligoric:jagannath:2010, + author = {Milos Gligoric and + Vilas Jagannath and + Darko Marinov}, + title = {MuTMuT: Efficient Exploration for Mutation Testing of Multithreaded + Code}, + booktitle = {Third International Conference on Software Testing, Verification and + Validation}, + pages = {55--64}, + month = {April}, + address = {Paris, France}, + year = {2010}, + url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL10MuTMuT.pdf}, +} + +@inproceedings{lauterburg:2010, + author = {Steven Lauterburg and + Rajesh K. Karmani and + Darko Marinov and + Gul Agha}, + title = {Evaluating Ordering Heuristics for Dynamic Partial-Order Reduction + Techniques}, + booktitle = {Fundamental Approaches to Software Engineering}, + address = {Paphos, Cyprus}, + month = {March}, + pages = {308--322}, + year = {2010}, + url = {http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL10DPORHeuristics.pdf}, +} + +@inproceedings{lauterburg:2009, + author = {Steven Lauterburg and + Mirco Dotta and + Darko Marinov and + Gul A. Agha}, + title = {A Framework for State-Space Exploration of Java-Based Actor Programs}, + booktitle = {24th {IEEE/ACM} International Conference on Automated Software Engineering}, + month = {November}, + address = {Auckland, New Zealand}, + pages = {468--479}, + year = {2009}, + url = {http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL09Basset.pdf}, +} + +@article{sobeih:2010, + author = {Ahmed Sobeih and + Marcelo d'Amorim and + Mahesh Viswanathan and + Darko Marinov and + Jennifer C. Hou}, + title = {Assertion Checking in J-Sim Simulation Models of Network Protocols}, + journal = {Simulation: Transactions of The Society for Modeling and Simulation International}, + volume = {86}, + number = {11}, + pages = {651--673}, + year = {2010}, + url = {http://dx.doi.org/10.1177/0037549709349326}, +} + +@inproceedings{gligoric:2009, + author = {Milos Gligoric and + Tihomir Gvero and + Steven Lauterburg and + Darko Marinov and + Sarfraz Khurshid}, + title = {Optimizing Generation of Object Graphs in Java PathFinder}, + booktitle = {Second International Conference on Software Testing Verification and Validation}, + month = {April}, + address = {Denver, Colorado, {USA}}, + pages = {51--60}, + year = {2009}, + url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL09OptimizingGeneration.pdf}, +} + +@article{damorim:2008, + author = {Marcelo d'Amorim and + Steven Lauterburg and + Darko Marinov}, + title = {Delta Execution for Efficient State-Space Exploration of Object-Oriented Programs}, + journal = {{IEEE} Transactions on Software Engineering}, + volume = {34}, + number = {5}, + pages = {597--613}, + year = {2008}, + month = {September/October}, + url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL08DeltaExecution.pdf}, +} + +@inproceedings{lauterburg:2008, + author = {Steven Lauterburg and + Ahmed Sobeih and + Darko Marinov and + Mahesh Viswanathan}, + title = {Incremental state-space exploration for programs with dynamically + allocated data}, + booktitle = {International Conference on Software Engineering}, + address = {Leipzig, Germany}, + month = {May}, + pages = {291--300}, + year = {2008}, + url = {​http://mir.cs.illinois.edu/~marinov/publications/LauterburgETAL08IncrementalChecking.pdf}, +} + +@inproceedings{gvero:2008, + author = {Tihomir Gvero and + Milos Gligoric and + Steven Lauterburg and + Marcelo d'Amorim and + Darko Marinov and + Sarfraz Khurshid}, + title = {State extensions for java pathfinder}, + booktitle = {International Conference on Software Engineering, Demo Papers}, + address = {Leipzig, Germany}, + month = {May}, + pages = {863--866}, + year = {2008}, + url = {http://mir.cs.illinois.edu/~marinov/publications/GligoricETAL09OptimizingGeneration.pdf}, +} + +@inproceedings{damorim:2007, + author = {Marcelo d'Amorim and + Steven Lauterburg and + Darko Marinov}, + title = {Delta execution for efficient state-space exploration of object-oriented + programs}, + booktitle = {Proceedings of the {ACM/SIGSOFT} International Symposium on Software + Testing and Analysis}, + address = {London, UK}, + month = {July}, + pages = {50--60}, + year = {2007}, + url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL07DeltaExecution.pdf}, +} + +@inproceedings{zhou:2007, + author = {Zhou, Yuanyuan and Marinov, Darko and Sanders, William and Zilles, Craig and d'Amorim, Marcelo and Lauterburg, Steven and Lefever, Ryan M. and Tucek, Joe}, + title = {Delta Execution for Software Reliability}, + booktitle = {Proceedings of the 3rd Workshop on on Hot Topics in System Dependability}, + series = {HotDep'07}, + year = {2007}, + address = {Edinburgh, UK}, + url = {http://mir.cs.illinois.edu/~marinov/publications/ZhouETAL07DeltaExecution.pdf}, + publisher = {USENIX Association}, +} + +@inproceedings{damorim:2006, + author = {Marcelo d'Amorim and + Ahmed Sobeih and + Darko Marinov}, + title = {Optimized Execution of Deterministic Blocks in Java PathFinder}, + booktitle = {Proceedings of Formal Methods and Software Engineering, 8th International Conference + on Formal Engineering Methods}, + address = {Macao, China}, + month = {November}, + pages = {549--567}, + year = {2006}, + url = {http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL06OptimizedDeterministicBlocks.pdf}, +} + +@inproceedings{damorim:pacheco:2006, + author = {Marcelo d'Amorim and + Carlos Pacheco and + Tao Xie and + Darko Marinov and + Michael D. Ernst}, + title = {An Empirical Comparison of Automated Generation and Classification + Techniques for Object-Oriented Unit Testing}, + booktitle = {Proceedings of 21st {IEEE/ACM} International Conference on Automated Software Engineering}, + address = {Tokyo, Japan}, + month = {September}, + pages = {59--68}, + year = {2006}, + url = {​http://mir.cs.illinois.edu/~marinov/publications/dAmorimETAL06Symclat.pdf}, +} + +@unpublished{kulikov:2010, + author = {Sergey Kulikov and Nastaran Shafiei and Franck van Breugel and Willem Visser}, + title = {{Detecting Data Races with Java PathFinder}}, + year = "2010", + url = {http://www.cse.yorku.ca/~franck/research/drafts/race.pdf} +} + +@inproceedings{indradeep:2013, + author = {Ghosh, Indradeep and Shafiei, Nastaran and Li, Guodong and Chiang, Wei-Fan}, + title = {{JST: an automatic test generation tool for industrial Java applications with strings}}, + booktitle = {Proceedings of the 35th International Conference on Software Engineering}, + year = {2013}, + month = {May}, + address = {San Francisco, CA, USA}, + pages = {992--1001}, + publisher = {IEEE}, + url = {http://dl.acm.org/citation.cfm?id=2486925} +} + +@article{nshafiei:2012, + author = {Shafiei, Nastaran and Mehlitz, Peter C.}, + journal = {ACM SIGSOFT Software Engineering Notes}, + number = 6, + pages = {1-5}, + title = {{Modeling class loaders in Java PathFinder version 7}}, + volume = 37, + year = 2012, + month = {November}, + url = {http://dl.acm.org/citation.cfm?id=2382800} +} + +@article{shafiei:2014, + author = {Shafiei, Nastaran and Mehlitz, Peter C.}, + journal = {ACM SIGSOFT Software Engineering Notes}, + number = 1, + pages = {1-5}, + title = {{Extending JPF to verify distributed systems}}, + volume = 39, + year = 2014, + month = {January}, + url = {http://dl.acm.org/citation.cfm?id=2560577}, +} + +@inproceedings{shafiei:2013, + author = {Nastaran Shafiei and + Franck van Breugel}, + title = {Towards model checking of computer games with Java PathFinder}, + booktitle = {Proceedings of the 3rd International Workshop on Games and Software + Engineering}, + address = {San Francisco, CA, USA}, + month = {May}, + pages = {15--21}, + year = {2013}, + url = {http://dl.acm.org/citation.cfm?id=2662596}, +} + + +@inproceedings{shafiei:breugel:2014, + author = {Nastaran Shafiei and + Franck van Breugel}, + title = {Automatic handling of native methods in Java PathFinder}, + booktitle = {Proceedings of the International SPIN Workshop on Model Checking of Software}, + address = {San Jose, CA, USA}, + month = {July}, + pages = {97--100}, + year = {2014}, + url = {http://dl.acm.org/citation.cfm?id=2632363}, +} \ No newline at end of file diff --git a/docs/user/api.md b/docs/user/api.md new file mode 100644 index 0000000..fdfd9a6 --- /dev/null +++ b/docs/user/api.md @@ -0,0 +1,125 @@ +# The Verify API # +Although the primary purpose of JPF is to verify applications that are not JPF dependent, it can also be used to check programs that are explicitly written to execute under JPF. There are two ways to do this + + * use of jpf annotations such as `@gov.nasa.jpf.annotation.JPFConfig` and `@gov.nasa.jpf.annotation.FilterField` + * use of the various `gov.nasa.jpf.vm.Verify` APIs + +The first method provides only directives to JPF (by means of Java annotations), and does not modify or add any specific code to your system under test. The second one is imperative and should only be used by JPF specific test drivers. + +## JPF Annotations ## +The JPF core currently supports two annotation types: `@JPFConfig` and `@FilterField` + +~~~~~~~~ {.java} +import gov.nasa.jpf.annotation.JPFConfig +... +@JPFConfig({"listener+=,gov.nasa.jpf.aprop.listener.SharedChecker", ..}) +public class MyClass { + .. +} +~~~~~~~~ + +The `@JPFConfig` annotation allows to set JPF properties (= pairs) for classes and methods of your application, which is especially useful to add specific listeners. You have to be aware of the property effects though, since not all behavior can be changed at runtime, and you usually cannot reverse features with this method + +The `@FilterField` annotation is used to mark certain fields in your application as not relevant for state matching. This is useful if you have to add debugging information like counters that would otherwise increase the state space (i.e. would prevent state matching). + +~~~~~~~~ {.java} +import gov.nasa.jpf.annotation.FilterField; +... +public class MyClass { + .. + @FilterField int counter; + .. +} +~~~~~~~~ + +This does not change execution of your program in any way, and also does not affect backtracking within JPF (i.e. values are properly restored). It only tells JPF to ignore marked fields when hashing/matching program states. + +There is a [jpf-aprop](wiki:projects/jpf-aprop) JPF module that is dedicated to Java annotation based program properties such as `@Nonnull`, `@NonShared`, `@Immutable`, `@Requires` and many others. + +## The Verify API ## + +Sometimes it is useful to create JPF specific test drivers, like you create JUnit test cases. In this code, you can make explicit use of JPF APIs, since it is not supposed to run outside JPF. There are several categories of APIs which are encapsulated in the `gov.nasa.jpf.vm.Verify` class. + +### Data ChoiceGenerators ### +Data ChoiceGenerators (CGs) are suitable for writing test drivers that are JPF aware. The idea is to obtain non-deterministic input values from JPF in a way that it can systematically analyze all relevant choices. In its most simple form, this can be used like + +~~~~~~~~ {.java} +// test driver code +import gov.nasa.jpf.vm.Verify; +.. +boolean cond = Verify.getBoolean(); +// following code is executed for both cond=true AND cond=false +.. +~~~~~~~~ + +The `Verify` class contains methods for creating a number of different choice generators for builtin Java types, like + +~~~~~~~~ {.java} +.. +int i = Verify.getInt(min,max); // evaluates for all values between 'min' and 'max' (inclusive) +.. +double d = Verify.getDoubleFromSet(-42.0, 0.0, 42.0 ..); // evaluates all given values +.. +~~~~~~~~ + + +CGs don't stop at value sets that can be completely enumerated based on their type (like boolean, and - at least theoretically - integers). JPF also supports configured heuristics based choice generators, where the values sets are application dependent and can be specified in property files. + +![Figure: Data ChoiceGenerators](../graphics/choicegen-example.svg){align=center width=750} + +Choice generator implementation is described in a [separate section](wiki:devel/choicegenerator) of this documentation. + +### Search Pruning ### + +Explicitly restricting the search is useful for highly application specific properties, where it is obvious that certain values are not of interest with respect to the property. + +~~~~~~~~ {.java} +// ..compute some data.. +Verify.ignoreIf(data > someValue); // prune search if true +// ..do some stuff with data.. +~~~~~~~~ +If the provided expression evaluates to true, JPF does not continue to execute the current path, and backtracks to the previous non-deterministic choice point. + +### State Annotation ### +Based on certain value combinations, an application might give JPF hints about the relevance of a program state that can be subsequently used by Search and/or Heuristic implementations. + +~~~~~~~~ {.java} +// ..compute some data +Verify.interesting( data < someValue ); +// ..do some stuff with data +~~~~~~~~ + +This does not stop execution by JPF, but stores an 'interesting' attribute for the current state. Its more general version is used to attach arbitrary strings to states: + +~~~~~~~~ {.java} +// ..compute some data +if (data < someValue) { + Verify.setAnnotation("critical data value"); + // ..do some stuff with dat +~~~~~~~~ + +Again, this category is about to become less important since Search- and VMListeners are superior mechanisms to store not just strings but arbitrary objects as state annotations. + +### Verification Output ### + +This is the most simple category, which is used to differentiate between normal program output (that is executed and analyzed by JPF), and output that is strictly verification relevant, i.e. should not appear when executing a program outside JPF. Not very surprising, it contains a number of print(..) methods. + +### Atomicity Control ### + +this category can be used to control the number of thread interleavings JPF has to analyze. While this is problematic in terms of missing potential defects, it is was often the only way to constrain the state space so that JPF could verify a given application. + +~~~~~~~~ {.java} +Verify.beginAtomic(); +... +// all code in here is executed by JPF in one transition +... +Verify.endAtomic(); +~~~~~~~~ + +Direct atomicity control was mainly used before the automatic, on-the-fly partial order reduction (POR) was implemented, and only remains relevant for applications that are (still) problematic with respect to POR. JPF's on-the-fly POR implementation is described in a [separate section](../devel/partial_order_reduction) of this documentation. + +### Other Usages ### + +Some `Verify` methods support collecting information during JPF execution, which is persistent and can be later-on queried by JPF embedding code (programs that execute JPF). This uses an MJI trick where the [native peer](../devel/mji) class (`JPF_gov_nasa_jpf_vm_Verify`) is used to set some data during JPF execution, which can be later-on retrieved by model class code (through `gov.nasa.jpf.vm.Verify`) that is executed outside of JPF. This is currently used to implement counters, which in turn are used to verify JPF itself. + +It should be noted that while most of the Verify APIs have alternative implementations that enable execution outside of JPF, applications using them at least don't build outside the JPF environment. Their use therefore is only recommended for JPF specific test drivers. \ No newline at end of file diff --git a/docs/user/application_types.md b/docs/user/application_types.md new file mode 100644 index 0000000..352e9c9 --- /dev/null +++ b/docs/user/application_types.md @@ -0,0 +1,36 @@ +# JPF Application Goals and Types # + +By now, you already know that you run JPF on compiled Java programs, just like a normal VM. But what are the goals to apply JPF, and - based on these goals - what are the different JPF application types? + +## Why to Use JPF? ## +Before we classify the different types of JPF applications, it is worth to spend a few thoughts on why we actually want to apply it. A word of caution: if you have a strictly sequential program with only a few well defined input values, you are probably better off writing a few tests - using JPF won't tell you much. There are two major reasons to run JPF: + +### Explore Execution Alternatives ### +After all, JPF started as a software model checker, so its original domain is to explore execution choices, of which we have four different types: + + - scheduling sequences - concurrent applications are still the major domain for JPF application because (a) defects like deadlocks and data races are subtle and usually spurious, and (b) the scheduler can usually not be controlled from a testing environment, i.e. this is hard to impossible to test. JPF on the other hand not only "owns" the scheduler (it is a virtual machine) and explores all interesting scheduling combinations, it even lets you define your own scheduling policies + - input data variation - JPF allows you to explore input value sets that can be defined by heuristics (e.g. a value below, at, and above a certain threshold). This is especially useful when writing test drivers + - environment events - program types like Swing or web applications usually react to external events like user input. Such events can be simulated by JPF as choice sets + - control flow choices - JPF can not only check how your program reacts to a concrete input, it can also turn around and systematically explore the program control structure (branch instructions) to compute input data values that would execute a certain part of your code. + +### Execution Inspection ### + +Even if your program does not have a lot of execution alternatives, you can make use of JPF's inspection capabilities. Being an extensible virtual machine, it is relatively easy to implement coverage analyzers, or non-invasive tests for conditions that would otherwise go unnoticed because they are hard or tedious to implement (like overflow in numerical instructions). + +## JPF Application Types ## +There are three basic JPF application types, each of them having different strengths and weaknesses: JPF- aware, unaware, and "enabled" programs. + +![Figure: JPF application types](../graphics/app-types.svg){align=center width=800} + +### JPF Unaware Programs ### +This is the usual case - you run JPF on an application that is not aware of verification in general, or JPF in particular. It just runs on any VM that is Java compatible. The typical reason to check such an application with JPF is to look for violations of so called non-functional properties that are hard to test for, such as deadlocks or race conditions. JPF is especially good at finding and explaining concurrency related defects, but you have to know the costs: JPF is much slower than a production VM (for a reason - it does a lot more than a normal byte code interpreter), and it might not support all the Java libraries that are used by the system under test. + +### JPF Dependent Programs ### +On the other side of the spectrum we have applications that are models - their only purpose in life is to be verified by JPF (e.g. to check a certain algorithm), so Java just happens to be the implementation language because that is what JPF understands. Typically, these applications are based on a domain specific framework (such as the [statechart extension](../projects/jpf-statechart) that has been written so that JPF can verify the model. As a consequence, the model applications themselves are usually small, scale well, and do not require additional property specification. The downside is that it is quite expensive to develop the underlying domain frameworks. + +### JPF Enabled Programs ### +The third category probably has the best return on investment - programs that can run on any VM, but contain Java annotations that represent properties which cannot easily be expressed with standard Java language. + +For example, assume you have a class which instances are not thread safe, and hence are not supposed to be used as shared objects. You can just run JPF and see if it finds a defect (like a data race) which is caused by illegally using such an object in a multi-threaded context. But even if JPF out-of-the-box can handle the size of the state space and finds the defect, you probably still have to spend a significant effort to analyze a long trace to find the original cause (which might not even be visible in the program). It is not only more easy on the tool (means faster), but also better for understanding if you simply mark the non-threadsafe class with a `@NonShared` annotation. Now JPF only has to execute up to the point where the offending object reference escapes the creating thread, and can report an error that immediately shows you where and how to fix it. + +There is an abundance of potential property-related annotations (such as `@NonNull` for a static analyzer and JPF), including support for more sophisticated, embedded languages to express pre- and post-conditions. diff --git a/docs/user/components.md b/docs/user/components.md new file mode 100644 index 0000000..55a01d2 --- /dev/null +++ b/docs/user/components.md @@ -0,0 +1,57 @@ +# JPF components # +Java is more than a programming language. It is a set of layers that starts with a platform specific VM implementation (which is referred to as the *host VM*) that sits on top of native libraries written for and using your operating system. To this stack, we add JPF - a Java application that runs on top of the "host VM", but is itself a VM which then executes your System Under Test (SUT). + +![Figure 1: Different layers involved when using JPF](../graphics/jpf-layers.svg){align=center width=700} + +With all this recursion, it is easy to get confused about what Java code gets processed at which level. To make things worse, most of the standard library class files (java.* classes) and some of the annotations get processed by both VMs, but of course in different instantiations. Purpose of this page is to shed some light on what code is associated with the different layers and parts of the system. + +In order to untangle, we have to step back and look at what components are involved when applying JPF to the SUT. We categorize the components with respect to two aspects: + + 1. processing VM (host VM, JPF) + 1. associated distribution entity (host Java installation, JPF core, JPF extensions, SUT) + +Remember the [What is JPF](../intro/what_is_jpf) diagram from the introduction? This is a more detailed version of it.  + +![Figure 2: JPF infrastructure](../graphics/jpf-intro-new.svg){align=center width=800} + +Let us walk this diagram left-to-right. We start with the compiled Java application we want to verify. This is of course not part of the JPF distribution, but will be executed by JPF, so the corresponding class files do not have to be visible to the host VM (that runs JPF). However, the application code might use classes and interfaces that reside in the JPF distribution. Together, the application and such modeling libraries and/or annotations form the System under Test (SUT) + +Next comes the JPF core itself. By now we know this is mainly a VM that is written in Java itself, so you run it on whatever Java system is installed on your machine. This means all classes that constitute JPF need to be visible to the host JVM, e.g. by setting the global `CLASSPATH` environment variable (which is not the recommended way to do this). + +Now comes the important part: **JPF is not a monolithic system**. It uses various configured components to do things such as + + * property implementation + * library modeling + * report generation + +and much more. Even if you don't specify anything when you run it, JPF will use a default configuration that pulls in a lot of components such as [listeners](../devel/listener), which do not have to be part of the [JPF core](../jpf-core/index), but can reside in their own JPF extension modules. + +If you do specify your own [configuration](../user/config), you can tell JPF to use components that live outside of the [JPF core](../jpf-core/index) distribution, either in one of the installed JPF extension modules, or in your own project. Either way, all these [listeners](../devel/listener), [native peers](../devel/mji), [publishers](../devel/report) and other components are at runtime part of the whole JPF system, so they need to be visible to the host VM. + +The last part is the most tricky one - your application is most probably using standard Java libraries (e.g. `System.out.println()`), as do the classes that constitute JPF. Some of the standard library classes have to be replaced by JPF specific versions when JPF executes the SUT (e.g. classes such as `java.lang.Class`that have native methods), and JPF has a special [MJI](../devel/mji) mechanism to do that. However, most standard library classes have pure Java implementations, and we take these straight from the host-JVM installation. This means, standard libraries end up in JPF's classpath *and* the host JVM CLASSPATH: and their code is executed by JPF *and* the host VM, but the corresponding instances are different (for instance, a `java.lang.String` object has very different representations in the host VM and JPF). + + +JPF keeps associated class paths separate. There are three different path settings in the JPF configuration: + + 1. `native_classpath` - this includes everything that has to be visible to the host VM, which includes mostly the classes of JPF itself, listeners, native peers and bytecode instruction sets. The `native_classpath` is dynamically constructed from your site.properties and jpf.properties [configuration files](../user/config) during JPF startup, and processed by the JPF classloader + 2. `classpath` - this includes the classes that are executed by JPF, which include your SUT, and all libraries that are used by it (*-classes.jar of installed JPF components). Note that some of the library classes (like `java.lang.Thread`) are replaced by JPF specific versions. Again, this is constructed by JPF during startup from all your configured jpf.properties files, but processed by JPFs internal classfile lookup mechanism. + 3. `sourcepath` - depending on the reports that have to be generated by JPF, it might have to find SUT and library sources for the executed classfiles (bytecodes). This is how you tell JPF where these sources reside. + +You can set these path lists explicitly from your application property file or the command line, but it is better to let JPF collect them when processing the jpf.properties files of your installed JPF components, which all include lines like + +~~~~~~~~ {/bash} +.native_classpath = .. +.classpath = .. +.sourcepath = .. +~~~~~~~~ + +A word of caution: if - during JPF startup - you encounter a message like + +~~~~~~~~ {.bash} +... +[SEVERE} error during VM runtime initialization: wrong model classes (check 'classpath') +~~~~~~~~ + +it means the `classpath` setting is wrong and JPF loads some of the standard library classes that have to be replaced with its own versions - they need to be *modeled* (like `java.lang.Thread`, `java.lang.Class` and others - all part of jpf-classes.jar within the jpf-core module). + +This can also happen later-on with less essential library classes that are not part of jpf-core, but should be loaded from one of the installed extensions. In this case, this usually shows up as an `UnsatisfiedLinkError` diff --git a/docs/user/config.md b/docs/user/config.md new file mode 100644 index 0000000..a57d07b --- /dev/null +++ b/docs/user/config.md @@ -0,0 +1,153 @@ +# Configuring JPF # + +JPF configuration can be intimidating. It is worth to think about why we need such a heavy mechanism before we dive into its details. Little in JPF is hardwired. Since JPF is such an open system that can be parameterized and extended in a variety of ways, there is a strong need for a general, uniform configuration mechanism. The challenge for this mechanism is that many of the parts which are subject to parameterization are configured themselves (i.e. options for optional JPF components like listeners). This effectively prohibits the use of a configuration object that contains concrete fields to hold configuration data, since this class would be a central "design bottleneck" for a potentially open number of JPF components like Searches, Instruction sets and Listeners. + +The goal is to have a configuration object that + + * is based on string values + * can be extended at will + * is passed down in a hierarchical initialization process so that every component extracts only its own parameters + +We achieve this by means of a central dictionary object (`gov.nasa.jpf.Config`) which is initialized through a hierarchical set of Java property files that target three different initialization layers: + + 1. site: optionally installed JPF components + 2. project: settings for each installed JPF module and (optionally) systems under test + 3. application: the class and program properties JPF should check (this is part of your system under test) + +Initialization happens in a prioritized order, which means you can override anything from later configuration stages, all the way up to command line parameters. Actually, this can be even overridden by using the `Verify` API from system under test code, but this is a developer topic. Here is the blueprint, which we will examine in order of execution: + +![Figure: Configuring JPF](../graphics/properties.svg){align=center width=800} + + +## Property Types ## + +Property specifications are processed in a hierarchical order: site properties, project properties, application properties and command line properties. Later stages can override previous stages. Each property is a `=` pair, but we do support some special notations (see below) for key/value expansion, value extension, and pseudo properties that act as directives. + +### Site Properties ### +The site.properties file is machine specific and not part of any JPF project, which means you have to create a [ site.properties](wiki:install/site-properties) file as part of the install process. A sample site.properties might look like: + +~~~~~~~~ +jpf-core = ${user.home}/projects/jpf/jpf-core +jpf-shell = ${user.home}/projects/jpf/jpf-shell +jpf-awt = ${user.home}/projects/jpf/jpf-awt +... +extensions=${jpf-core},${jpf-shell} +~~~~~~~~ + +Each module is listed as a `=` pair, and optionally added to the comma separated list of `extensions`. The order in which modules are added to `extensions` does matter, since it will determine the order in which each of these components is initialized, which basically maps to an ordered list of classpath entries (both for the host VM and JPF itself - paths are kept separate). + +Note that we do **not** require all modules being added to `extensions`, **but** jpf-core needs to be in there. Dependencies on modules not listed in `extensions` can be specified later-on with the `@using` directive. It is a good idea to keep the `extensions` list small to avoid conflicts, and to improve class load times (shorter classpaths). + +Note also that the `extensions` entries are of the form `${}`, which tells JPF to replace these expressions with the value that is associated to . + +Site properties have to be stored in the directory from where you start JPF, one of its parent directories, or a global `${user.home}/.jpf/site.properties`. We recommend a to keep it in a common root directory that contains all your JPF projects and modules. + + +### Project Properties ### +Each JPF module contains a jpf.properties file in its root directory, no matter if this is the jpf-core or an extension. System under test projects can contain a jpf.properties file to factor out common settings (such as class paths) for all JPF applications within this project. + +A project property file defines the JPF specific paths that need to be set for the module or system under test to work properly + + 1. `.`**`native_classpath`**: the host VM classpath (i.e. the classes that constitute JPF itself) + 1. `.`**`classpath`**: the classpath JPF uses to execute the system under test + 1. `.`**`test_classpath`**: host VM and JPF classpath for regression tests + 1. `.`**`sourcepath`**: the path entries JPF uses to locate sources in case it needs to create program traces + +Additionally, `jpf.properties` should contain default values for all module or project specific settings (e.g. report options). + +An example project properties file might look like: + +~~~~~~~~ {.bash} +jpf-aprop = ${config_path} + +#--- path specifications +jpf-aprop.native_classpath = build/jpf-aprop.jar;lib/antlr-runtime-3.1.3.jar +jpf-aprop.classpath = build/examples +jpf-aprop.test_classpath = build/tests +jpf-aprop.sourcepath = src/examples + +#--- other project specific settings +listener.autoload=${listener.autoload},javax.annotation.Nonnull,... +listener.javax.annotation.Nonnull=gov.nasa.jpf.aprop.listener.NonnullChecker +... +~~~~~~~~ + + + +The first entry (`=${config_path}`) in a jpf.properties should always define the module name. JPF automatically expands `${config_path}` with the pathname of the directory in which this jpf.properties file resides. + +jpf.properties are executed in order of definition within site.properties, with one caveat: if you start JPF from within a directory that contains a jpf.properties file, this one will always take precedence, i.e. will be loaded last (overriding previous settings except of the command line). This way, we ensure that JPF developers can enforce priority of the component they are working on. + +Both site.properties and jpf.properties can define or override any key/value pairs they want, but keep in mind that you might end up with different system behavior depending on where you start JPF - avoid configuration force fights by keeping jpf.properties settings disjunct wherever you can. + +Please note that site and project properties have to be consistent, i.e. the module names (e.g. jpf-awt) in site.properties and jpf.properties need to be the same. This is also true for the build.xml Ant project names. + +It is perfectly fine to have a jpf.properties in a SUT that only uses JPF for verification. You need at least to set up the `classpath` so that JPF knows where to find the SUT classes. + + +### Application Properties ### +In order to run JPF, you need to tell it what main class it should start to execute. This is the minimal purpose of the *.jpf application properties files, which are part of your systems under test (SUT). Besides the `target` setting that defines the main class of your SUT, you can also define a list of `target_args` and any number of JPF properties that define how you want your application to be checked (listeners, search policy, bytecode factories etc.). A typical example looks like + +~~~~~~~~ {.bash} +#--- dependencies on other JPF modules +@using = jpf-awt +@using = jpf-shell + +#--- what JPF should run +target = RobotManager + +#--- other stuff that defines how to run JPF +listener+=,.listener.OverlappingMethodAnalyzer + +shell=.shell.basicshell.BasicShell +awt.script=${config_path}/RobotManager-thread.es +cg.enumerate_random=true +... +~~~~~~~~ + +The `@using = ` directive tells JPF to load the `jpf.properties` of the specified projects (defined in `site.properties`). This is the way to ensure proper path initialization of projects that are not listed in `extensions`. + +### Command Line Properties ### +Last not least, you can override or extend any of the previous settings by providing "**+**=" pairs as command line options. This is convenient for experiments if you have to determine the right settings values empirically + + +## Special Property Syntax ## +JPF supports a number of special notations that are valid Java properties syntax, but are only processed by JPF (and - to a certain extend - by Ant): + + * **`key=...${x}..`** - replaces `"${x}"` with whatever is currently stored under the key "`x`". This also works recursively, as in "`classpath = mypath;${classpath}`". Note that while Apache Ant does also support value expansion, but not recursively. In addition, JPF also supports expansion in the key part (i.e. left of the "`=`") + + * **`key+=val`** - appends val to whatever is currently stored under "`key`". Note that there can be no blank between key and "`+=`", which would not be parsed by Java. This expansion only works in JPF + + * **`+key=val`** - in a properties file adds "`val`" in front of what is currently stored under "`key`". Note that if you want to use this from the command line, you have to use two "`++`", since command line options start with "+" + + * **`${config_path}`** - is automatically set to the directory pathname of the currently parsed property file. This can be useful to specify relative pathnames (e.g. input scripts for the jpf-awt extension) + + * **`${config}`** - is set to the file pathname of the currently parsed file + + * **`@requires=`** - can be used to short-circuit loading of a properties file. This is a simple mechanism to control loading of jpf.properties file sections that are incompatible with other modules, and compares to `#ifdef` preprocessor directives. The respective keys are usually set from application properties (*.jpf) files. +Note this does not throw an exception if the required key is not defined, it just bails out of loading the properties file that contains the @requires directive + + * **`@include=`** - recursively loads the properties file with the specified pathname. You can use the automatically defined `${config_path}` property to specify path names that are relative to where the file containing the `@include` directive is, or use `${}` for paths that are relative to the specified module. + + * **`@using=`** - is similar to `@include`, but loads the jpf.properties of the specified module name (which has to be defined in site.properties). Note that there is no `${..}` around the module name - otherwise it would be replaced. The `@using` directive is the preferred way to specify dependencies on modules that are not in the `extensions` list (i.e. automatically initialized). + + * **`@include_if = ??`** - is a conditional `@include` that only loads the properties file if the specified `` is defined + + * **`@include_unless = ??`** - likewise loads the file only if `` is not defined. Both of these directives are used rarely. + + * Omitting the "`=..`" part in command line settings defaults to a "`true`" value for the corresponding key + + * Setting an empty value (`key=`) removes the key from the config dictionary + +## Debugging ## +Depending on the number of installed and loaded projects, you can easily end up with hundreds of settings. There are two command line options you can use if you assume there is a configuration error: + + * **`-show`** - prints all Config entries after the initialization is complete + + * **`-log`** - lists the order in which properties files got loaded by JPF + +## Details on various options ## + +* [Randomization](config/random) + +* Error Reporting diff --git a/docs/user/config/random.md b/docs/user/config/random.md new file mode 100644 index 0000000..4fae737 --- /dev/null +++ b/docs/user/config/random.md @@ -0,0 +1,15 @@ +## Randomization Options in JPF ## + +The randomization options in JPF allow the user to experiment in randomizing the order of choices explored. + +`cg.randomize_choices` can have three possible values: random, path, def. + + * `random`: It explores random choices during program execution with **varying results among different trials**. The default seed used to generate different results is the **system time in milliseconds** + + * `path`: It explores random choices during program execution with **reproducible results among different trials**. The default seed used to generate reproducible results is **42**. The value of the seed can be changed by setting the seed config option. + + * `def`: No randomization, choices are explored using the default search order imposed by the model checker. + +`cg.seed (_INT_)`: The user can specify a particular seed for the random number generator in order to obtain reproducible results in the presence of randomization. Note that this is effective only when the `path` option of `randomize_choices` is selected. + + diff --git a/docs/user/index.md b/docs/user/index.md new file mode 100644 index 0000000..6626007 --- /dev/null +++ b/docs/user/index.md @@ -0,0 +1,19 @@ +# How to Use JPF # + +This section is where the real fun starts. Here you learn about + + - [Different applications of JPF](application_types) + - [JPF's runtime components](components) + - [Starting JPF](run) + - [Configuring JPF](config) + - [Understanding JPF output](output) + - [Using JPF's Verify API in the system under test](api) + +All this assumes you are more interested in running JPF than in developing with/for it, so we will leave most of the JPF internals for the [developer section](../devel/index) of this wiki. + +We do have to bother you with some basic concepts though. Keep in mind that JPF is usually not a black-box tool (such as a compiler). Most probably you have to configure it according to your needs because + + * you have specific verification goals (properties) + * your application has a huge state space that is challenging for a model checker + +On the other hand, JPF is also not a "works-or-fails" tool. Depending on how much time you want to invest, you can adapt it to almost all application types and verification goals. And since JPF is open sourced, chances are somebody has already done that diff --git a/docs/user/output.md b/docs/user/output.md new file mode 100644 index 0000000..349242d --- /dev/null +++ b/docs/user/output.md @@ -0,0 +1,98 @@ +# Understanding JPF Output # + +There are three different ways a JPF run can produce output, each of them with a different purpose, but all controlled by the [general JPF configuration mechanism](config): + + 1. System under test output - what is the SUT doing?\ + + 2. JPF logging - what is JPF doing?\ + + 3. JPF reporting system - what is the result of the JPF run?\ + + + +## System Under Test Output ## + +This is the most simple form of output, which usually just consists of `System.out.println(..)` calls embedded in the application code. There is only one caveat - since this is executed by JPF as part of the application, the same print statement might be executed several times: + +~~~~~~~~ {.java} +public class MyApplication ..{ + ... + boolean cond = Verify.getBoolean(); + System.out.println("and the cond is: " + cond); + ... +} +~~~~~~~~ + +will produce + +~~~~~~~~ +... +and the cond is: true +... +and the cond is: false +... +~~~~~~~~ + +The second execution of the print statement is of course preceded by a backtrack operation of JPF (the `Verify.getBoolean()` statement has two choices `{true,false}`), but the backtracking might not be visible, e.g. when running without the `ExecTracker` or `ChoiceTracker` listeners. + +Since it can be sometimes confusing to see the same output twice without knowing if there is an iteration in the application, or JPF did backtrack between executions, there are two configuration options to control the output behavior: + +`vm.tree_output = {true|false}` - means output is shown on the console each time a print statement is executed. This corresponds to the above example, and is the default behavior. + +`vm.path_output = {true|false}` - will not immediately print the output on the console, but store in the path for subsequent processing once JPF terminates (if the *output* topic is specified - see below). This should produce the same output as running the test application on a normal JVM. + +## Logging ## + +This is a more interesting form of JPF output, primarily intended to show what JPF does internally. For this purpose, it has to support various levels of details, ranging from severe errors to fine grained logging of JPF operations. + +JPF's logging mechanism does not reinvent the wheel, it piggybacks on the standard java.util.logging infrastructure. While this means it would be possible to use customized LogHandlers and Formatters (e.g. to log in XML format), there are specialized JPF incarnations of these classes, mainly to enable logging configuration via the standard JPF configuration mechanism rather than system properties. + +Using the JPF Logging involves two aspects: (1) controlling log output destination, and (2) setting log levels. Both are done with JPF property files. + +To set the default log level, use the `log.level` property (the supported levels being *severe,warning,info,fine,finer,finest*) + +If you want to log to a different console that possibly even runs on a remote machine, use the gov.nasa.jpf.tools.LogConsole on the machine that should display the log messages: + +~~~~~~~~ {.bash} +$ java gov.nasa.jpf.tools.LogConsole +~~~~~~~~ + +Then start JPF on the test machine, specifying where the log output should go: + +~~~~~~~~ {.bash} +$ jpf +log.output=: ... MyTestApp +~~~~~~~~ + +The default host is "localhost", default port is 20000. If these are suitable settings, you can start the `LogConsole` without parameters, and just specify `+log.output=socket` when running JPF. + + +If you develop your own JPF classes, please also check the [JPF logging API](../devel/logging) page. + +## Reports ## + +The JPF reporting system is used to show the outcome of a JPF run, to report property violations, print traces, show statistics and much more. This is in a way the most important part of the JPF user interface, and might involve various different output formats (text, XML, API calls) and targets (console, IDE). Depending on application and project, users might also need control over what items are displayed in which order. It is also obvious this needs to be an extensible mechanism, to adapt to new tools and properties. The JPF report system provides all this, again controlled by JPF's general configuration mechanism. + +The basic concept is that reporting depends on a predefined set of output phases, each of them with a configured, ordered list of topics. The output phases supported by the current system are: + + * start - processed when JPF starts + * transition - processed after each transition + * property_violation - processed when JPF finds a property violation + * finished - processed when JPF terminates + +There is no standard transition topic yet (but it could be implemented in `PublisherExtensions`). The standard `property_violation` topics include: + + * error - shows the type and details of the property violation found + * trace - shows the program trace leading to this property violation + * snapshot - lists each threads status at the time of the violation + * output - shows the program output for the trace (see above) + * statistics - shows property statistics information + +Last not least, the finished list of topics that usually summarizes the JPF run: + + * result - reports if property violations were found, and shows a short list of them + * statistics - shows overall statistics information + +The system consists of three major components: (1) the Reporter, (2) any number of format specific Publisher objects, and (3) any number of tool-, property- and Publisher-specific PublisherExtension objects. Here is the blueprint: + + +Again, there is separate [report system API](../devel/report) documentation if you are interested in JPF development. diff --git a/docs/user/run.md b/docs/user/run.md new file mode 100644 index 0000000..ce3b515 --- /dev/null +++ b/docs/user/run.md @@ -0,0 +1,258 @@ +# Running JPF # +There are five general ways to run JPF, depending on your execution environment (command prompt or IDE) and desired level of configuration support. This page has to cover quite some ground, so bear with us + + 1. [from a command prompt (operating system shell)](#command-line) + 2. [from an IDE (NetBeans, Eclipse) without using JPF plugins](#running-jpf-from-within-ide-without-plugins) + 3. [from an IDE with JPF plugins installed](#running-jpf-from-within-ide-with-plugins) + 4. [from within a JUnit test class](#launching-jpf-from-junit-tests) + 5. [single tests from command line](#explicitly-running-tests-from-the-command-line) + 6. [explicitly from an arbitrary Java program](#explicitly-launching-jpf-from-a-java-program) + +## Command Line ## + +There are several ways to run JPF from the command line, using varying degrees of its runtime infrastructure. The most simple way is to use the provided `bin/jpf` script of the jpf-core distribution. Go to the directory where your system under test (SUT) classes reside, and do a + +~~~~~~~~ {.bash} +> /bin/jpf +classpath=. +~~~~~~~~ + +or preferably + +~~~~~~~~ {.bash} +> /bin/jpf .jpf +~~~~~~~~ + +(see target specification below). If you want to avoid platform specific scripts, you only have to slightly expand this to + +~~~~~~~~ {.bash} +> java -jar /build/RunJPF.jar +classpath=. +~~~~~~~~ + +This makes use of the small RunJPF.jar startup jar that is part of the jpf-core distribution, which only includes the classes that are required to start the JPF bootstrapping process (esp. the JPF classloader). These classes automatically process the various [JPF configuration files](config). If your SUT is not trivial, it is also recommended to add a "-Xmx1024m" host VM option, to avoid running out of memory. + +Last (and probably most rarely), you can directly start JPF and give it an explicit classpath. This amounts to something like + +~~~~~~~~ {.bash} +> java -classpath /build/jpf.jar gov.nasa.jpf.JPF +classpath=. +~~~~~~~~ + +Of course, this gets quickly more complicated if you use JPF extensions, which require to add to both the host VM and the JPF classpath, which is completely automated if you use the RunJPF.jar method. Explicitly setting paths is only for rare occasions if you develop JPF components yourself. + +There are three different argument groups that are processed by JPF: + +#### (1) JPF command line options #### + +These options should come first (after RunJPF.jar), and all start with a hyphen ("-"). The set of currently supported options is: + + * -help : show usage information and exit + * -log : print the configuration steps + * -show : print the configuration dictionary after configuration is complete + +The last two options are mostly used to debug if the JPF configuration does not work as expected. Usually you start with `-show`, and if you don't see the values you expect, continue with `-log` to find out how the values got set. + + +#### (2) JPF properties #### + +This is the second group of options, which all start with a plus ("+") marker, and consist of "`+=`" pairs like + +~~~~~~~~ {.bash} +.. +cg.enumerate_random=true +~~~~~~~~ + +All properties from the various JPF properties [configuration files](config) can be overridden from the command-line, which means there is no limit regarding number and values of options. If you want to extend an existing value, you can use any of the following notations + + * `++=` - which appends + * `++=` - which prepends + * `+=..${}..` - which gives explicit control over extension positions + +Normal JPF properties `${}` expansion is supported. + +If the `=` part is omitted, a default value of `true` is assumed. If you want to set a value to null (i.e. remove a key), just skip the `` part, as in `+=` + +#### (3) target specification #### + +There are two ways to specify what application JPF should analyze + + * explicit classname and arguments + +~~~~~~~~ {.bash} +> jpf ... x.y.MyApplication arg1 arg2 .. +~~~~~~~~ + + * application property file (*.jpf) + +~~~~~~~~ {.bash} +> jpf ... MyApplication.jpf +~~~~~~~~ + +We recommend using the second way, since it enables you to store all required settings in a text file that can be kept together with the SUT sources, and also allows you to start JPF from within !NetBeans or Eclipse just by selecting the *.jpf file (this is mainly what the IDE plugins are for). Please note that application property files require a "`target`" entry, as in + +~~~~~~~~ {.bash} +# JPF application property file to verify x.y.MyApplication +target = x.y.MyApplication +target.args = arg1,arg2 +# Note that target_args in JPF 6 changed to target.args in JPF 7. +... +~~~~~~~~ + +## Running JPF from within IDE without plugins ## + +You can start JPF from within !NetBeans or Eclipse without having the IDE specific JPF plugins installed. In this case, JPF uses the standard IDE consoles to report verification results. For details, please refer to the following pages: + + * [Running JPF from within NetBeans without plugin](run_nb) + * [Running JPF from Eclipse without plugin](run_eclipse) + +Note that this is **not** the recommended way to run JPF from within an IDE, unless you want to debug JPF or your classes. + +## Running JPF from within IDE with plugins ## + +You can simplify launching JPF from within !NetBeans or Eclipse by using the respective plugins that are available from this server. In this case, you just have to create/select an application property (*.jpf) file within your test project, and use the IDE context menu to start a graphical JPF user interface. These so called "JPF shells" are separate applications (that can be configured through normal JPF properties), i.e. appear in a separate window, but can still communicate with the IDE, e.g. to position editor windows. You can find more details on + + * [Running JPF from within NetBeans with netbeans-jpf plugin](run_nb_plugin) + * [Running JPF from Eclipse with eclipse-jpf plugin](run_eclipse_plugin) + +This is becoming the primary method of running JPF. The benefits are twofold: (1) this is executed outside of the IDE process, i.e. it doesn't crash the IDE if JPF runs out of memory, and (2) it makes use of all your standard JPF configuration (site.properties and jpf.properties), in the same way like running JPF from a command-line. + +## Launching JPF from JUnit tests ## + +JPF comes with [JUnit](http://www.junit.org) based testing infrastructure that is used for its own regression test suite. This mechanism can also be used to create your own test drivers that are executed by JUnit, e.g. through an [Ant](http://ant.apache.org) build script. The source structure of your tests is quite simple + +~~~~~~~~ {.java} +import gov.nasa.jpf.util.test.JPFTestSuite; +import org.junit.Test; + +public class MyTest extends TestJPF { + + @Test + public void testSomeFunction() { + if (verifyNoPropertyViolation(jpfOptions)) { // specifies the test goal, "jpfOptions" are optional + someFuntction(); .. // this section is verified by JPF + } + } + + //.. more @Test methods +~~~~~~~~ + +From a JUnit perspective, this is a completely normal test class. You can therefore execute such a test with the standard `` [Ant](http://ant.apache.org) task, like + +~~~~~~~~ {.xml} + + + ... + + ... + + ... + + + + + + ... + + + + + ... +~~~~~~~~ + +Only jpf.jar needs to be in the host VM classpath when compiling and running the test, since `gov.nasa.jpf.util.test.TestJPF` will use the normal JPF configuration (site.properties and configured jpf.properties) to set up the required `native_classpath`, `classpath`, 'test_classpath` and `sourcepath` settings at runtime. Please refer to the [JPF configuration](config) page for details. + +If you don't have control over the build.xml because of the IDE specific project type (e.g. if your SUT is configured as a NetBeans "Class Library Project"), you have to add jpf.jar as an external jar to your IDE project configuration. + +In addition to adding jpf.jar to your build.xml or your IDE project configuration, you might want to add a jpf.properties file to the root directory of your project, to set up things like where JPF finds classes and sources it should analyze (i.e. settings that should be common for all your tests). A generic example could be + +~~~~~~~~ {.bash} + # example of JPF project properties file to set project specific paths + + # no native classpath required if this is not a JPF project itself + myproject.native_classpath=... + + # where does JPF find the classfiles to execute + myproject.classpath=build/classes + + # where do test classes reside + myproject.test_classpath=build/test/classes + + # other project common JPF settings like autoloaders etc. + listener.autoload+=,javax.annotation.Nonnull + listener.javax.annotation.Nonnull=.aprop.listener.NonnullChecker + ... +~~~~~~~~ + +You can find project examples here + + * [standard NetBeans project](../projects/standardnbproject) ("Java Class Library" or "Java Application") + * Freeform NetBeans project (with user supplied build.xml) + * standard Eclipse project (with user supplied build.xml) + +Please refer to the [Verify API](api) and the [JPF tests](../devel/jpf_tests) pages for details about JPF APIs (like `verifyNoPropertyViolation(..)` or `Verify.getInt(min,max)`) you can use within your test classes. + +Since JPF projects use the same infrastructure for their regression tests, you can find a wealth of examples under the `src/tests` directories of your installed JPF projects. + +## Explicitly Running Tests from the command line ## + +You can also run your `TestJPF` derived test drivers by using the `bin/test` script (which in turn just a short for "`java -jar tools/RunTest.jar`", i.e. is platform independent): + +~~~~~~~~ {.bash} +bin/test [] +~~~~~~~~ + +Note that each `verify..(jpfArgs)` uses its own `Config` instance in this case. If you want to specify temporary JPF options from the command-line when running `RunTest`, prefix them with `test` like in the following example + +~~~~~~~~ {.bash} +bin/test +test.listener=.listener.ExecTracker gov.nasa.jpf.test.mc.basic.AttrsTest +~~~~~~~~ + +## Explicitly Launching JPF from a Java Program ## +Since JPF is a pure Java application, you can also run it from your own application. The corresponding pattern looks like this: + +~~~~~~~~ {.java} +public class MyJPFLauncher { + ... + public static void main(String[] args){ + .. + try { + + // this initializes the JPF configuration from default.properties, site.properties + // configured extensions (jpf.properties), current directory (jpf.properies) and + // command line args ("+=" options and *.jpf) + Config conf = JPF.createConfig(args); + + // ... modify config according to your needs + conf.setProperty("my.property", "whatever"); + + // ... explicitly create listeners (could be reused over multiple JPF runs) + MyListener myListener = ... + + JPF jpf = new JPF(conf); + + // ... set your listeners + jpf.addListener(myListener); + + jpf.run(); + if (jpf.foundErrors()){ + // ... process property violations discovered by JPF + } + } catch (JPFConfigException cx){ + // ... handle configuration exception + // ... can happen before running JPF and indicates inconsistent configuration data + } catch (JPFException jx){ + // ... handle exception while executing JPF, can be further differentiated into + // ... JPFListenerException - occurred from within configured listener + // ... JPFNativePeerException - occurred from within MJI method/native peer + // ... all others indicate JPF internal errors + } + ... +~~~~~~~~ + +Please refer to the [Embedding JPF](../devel/embedded) developers documentation for details. If you start JPF through your own launcher application, you have to take care of setting up the required `CLASSPATH` entries so that it finds your (and JPFs) classes, or you can use the generic `gov.nasa.jpf.Main` to load and start your launcher class, which makes use of all the path settings you have in your [site.properties](../install/site-properties) and the directories holding project properties (jpf.properties) referenced therein (details on [how to configure JPF](../user/config). This brings us back to the command line at the top of this page, only that you specify which class should be loaded through `Main`: + +~~~~~~~~ {.bash} +> java -jar .../RunJPF.jar -a MyJPFLauncher ... +~~~~~~~~ + +(note that `gov.nasa.jpf.Main` is the `Main-Class` entry of the executable RunJPF.jar, which also holds the `JPFClassLoader`). + +Just for the sake of completeness, there is another way to start JPF explicitly through a `gov.nasa.jpf.JPFShell` implementation, which is using the normal `JPF.main()` to load your shell, which in turn instantiates and runs a `JPF` object. This is specified in your application property (*.jpf) file with the `shell=` option. Use this if your way to start JPF is optional, i.e. JPF could also be run normally with your *.jpf. \ No newline at end of file diff --git a/docs/user/run_eclipse.md b/docs/user/run_eclipse.md new file mode 100644 index 0000000..72a8e3a --- /dev/null +++ b/docs/user/run_eclipse.md @@ -0,0 +1,20 @@ +## Running JPF within eclipse ## + +To run JPF in eclipse after building + +* JPF click "Run"-->"Run" or click "Play"-->"Run As Dialog". + +* Select Java Application and click "New". + +* Click on the "Main" tab. Ensure the project selected is jpf-core and the in the Main Class pick `gov.nasa.jpf.JPF`. + +* Click on the "Arguments" tab. Specify the `` in the Program Arguments. Any additional configuration properties can be specified. For example, + +~~~~~~~~ {.bash} ++cg.randomize_choices=true +oldclassic +~~~~~~~~ + +* Click on "Run" to verify the application in JPF. The output of the program and the results will be displayed on the eclipse console window. + +Alternatively you pick the run-jpf-core launch configuration and add the `` of the system under test. The eclipse IDE detects the various launch configurations. When you click on the Run button they appear on the left column, pick "run-jpf-core". It is, however, recommended you run the application with the eclipse plugin for better performance and ease of usability. \ No newline at end of file diff --git a/docs/user/run_eclipse_plugin.md b/docs/user/run_eclipse_plugin.md new file mode 100644 index 0000000..a2f40e8 --- /dev/null +++ b/docs/user/run_eclipse_plugin.md @@ -0,0 +1,12 @@ +# Running JPF from within Eclipse using eclipse-jpf # + +eclipse-jpf can be easily configured to run JPF from within Eclipse + + 1. Install eclipse-jpf (see [Installing Eclipse JPF plugin](../install/eclipse-plugin)) + 2. Make sure that the correct site.properties file is being used for JPF (The default is usually correct) + To see which site.properties file is being used: + 3. From the Eclipse top menu go to **Window**->**Preferences** + 4. Select **JPF Preferences** + 5. Make sure that "Path to site.properties" is defined properly. + 6. From either the **Package Explorer** view (On the left of the main Eclipse screen by default) right-click on the *.jpf with the JPF configuration wanted and select **Verify...** + 7. Make sure that the **Console view** (Usually at the bottom of the main Eclipse screen) is opened to view the results from JPF \ No newline at end of file diff --git a/docs/user/run_nb.md b/docs/user/run_nb.md new file mode 100644 index 0000000..b6e60d9 --- /dev/null +++ b/docs/user/run_nb.md @@ -0,0 +1,92 @@ +# Running JPF from within NetBeans without JPF plugin # + +Please Note that the following description assumes NetBeans "freeform projects". In general, it is much better to use the JPF plugins, which not only make the configuration steps described below obsolete, but also work with other NetBeans project types. + +Since the NetBeans build process is Ant based, and Ant can read a subset of JPF configuration files, integration is fairly straight forward. Every JPF project comes with its own build.xml, and a `.../nbproject` directory that holds a NetBeans specific project.xml and ide-file-target.xml file, which can serve as templates for your own projects. + +Once everything is configured correctly, you can run JPF by selecting application property (*.jpf) files in the "project view", and do a "Run"->"Run File" from the NetBeans main menu (without the plugin, there will be no "run" item in the project view context menu, but hotkeys should still work). + +To make this work, you have to configure two NetBeans specific files: + +### nbproject/project.xml ### + +If you want to use JPF specific classes (like annotations), you have to make sure the NetBeans source checker will see them. You can achieve this by re-using the JPF property files to set the required classpaths, like + +~~~~~~~~ {.xml} +... + + ... + + ${user.home}/.jpf/site.properties + ${jpf-core}/jpf.properties + ... + + ... + + + ... + ...;${jpf-core.native_classpath} + + ... +~~~~~~~~ + +This works for two reasons: + + * Ant supports `${key}` expansion from properties (as long as they are not self-recursive) + * Ant properties are single-assignment, i.e. subsequent definitions of the same property name will be ignored + +The next step is required no matter if you use JPF types or not - you have to define file actions, which will link to the ide-file-targets.xml + +~~~~~~~~ {.xml} + ... + + ... + + + run-selected-jpf + + jpf.config + ... + \.jpf$ + absolute-path + + + + + + ... +~~~~~~~~ + +It seems this has to be defined for each source folder, which can require a number of redundant XML elements + +### nbproject/ide-file-targets.xml ### + +Within this file, you have to provide the scripts to run the actions defined in the project.xml. This can also make use of the JPF configuration files: + +~~~~~~~~ {.xml} + + + + + + + ... + + + ... + + Must set property 'jpf.config' + + + + + + + ... + + + + + ... +~~~~~~~~ + diff --git a/docs/user/run_nb_plugin.md b/docs/user/run_nb_plugin.md new file mode 100644 index 0000000..134634e --- /dev/null +++ b/docs/user/run_nb_plugin.md @@ -0,0 +1,12 @@ +# Running JPF from within NetBeans with netbeans-jpf plugin # +netbeans-jpf can be easily configured to run JPF at the click of a mouse. + + 1. Install netbeans-jpf (see: [Installing the NetBeans JPF plugin](../install/netbeans-plugin)) + 2. Make sure the correct `site.properties` file is being used for JPF (The default is usually correct)\ + To see which `site.properties` file is being used: + 3. From the NetBeans top menu go to "Tools"->"Options" (Alt+T followed by Alt+O) + 4. Select "Miscellaneous" from the top of the Options Window + 5. Select the "Java Pathfinder" tab + 6. Make sure that "Path to `site.properties`" is defined properly, uncheck "Use default `site.properties` location" to change the path + 7. From either the "Projects" or "Files" view (on the left of the main NetBeans screen by default,) select the JPF properties file (i.e., a file with a `.jpf` extension) you would like to run. Right click on this file and select the "Verify..." menu item to run JPF. + 8. To view the results, make sure that the "Output" View is open (On the bottom of the main NetBeans screen by default) \ No newline at end of file