// // Copyright (C) 2013 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 cmu.conditional.Conditional; import cmu.conditional.One; import de.fosd.typechef.featureexpr.FeatureExpr; import gov.nasa.jpf.annotation.MJI; import gov.nasa.jpf.util.Predicate; /** * @author Nastaran Shafiei <nastaran.shafiei@gmail.com> * * A native peer for FinalizerThread. This is also an interface between the FinalizerThread * object at the SUT level and it corresponding FinalizerThreadInfo object at the JPF * level. */ public class JPF_gov_nasa_jpf_FinalizerThread extends NativePeer { @MJI public void runFinalizer__Ljava_lang_Object_2__V (MJIEnv env, int tiRef, int objRef, FeatureExpr ctx) { int queueRef = env.getReferenceField(ctx, tiRef, "finalizeQueue").getValue(); Conditional<Integer>[] elements = env.getReferenceArrayObject(queueRef); if(elements.length>0 && elements[0].getValue()==objRef) { ThreadInfo finalizerTi = env.getThreadInfo(); ClassInfo objCi = env.getElementInfo(objRef).getClassInfo(); MethodInfo mi = objCi.getMethod("finalize()V", false); // create and push a stack frame for finalize()V DirectCallStackFrame frame = mi.createDirectCallStackFrame(ctx, finalizerTi, 0); frame.setReferenceArgument(ctx, 0, objRef, frame); finalizerTi.pushFrame(frame); removeElement(env, tiRef, objRef, ctx); } } // removes the very first element in the list, which is the last finalizable objects processed void removeElement(MJIEnv env, int tiRef, int objRef, FeatureExpr ctx) { int queueRef = env.getReferenceField(ctx, tiRef, "finalizeQueue").getValue(); ThreadInfo ti = env.getThreadInfo(); Conditional<Integer>[] oldValues = env.getReferenceArrayObject(queueRef); assert (objRef == oldValues[0].getValue()); assert (oldValues.length>0); int len = oldValues.length - 1; ElementInfo newQueue = env.getHeap().newArray(ctx, "Ljava/lang/Object;", len, ti); Conditional<Integer>[] newValues = newQueue.asReferenceArray(); System.arraycopy(oldValues, 1, newValues, 0, len); env.getModifiableElementInfo(tiRef).setReferenceField(ctx, "finalizeQueue", new One<>(newQueue.getObjectRef())); } // a predicate to obtain all alive, non-finalizer threads within the ti process Predicate<ThreadInfo> getAppAliveUserPredicate (final ThreadInfo ti){ return new Predicate<ThreadInfo>(){ public boolean isTrue (ThreadInfo t){ return (t.isAlive() && !t.isSystemThread() && t.appCtx == ti.appCtx); } }; } @MJI public void manageState____V (MJIEnv env, int objref, FeatureExpr ctx){ ApplicationContext appCtx = env.getVM().getApplicationContext(objref); FinalizerThreadInfo finalizerTi = appCtx.getFinalizerThread(); VM vm = env.getVM(); // check for termination - Note that the finalizer thread has to be the last alive thread // of the process if(!vm.getThreadList().hasAnyMatching(getAppAliveUserPredicate(finalizerTi))) { shutdown(env, objref, ctx); } // make the thread wait until more objects are added to finalizerQueue else { finalizerTi.waitOnSemaphore(); assert finalizerTi.isWaiting(); ChoiceGenerator<ThreadInfo> cg = env.getSystemState().getSchedulerFactory().createPostFinalizeCG(finalizerTi); env.getSystemState().setMandatoryNextChoiceGenerator(cg, "finalizeQueue processe without CG: "); } } protected void shutdown(MJIEnv env, int objRef, FeatureExpr ctx) { env.getModifiableElementInfo(objRef).setBooleanField(ctx, "done", One.TRUE); } }