// // Copyright (C) 2011 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.listener; import java.io.PrintWriter; import java.util.Arrays; import gov.nasa.jpf.Config; import gov.nasa.jpf.ListenerAdapter; import gov.nasa.jpf.jvm.bytecode.InstanceFieldInstruction; import gov.nasa.jpf.jvm.bytecode.InstanceInvocation; import gov.nasa.jpf.vm.ElementInfo; import gov.nasa.jpf.vm.Instruction; import gov.nasa.jpf.vm.StackFrame; import gov.nasa.jpf.vm.ThreadInfo; import gov.nasa.jpf.vm.VM; /** * tiny utility listener that can be used to find out where a certain * object (specified by reference) gets allocated or accessed (call or field), * and when it gets gc'ed */ public class ReferenceLocator extends ListenerAdapter { PrintWriter pw; int[] createRefs; int[] releaseRefs; int[] useRefs; public ReferenceLocator (Config conf){ createRefs = sort( conf.getIntArray("refloc.create")); releaseRefs = sort( conf.getIntArray("refloc.release")); useRefs = sort( conf.getIntArray("refloc.use")); // <2do> we might want to configure output destination pw = new PrintWriter(System.out, true); } protected int[] sort(int[] a){ if (a != null){ Arrays.sort(a); } return a; } protected void printLocation(String msg, ThreadInfo ti){ pw.println(msg); for (StackFrame frame : ti) { pw.print("\tat "); pw.println(frame.getStackTraceInfo()); } pw.println(); } @Override public void objectCreated (VM vm, ThreadInfo ti, ElementInfo ei){ int ref = ei.getObjectRef(); if (createRefs != null && Arrays.binarySearch(createRefs, ref) >= 0){ printLocation("[ReferenceLocator] object " + ei + " created at:", ti); } } @Override public void objectReleased (VM vm, ThreadInfo ti, ElementInfo ei){ int ref = ei.getObjectRef(); if (releaseRefs != null && Arrays.binarySearch(releaseRefs, ref) >= 0){ pw.println("[ReferenceLocator] object " + ei + " released"); } } @Override public void instructionExecuted (VM vm, ThreadInfo ti, Instruction nextInsn, Instruction executedInsn){ if (useRefs != null){ if (executedInsn instanceof InstanceInvocation) { int ref = ((InstanceInvocation)executedInsn).getCalleeThis(ti); if (Arrays.binarySearch(useRefs, ref) >= 0){ printLocation("[ReferenceLocator] call on object " + ti.getElementInfo(ref) + " at:", ti); } } else if (executedInsn instanceof InstanceFieldInstruction){ int ref = ((InstanceFieldInstruction)executedInsn).getLastThis(); if (Arrays.binarySearch(useRefs, ref) >= 0){ printLocation("[ReferenceLocator] field access of " + ti.getElementInfo(ref) + " at:", ti); } } } } }