As mentioned in the Getting Started guide, AnvilJ can operate on most Java programs, but there are a small set of restrictions which must be observed in order for the programs to be refactored correctly. This page will assume that you are familiar with the concept of AnvilJ Instances.

AnvilJ instances must be static final fields

AnvilJ threads and shared object instances must be declared as static final fields. This is so that the refactoring engine can determine at compile-time their location and number, which is not in general possible otherwise. For example:
//Correct
static final Thread myThread = new Thread();
 
//Incorrect (if myThread is declared an an AnvilJ Thread by the architecture.xml file)
int main(void) {
  Thread myThread;
}
Making AnvilJ instances static ensures that the exact number of instances is clear. Requiring them to be final helps the refactoring engine to determine the expression which is used to instantiate the instance (so in the "correct" example above, the expression is = new Thread()). Related to this point...

AnvilJ instances must be instantiated by a unique expression

The refactoring engine needs to be able to determine the expression which is used to create each AnvilJ Instance. Because AnvilJ instances have to be static final, instances must be instantiated directly during declaration or in a static initialiser. This restriction forces the static initialiser to only write to the instance field once (and not, for example, use a case or if to select between a range of possible instantiations). For example:
//Correct
static final Thread myThread = new Thread();
 
//Also correct
static final Thread myThread;
static {
  myThread = new Thread();
}
 
//Incorrect (if myThread is declared an an AnvilJ Thread by the architecture.xml file)
static final Thread myThread;
static {
  if(someVariable) {
    myThread = new Thread();
  } else {
    myThread = new AnotherThreadClass();
  }
}
It can be seen that this restriction could be avoided by extending the capabilities of the refactoring engine, but this has currently not been done. Currently, the workaround to this is to pass someVariable into the instantiated class and use it in the constructor instead.

Threads on different nodes must only use other AnvilJ objects to communicate

The most challenging part of working with AnvilJ is working out how much of the input application needs to be marked as AnvilJ Instances (and therefore allocated by the architecture specification and subject to the above restrictions). In general, the overhead to allocating extra AnvilJ Instances is very small and so the programmer should always err on the side of caution, but clearly too many instances is not ideal as more of the application is restricted. The rule to remember is:

Normal Java threads can call methods and access fields of any instances on the local JVM. However, if a thread wishes to access an object instance which is located on a different node, the remote instance must be tagged as an AnvilJ Instance.

Clearly, the decision as to what is the "local JVM" can change depending on the allocation in the architecture definition. Therefore the programmer should ensure that their program is structured such that the allocatable units of their application communicate through well-defined interface classes. It is then sufficient to only have these interface classes marked as AnvilJ Instances.

Unfortunately this restriction cannot be verified by the refactoring engine.

AnvilJ instances must be accessed by direct static reference

All accesses to an AnvilJ instances must directly refer to the field (using dot notation if the reference is in another class). It is forbidden to 'leak' a reference to an AnvilJ instances through the following actions:

*Returning it from a method
*Passing it into a method
*Assigning it to a field (copying the reference)

Any of these actions will be checked for by the refactoring engine and if any are found the refactoring will be halted until the code has been corrected. For example, the following code is not permitted:
//In this example, myThread is designated an AnvilJ Thread in the architecture definition
 
//Correct - myThread is accessed through dot notation
GlobalInstances.myThread.start();
 
//Incorrect - myThread cannot be returned from a method
Thread getThread() {
  return MyDefinitions.myThread; //This is not permitted
  //if myThread is an AnvilJ Instance
}
 
int main(void) {
    getThread.start();
}

Arguments and return values of shared methods and public fields must be serializable

The arguments and return values of shared methods that are exported by an AnvilJ Thread or Shared Instance must implement the java.io.Serializable interface (or a descendent interface). This also applies to public fields (which are transparently refactored into getter/setter methods by the refactoring engine). This is because shared method arguments are passed using Java's serialization API.

The refactoring engine will attempt to check that this is the case, but it is not always possible. When abstract classes are used in method signatures (like java.util.List) it cannot determine statically the concrete class which will be used to implement it at runtime. java.util.List is not serialisable, but all standard implementations of it are (such as java.util.ArrayList). If the refactoring engine cannot determine for certain that an argument is serializable it will emit a warning and the programmer can determine if this can be ignored. If in doubt, rewrite the method to require a concrete, serializable class.
//If sharedInstance is an AnvilJ Instance
 
//Works, but will give a warning
static final List<Integer> sharedInstance;
 
//Preferred as ArrayList is the concrete class
static final ArrayList<Integer> sharedInstance;
Note that by default, all methods of a class that is used as an AnvilJ Thread or Shared Instance are treated as potentially shared methods. To prevent a method from being treated as shared, mark it with the @AnvilJExclude annotation, as below:
public class SharedClass {
 
  public int methodOne(int x) {...};
 
  @AnvilJExclude
  public int methodTwo(List<String> s) {...);
 
}
In the above example, the class exports two shared methods. methodTwo however uses an abstract class as an argument and so this would create a warning at refactoring time. In this example, the method is only intended to be called locally (by threads on the same node as the shared instance) so the programmer has added the @AnvilJExclude annotation to exclude it from the shared method processing and thereby suppressing the warning. Note that because of this annotation this code will fail at runtime if the method is called from a remote node.