//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.vm;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.JPFListener;
import gov.nasa.jpf.jvm.ClassFile;
/**
* interface to register for callbacks by the VM
* Observer role in equally named pattern
*
* Note that we only have notifications for generic events, NOT for conditions that
* are property specific, and especially nothing that is just triggered from an extension.
* If listeners are used to implement high level properties, the notifications should be
* used to implement properties, not to report some property violation that was detected
* by JPF
*/
public interface VMListener extends JPFListener {
/**
* VM got initialized (but search is not yet running). This can be used to
* do type initialization in listeners, since the ClassLoader mechanism is now functional
*/
void vmInitialized (VM vm);
/**
* Rests the instruction counter.
*/
void resetInstructionCounter();
/**
* VM is about to execute the next instruction
*/
void executeInstruction (FeatureExpr ctx, VM vm, ThreadInfo currentThread, Instruction instructionToExecute);
/**
* VM has executed the next instruction
* (can be used to analyze branches, monitor PUTFIELD / GETFIELD and
* INVOKExx / RETURN instructions)
*/
void instructionExecuted (VM vm, ThreadInfo currentThread, Instruction nextInstruction, Instruction executedInstruction);
/**
* new Thread entered run() method
*/
void threadStarted (VM vm, ThreadInfo startedThread);
/**
* thread waits to acquire a lock
// NOTE: vm.getLastThreadInfo() does NOT have to be the running thread, as this
// notification can occur as a result of a lock operation in the current thread
*/
void threadBlocked (VM vm, ThreadInfo blockedThread, ElementInfo lock);
/**
* thread is waiting for signal
*/
void threadWaiting (VM vm, ThreadInfo waitingThread);
/**
* thread got notified
*/
void threadNotified (VM vm, ThreadInfo notifiedThread);
/**
* thread got interrupted
*/
void threadInterrupted (VM vm, ThreadInfo interruptedThread);
/**
* Thread exited run() method
*/
void threadTerminated (VM vm, ThreadInfo terminatedThread);
/**
* new thread was scheduled by VM
*/
void threadScheduled (VM vm, ThreadInfo scheduledThread); // this might go into the choice generator notifications
/**
* a new classfile is about to be parsed. This notification allows replacement
* of the related classfile data via ClassFile.{get/set}Data() and can be
* used to do on-the-fly classfile instrumentation with 3rd party libraries
*/
public void loadClass (VM vm, ClassFile cf);
/**
* new class was loaded. This is notified after the ClassInfo has been
* instantiated, but before the class object is initialized, i.e. clinit
* is called. The main use for this notification is to identify and
* store ClassInfos, MethodInfos, FieldInfos or Instructions that are
* used by listeners etc. in order to enable efficient identify based filters
* in the performance critical instruction notifications
*/
void classLoaded (VM vm, ClassInfo loadedClass);
/**
* new object was created
*/
void objectCreated (VM vm, ThreadInfo currentThread, ElementInfo newObject);
/**
* object was garbage collected (after potential finalization)
*/
void objectReleased (VM vm, ThreadInfo currentThread, ElementInfo releasedObject);
/**
* notify if an object lock was taken (this includes automatic
* surrender during a wait())
*/
void objectLocked (VM vm, ThreadInfo currentThread, ElementInfo lockedObject);
/**
* notify if an object lock was released (this includes automatic
* reacquisition after a notify())
*/
void objectUnlocked (VM vm, ThreadInfo currentThread, ElementInfo unlockedObject);
/**
* notify if a wait() is executed
*/
void objectWait (VM vm, ThreadInfo currentThread, ElementInfo waitingObject);
/**
* notify if an object notifies a single waiter
*/
void objectNotify (VM vm, ThreadInfo currentThread, ElementInfo notifyingObject);
/**
* notify if an object notifies all waiters
*/
void objectNotifyAll (VM vm, ThreadInfo currentThread, ElementInfo notifyingObject);
/**
* object becomes reachable through a shared reference
* 'sharedObject' is the (already shared) owner of the field to which the (yet unshared) 'exposedObject' reference got assigned
*/
void objectExposed (VM vm, ThreadInfo currentThread, ElementInfo sharedObject, ElementInfo exposedObject);
/**
* object fields accessed by more than one live thread
*/
void objectShared (VM vm, ThreadInfo currentThread, ElementInfo sharedObject);
void gcBegin (VM vm);
void gcEnd (VM vm);
/**
* exception was thrown
*/
void exceptionThrown (VM vm, ThreadInfo currentThread, ElementInfo thrownException);
/**
* exception causes top frame to be purged
*/
void exceptionBailout (VM vm, ThreadInfo currentThread);
/**
* exception handled by current top frame
*/
void exceptionHandled (VM vm, ThreadInfo currentThread);
/**
* next ChoiceGenerator was registered, which means this is the end of the current transition
*
* the reason why we have this in addition to the choiceGeneratorSet is that listeners
* can reset the registered CG and so force the current transition to continue (although the
* listener in this case has to make sure the operand stack is in a consistent state for
* continued execution because there might be a bottom half of an Instruction.execute() missing)
*/
void choiceGeneratorRegistered (VM vm, ChoiceGenerator<?> nextCG, ThreadInfo currentThread, Instruction executedInstruction);
/**
* a new ChoiceGenerator was set, which means we are at the beginning of a new transition.
*
* NOTE - this notification happens before the KernelState is stored, i.e. listeners are NOT
* allowed to alter the KernelState (e.g. by changing field values or thread states)
*/
void choiceGeneratorSet (VM vm, ChoiceGenerator<?> newCG);
/**
* the next choice was requested from a previously registered ChoiceGenerator
*
* NOTE - this notification happens before the KernelState is stored, i.e. listeners are NOT
* allowed to alter the KernelState (e.g. by changing field values or thread states)
*/
void choiceGeneratorAdvanced (VM vm, ChoiceGenerator<?> currentCG);
/**
* a ChoiceGnerator has returned all his choices
*
* NOTE - this notification happens before the KernelState is stored, i.e. listeners are NOT
* allowed to alter the KernelState (e.g. by changing field values or thread states)
*/
void choiceGeneratorProcessed (VM vm, ChoiceGenerator<?> processedCG);
/**
* method body was entered. This is notified before the first instruction
* is executed
*/
void methodEntered (VM vm, ThreadInfo currentThread, MethodInfo enteredMethod);
/**
* method body was left. This is notified after the last instruction had
* been executed
* NOTE - this is also notified when a StackFrame is dropped due to unhandled exceptions
*/
void methodExited (VM vm, ThreadInfo currentThread, MethodInfo exitedMethod);
}