diff --git a/src/org/ntlab/deltaViewer/CollaborationLayout.java b/src/org/ntlab/deltaViewer/CollaborationLayout.java index 2469a6b..0cc39a0 100644 --- a/src/org/ntlab/deltaViewer/CollaborationLayout.java +++ b/src/org/ntlab/deltaViewer/CollaborationLayout.java @@ -1,481 +1,548 @@ -package org.ntlab.deltaViewer; - -import java.util.AbstractMap; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.ntlab.deltaExtractor.Alias; -import org.ntlab.deltaExtractor.Alias.AliasType; -import org.ntlab.deltaExtractor.IAliasCollector; -import org.ntlab.trace.ArrayAccess; -import org.ntlab.trace.ArrayCreate; -import org.ntlab.trace.ArrayUpdate; -import org.ntlab.trace.FieldAccess; -import org.ntlab.trace.FieldUpdate; -import org.ntlab.trace.MethodExecution; -import org.ntlab.trace.MethodInvocation; -import org.ntlab.trace.Reference; -import org.ntlab.trace.Statement; - -import com.mxgraph.model.mxICell; -import com.mxgraph.util.mxPoint; - -public class CollaborationLayout implements IObjectLayout { - private static final int angleStep = 15; - private mxPoint coordinatorPoint = new mxPoint(0, 100); - private double step; - private double padding; - - @Override - public void execute(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector, Map objectToVertexMap) { - step = 150; - padding = 200; - - // Extract the bottom reference. - Statement relatedSt = objectCallGraph.getRelatedPoints().get(objectCallGraph.getRelatedPoints().size() - 1).getStatement(); - String bottomSrcObjId = null; - String bottomDstObjId = null; - if (relatedSt instanceof FieldUpdate) { - // container to component - bottomSrcObjId = ((FieldUpdate) relatedSt).getContainerObjId(); - bottomDstObjId = ((FieldUpdate) relatedSt).getValueObjId(); - } else if (relatedSt instanceof ArrayUpdate) { - // container to component - bottomSrcObjId = ((ArrayUpdate) relatedSt).getArrayObjectId(); - bottomDstObjId = ((ArrayUpdate) relatedSt).getValueObjectId(); - } else if (relatedSt instanceof MethodInvocation) { - MethodInvocation methodInvStatement = (MethodInvocation) relatedSt; - MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution(); - String methodSignature = calledMethodExec.getSignature(); - if (calledMethodExec.isCollectionType() - && (methodSignature.contains("add(") - || methodSignature.contains("set(") - || methodSignature.contains("put(") - || methodSignature.contains("push(") - || methodSignature.contains("addElement("))) { - // container to component - bottomSrcObjId = calledMethodExec.getThisObjId(); - bottomDstObjId = calledMethodExec.getArguments().get(0).getId(); - } else { - // this to another - bottomSrcObjId = methodInvStatement.getThisObjId(); - bottomDstObjId = calledMethodExec.getReturnValue().getId(); - } - } else { - return; - } - - // Extract the reference access history. - List references = objectCallGraph.getReferences(); - Map> referenceHistory = new HashMap<>(); - int order = 0; - for (Alias a: aliasCollector.getAliasList()) { - int idx = -1; - if (a.getAliasType() == AliasType.FIELD) { - FieldAccess f = (FieldAccess) a.getOccurrencePoint().getStatement(); - idx = references.indexOf(new Reference(f.getContainerObjId(), f.getValueObjId(), f.getContainerClassName(), f.getValueClassName())); - } else if (a.getAliasType() == AliasType.ARRAY_ELEMENT) { - ArrayAccess aa = (ArrayAccess) a.getOccurrencePoint().getStatement(); - idx = references.indexOf(new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName())); - } else if (a.getAliasType() == AliasType.RETURN_VALUE) { - MethodExecution methodExec = a.getMethodExecution(); - if (methodExec.getSignature().contains("List.get(") || - methodExec.getSignature().contains("Map.get(")) { - String srcObjId = methodExec.getThisObjId(); - String dstObjId = methodExec.getReturnValue().getId(); - String srcClassName = methodExec.getThisClassName(); - String dstClassName = methodExec.getReturnValue().getActualType(); - idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); - } - } else if (a.getAliasType() == AliasType.CONSTRACTOR_INVOCATION) { - MethodInvocation c = (MethodInvocation) a.getOccurrencePoint().getStatement(); - String srcObjId = a.getMethodExecution().getThisObjId(); - String dstObjId = c.getCalledMethodExecution().getThisObjId(); - String srcClassName = a.getMethodExecution().getThisClassName(); - String dstClassName = c.getCalledMethodExecution().getThisClassName(); - idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); - } else if (a.getAliasType() == AliasType.ARRAY_CREATE) { - ArrayCreate ac = (ArrayCreate) a.getOccurrencePoint().getStatement(); - String srcObjId = a.getMethodExecution().getThisObjId(); - String srcClassName = a.getMethodExecution().getThisClassName(); - idx = references.indexOf(new Reference(srcObjId, ac.getArrayObjectId(), srcClassName, ac.getArrayClassName())); - } - if (idx >= 0) { - Reference r = references.get(idx); - List rHIstory = referenceHistory.get(r); - if (rHIstory == null) { - rHIstory = new ArrayList<>(); - referenceHistory.put(r, rHIstory); - } - rHIstory.add(order); - } - order++; - } - - // Construct the object graph. - Map> preds = new HashMap<>(); - Map> succs = new HashMap<>(); - for (Reference r: references) { - String dstObjId = r.getDstObjectId(); - List pre = preds.get(dstObjId); - if (pre == null) { - pre = new ArrayList(); - preds.put(dstObjId, pre); - } - pre.add(r); - String srcObjId = r.getSrcObjectId(); - List suc = succs.get(srcObjId); - if (suc == null) { - suc = new ArrayList(); - succs.put(srcObjId, suc); - } - suc.add(r); - } - - // Extract the source side and destination side paths. - String topObjId = objectCallGraph.getStartPoints().get(0).getThisObjId(); - List dstSide = new ArrayList<>(); - List dstSideObjects = new ArrayList<>(); - String dstObjId = bottomDstObjId; - dstSideObjects.add(dstObjId); - while (!dstObjId.equals(topObjId)) { - if (preds.get(dstObjId) != null) { - Reference minRef = getFirstReferece(preds.get(dstObjId), referenceHistory, true); - dstSide.add(minRef); - dstObjId = minRef.getSrcObjectId(); - } else { - dstSide.add(null); - dstObjId = topObjId; - } - dstSideObjects.add(dstObjId); - } - - List srcSide = new ArrayList<>(); - List srcSideObjects = new ArrayList<>(); - String srcObjId = bottomSrcObjId; - srcSideObjects.add(srcObjId); - while (!srcObjId.equals(topObjId)) { - if (preds.get(srcObjId) != null) { - Reference maxRef = getFirstReferece(preds.get(srcObjId), referenceHistory, false); - srcSide.add(maxRef); - srcObjId = maxRef.getSrcObjectId(); - } else { - srcSide.add(null); - srcObjId = topObjId; - } - srcSideObjects.add(srcObjId); - } - - // Fix the confluent points. - List> confluPoints = new ArrayList<>(); - boolean bConfluent = false; - int hight = 0; - int width = -1; - int dstHight = 0; - int srcHight = 0; - for (String srcObj: srcSideObjects) { - if (dstSideObjects.contains(srcObj)) { - if (!bConfluent) { - int dstDiff = dstSideObjects.indexOf(srcObj) - dstHight; - int srcDiff = srcSideObjects.indexOf(srcObj) - srcHight; - dstHight += dstDiff; - srcHight += srcDiff; - if (dstDiff > srcDiff) { - hight += dstDiff; - } else { - hight += srcDiff; - } - if (width < 0) width = dstHight; - confluPoints.add(new AbstractMap.SimpleEntry(srcObj, hight)); - bConfluent = true; - } else { - hight++; - } - } else { - bConfluent = false; - } - } - coordinatorPoint.setX(coordinatorPoint.getX() + step * width + padding); - double xCor = coordinatorPoint.getX(); - double yCor = coordinatorPoint.getY(); - Set fixed = new HashSet<>(); - for (Map.Entry confluPoint: confluPoints) { - setVertexCoordinate(objectToVertexMap.get(confluPoint.getKey()), xCor, yCor + (hight - confluPoint.getValue()) * step); - fixed.add(confluPoint.getKey()); - } - - // Fix the bottom objects. - Map.Entry firstConfl = confluPoints.get(0); - dstHight = hight - firstConfl.getValue() + dstSideObjects.indexOf(firstConfl.getKey()); - srcHight = hight - firstConfl.getValue() + srcSideObjects.indexOf(firstConfl.getKey()); - int width2 = srcSideObjects.indexOf(firstConfl.getKey()); - setVertexCoordinate(objectToVertexMap.get(bottomDstObjId), padding, yCor + dstHight * step); - fixed.add(bottomDstObjId); - setVertexCoordinate(objectToVertexMap.get(bottomSrcObjId), xCor + width2 * step, yCor + srcHight * step); - fixed.add(bottomSrcObjId); - - // Fix the destination side, source side and common path. - int srcIndex = 0; - int dstIndex = 0; - double dstDirection = 60; - double srcDirection = 120; - for (Map.Entry confluPoint: confluPoints) { - String conflObj = confluPoint.getKey(); - - // Fix the destination side path. - List path = dstSideObjects.subList(dstIndex, dstSideObjects.indexOf(conflObj) + 1); - if (path.size() > 2) fixPath(path, dstDirection, objectToVertexMap, fixed, true); - dstDirection = 120; - dstIndex = dstSideObjects.indexOf(conflObj); - - // Fix the source side path. - path = srcSideObjects.subList(srcIndex, srcSideObjects.indexOf(conflObj) + 1); - if (path.size() > 2) fixPath(path, srcDirection, objectToVertexMap, fixed, true); - srcDirection = 60; - srcIndex = srcSideObjects.indexOf(conflObj); - - // Fix the common path. - int commonHight = confluPoint.getValue(); - for (;;) { - commonHight++; - srcIndex++; - dstIndex++; - if (srcIndex >= srcSideObjects.size() || dstIndex >= dstSideObjects.size()) break; - if (!srcSideObjects.get(srcIndex).equals(dstSideObjects.get(dstIndex))) break; - String commonObjId = srcSideObjects.get(srcIndex); - setVertexCoordinate(objectToVertexMap.get(commonObjId), xCor, yCor + (hight - commonHight) * step); - fixed.add(commonObjId); - } - srcIndex--; - dstIndex--; - } - - // Fix the branches from the destination side path. - for (Reference ref: dstSide) { - if (ref != null) { - List nextRefs = new ArrayList<>(preds.get(ref.getDstObjectId())); - nextRefs = new ArrayList<>(nextRefs); - nextRefs.remove(ref); - double direction = getDirection(ref, objectToVertexMap) - angleStep; - while (nextRefs.size() > 0) { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); - List path = new ArrayList<>(); - path.add(firstRef.getDstObjectId()); - traversePreds(preds, firstRef, direction, true, referenceHistory, objectToVertexMap, fixed, path); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objectToVertexMap) - angleStep; - } - } - } - - // Fix the branches from the source side path. - for (Reference ref: srcSide) { - if (ref != null) { - List nextRefs = new ArrayList<>(preds.get(ref.getDstObjectId())); - nextRefs = new ArrayList<>(nextRefs); - nextRefs.remove(ref); - double direction = getDirection(ref, objectToVertexMap) + angleStep; - while (nextRefs.size() > 0) { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, false); - List path = new ArrayList<>(); - path.add(firstRef.getDstObjectId()); - traversePreds(preds, firstRef, direction, false, referenceHistory, objectToVertexMap, fixed, path); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objectToVertexMap) + angleStep; - } - } - } - - // Fix the reverse branches from the destination side path. - Collections.reverse(dstSide); - for (Reference ref: dstSide) { - if (ref != null) { - List nextRefs = new ArrayList<>(succs.get(ref.getSrcObjectId())); - nextRefs = new ArrayList<>(nextRefs); - nextRefs.remove(ref); - double direction = getDirection(ref, objectToVertexMap) + 180 + angleStep; - while (nextRefs.size() > 0) { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); - List path = new ArrayList<>(); - path.add(firstRef.getSrcObjectId()); - traverseSuccs(succs, firstRef, direction, true, referenceHistory, objectToVertexMap, fixed, path); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objectToVertexMap) + 180 + angleStep; - } - } - } - - // Fix the reverse branches from the source side path. - Collections.reverse(srcSide); - for (Reference ref: srcSide) { - if (ref != null) { - List nextRefs = new ArrayList<>(succs.get(ref.getSrcObjectId())); - nextRefs = new ArrayList<>(nextRefs); - nextRefs.remove(ref); - double direction = getDirection(ref, objectToVertexMap) + 180 - angleStep; - while (nextRefs.size() > 0) { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, false); - List path = new ArrayList<>(); - path.add(firstRef.getSrcObjectId()); - traverseSuccs(succs, firstRef, direction, false, referenceHistory, objectToVertexMap, fixed, path); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objectToVertexMap) + 180 - angleStep; - } - } - } - } - - private double getDirection(Reference ref, Map objToVtx) { - ObjectVertex src = objToVtx.get(ref.getSrcObjectId()); - ObjectVertex dst = objToVtx.get(ref.getDstObjectId()); - return Math.toDegrees(Math.atan2(dst.getY() - src.getY(), src.getX() - dst.getX())); - } - - private Reference getFirstReferece(List refs, Map> referenceHistory, boolean bLeftFirst) { - double first = 0.0; - Reference firstRef = null; - for (Reference ref: refs) { - double avgOrder = 0.0; - if (referenceHistory.get(ref) != null) { - for (int ord: referenceHistory.get(ref)) { - avgOrder += (double) ord; - } - avgOrder /= ((double) referenceHistory.get(ref).size()); - } - if (firstRef == null || (bLeftFirst && avgOrder < first) || (!bLeftFirst && avgOrder > first)) { - firstRef = ref; - first = avgOrder; - } - } - return firstRef; - } - - private void traversePreds(Map> preds, Reference ref, double direction, boolean bLeftFirst, Map> referenceHistory, Map objToVtx, Set fixed, List path) { - String curObj = ref.getSrcObjectId(); - path.add(curObj); - if (fixed.contains(curObj)) { - if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, true); - return; - } - List nextRefs = preds.get(curObj); - if (nextRefs == null || nextRefs.size() == 0) { - if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, false); - return; - } - nextRefs = new ArrayList<>(nextRefs); - do { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, bLeftFirst); - traversePreds(preds, firstRef, direction, bLeftFirst, referenceHistory, objToVtx, fixed, path); - path = new ArrayList<>(); - path.add(curObj); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objToVtx); - if (bLeftFirst) { - direction -= angleStep; - } else { - direction += angleStep; - } - } while (nextRefs.size() > 0); - return; - } - - - private void traverseSuccs(Map> succs, Reference ref, double direction, boolean bLeftFirst, Map> referenceHistory, Map objToVtx, Set fixed, List path) { - String curObj = ref.getDstObjectId(); - path.add(curObj); - if (fixed.contains(curObj)) { - if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, true); - return; - } - List nextRefs = succs.get(curObj); - if (nextRefs == null || nextRefs.size() == 0) { - if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, false); - return; - } - nextRefs = new ArrayList<>(nextRefs); - do { - Reference firstRef = getFirstReferece(nextRefs, referenceHistory, bLeftFirst); - traverseSuccs(succs, firstRef, direction, bLeftFirst, referenceHistory, objToVtx, fixed, path); - path = new ArrayList<>(); - path.add(curObj); - nextRefs.remove(firstRef); - direction = getDirection(firstRef, objToVtx) + 180; - if (bLeftFirst) { - direction += angleStep; - } else { - direction -= angleStep; - } - } while (nextRefs.size() > 0); - return; - } - - private void fixPath(List path, double direction, Map objToVtx, Set fixed, boolean bClose) { - if (path.size() < 2) return; - ObjectVertex start = objToVtx.get(path.get(0)); - double x = start.getX(); - double y = start.getY(); - double dirY = -Math.sin(Math.toRadians(direction)); - double dirX = Math.cos(Math.toRadians(direction)); - if (!bClose) { - // straight line - for (int i = 1; i < path.size(); i++) { - x += step * dirX; - y += step * dirY; - setVertexCoordinate(objToVtx.get(path.get(i)), x, y); - fixed.add(path.get(i)); - } - } else { - ObjectVertex end = objToVtx.get(path.get(path.size() - 1)); - double diffX = end.getX() - start.getX(); - double diffY = end.getY() - start.getY(); - double distance = Math.sqrt(diffX * diffX + diffY * diffY); - diffX /= distance; - diffY /= distance; - double outer = dirX * diffY - dirY * diffX; - double centerX, centerY, vecX, vecY; - double theta = Math.acos(diffX * dirX + diffY * dirY); - double radius = distance / 2 / Math.sin(theta); - if (outer > 0) { - vecX = -dirY; - vecY = dirX; - theta = theta * 2.0 / (double) (path.size() - 1); - } else if (outer < 0) { - vecX = dirY; - vecY = -dirX; - theta = -theta * 2.0 / (double) (path.size() - 1); - } else { - // straight line - diffX *= distance / (double) (path.size() - 1); - diffY *= distance / (double) (path.size() - 1); - for (int i = 1; i < path.size(); i++) { - x += diffX; - y += diffY; - setVertexCoordinate(objToVtx.get(path.get(i)), x, y); - fixed.add(path.get(i)); - } - return; - } - // arc - centerX = x + radius * vecX; - centerY = y + radius * vecY; - for (int i = 1; i < path.size() - 1; i++) { - double tmp = vecX * Math.cos(theta) - vecY * Math.sin(theta); - vecY = vecX * Math.sin(theta) + vecY * Math.cos(theta); - vecX = tmp; - setVertexCoordinate(objToVtx.get(path.get(i)), centerX - radius * vecX, centerY - radius * vecY); - fixed.add(path.get(i)); - } - } - } - - private void setVertexCoordinate(ObjectVertex vertex, double x, double y) { - vertex.setX(x); - vertex.setY(y); - vertex.setInitialPoint(x, y); - } -} +package org.ntlab.deltaViewer; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.ntlab.deltaExtractor.Alias; +import org.ntlab.deltaExtractor.Alias.AliasType; +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.trace.ArrayAccess; +import org.ntlab.trace.ArrayCreate; +import org.ntlab.trace.ArrayUpdate; +import org.ntlab.trace.FieldAccess; +import org.ntlab.trace.FieldUpdate; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.Reference; +import org.ntlab.trace.Statement; + +import com.mxgraph.model.mxICell; +import com.mxgraph.util.mxPoint; + +public class CollaborationLayout implements IObjectLayout { + private static final int angleStep = 15; + private mxPoint coordinatorPoint = new mxPoint(0, 100); + private double step; + private double padding; + + @Override + public void execute(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector, Map objectToVertexMap) { + step = 150; + padding = 200; + + // Extract the bottom reference. + Statement relatedSt = objectCallGraph.getRelatedPoints().get(objectCallGraph.getRelatedPoints().size() - 1).getStatement(); + String bottomSrcObjId = null; + String bottomDstObjId = null; + if (relatedSt instanceof FieldUpdate) { + // container to component + bottomSrcObjId = ((FieldUpdate) relatedSt).getContainerObjId(); + bottomDstObjId = ((FieldUpdate) relatedSt).getValueObjId(); + } else if (relatedSt instanceof ArrayUpdate) { + // container to component + bottomSrcObjId = ((ArrayUpdate) relatedSt).getArrayObjectId(); + bottomDstObjId = ((ArrayUpdate) relatedSt).getValueObjectId(); + } else if (relatedSt instanceof MethodInvocation) { + MethodInvocation methodInvStatement = (MethodInvocation) relatedSt; + MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution(); + String methodSignature = calledMethodExec.getSignature(); + if (calledMethodExec.isCollectionType() + && (methodSignature.contains("add(") + || methodSignature.contains("set(") + || methodSignature.contains("put(") + || methodSignature.contains("push(") + || methodSignature.contains("addElement("))) { + // container to component + bottomSrcObjId = calledMethodExec.getThisObjId(); + bottomDstObjId = calledMethodExec.getArguments().get(0).getId(); + } else { + // this to another + bottomSrcObjId = methodInvStatement.getThisObjId(); + bottomDstObjId = calledMethodExec.getReturnValue().getId(); + } + } else { + return; + } + + // Extract the reference access history. + List references = objectCallGraph.getReferences(); + Map> referenceHistory = new HashMap<>(); + int order = 0; + for (Alias a: aliasCollector.getAliasList()) { + int idx = -1; + if (a.getAliasType() == AliasType.FIELD) { + FieldAccess f = (FieldAccess) a.getOccurrencePoint().getStatement(); + idx = references.indexOf(new Reference(f.getContainerObjId(), f.getValueObjId(), f.getContainerClassName(), f.getValueClassName())); + } else if (a.getAliasType() == AliasType.ARRAY_ELEMENT) { + ArrayAccess aa = (ArrayAccess) a.getOccurrencePoint().getStatement(); + idx = references.indexOf(new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName())); + } else if (a.getAliasType() == AliasType.RETURN_VALUE) { + MethodExecution methodExec = a.getMethodExecution(); + if (methodExec.getSignature().contains("List.get(") || + methodExec.getSignature().contains("Map.get(")) { + String srcObjId = methodExec.getThisObjId(); + String dstObjId = methodExec.getReturnValue().getId(); + String srcClassName = methodExec.getThisClassName(); + String dstClassName = methodExec.getReturnValue().getActualType(); + idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); + } + } else if (a.getAliasType() == AliasType.CONSTRACTOR_INVOCATION) { + MethodInvocation c = (MethodInvocation) a.getOccurrencePoint().getStatement(); + String srcObjId = a.getMethodExecution().getThisObjId(); + String dstObjId = c.getCalledMethodExecution().getThisObjId(); + String srcClassName = a.getMethodExecution().getThisClassName(); + String dstClassName = c.getCalledMethodExecution().getThisClassName(); + idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); + } else if (a.getAliasType() == AliasType.ARRAY_CREATE) { + ArrayCreate ac = (ArrayCreate) a.getOccurrencePoint().getStatement(); + String srcObjId = a.getMethodExecution().getThisObjId(); + String srcClassName = a.getMethodExecution().getThisClassName(); + idx = references.indexOf(new Reference(srcObjId, ac.getArrayObjectId(), srcClassName, ac.getArrayClassName())); + } + if (idx >= 0) { + Reference r = references.get(idx); + List rHIstory = referenceHistory.get(r); + if (rHIstory == null) { + rHIstory = new ArrayList<>(); + referenceHistory.put(r, rHIstory); + } + rHIstory.add(order); + } + order++; + } + + // Construct the object graph. + Map> preds = new HashMap<>(); + Map> succs = new HashMap<>(); + for (Reference r: references) { + String dstObjId = r.getDstObjectId(); + List pre = preds.get(dstObjId); + if (pre == null) { + pre = new ArrayList(); + preds.put(dstObjId, pre); + } + pre.add(r); + String srcObjId = r.getSrcObjectId(); + List suc = succs.get(srcObjId); + if (suc == null) { + suc = new ArrayList(); + succs.put(srcObjId, suc); + } + suc.add(r); + } + + // Extract the source side and destination side paths. + String topObjId = objectCallGraph.getStartPoints().get(0).getThisObjId(); + List dstSide = new ArrayList<>(); + List dstSideObjects = new ArrayList<>(); + String dstObjId = bottomDstObjId; + dstSideObjects.add(dstObjId); + while (!dstObjId.equals(topObjId)) { + if (preds.get(dstObjId) != null) { + Reference minRef = getFirstReferece(preds.get(dstObjId), referenceHistory, true); + dstSide.add(minRef); + dstObjId = minRef.getSrcObjectId(); + } else { + dstSide.add(null); + dstObjId = topObjId; + } + dstSideObjects.add(dstObjId); + } + + List srcSide = new ArrayList<>(); + List srcSideObjects = new ArrayList<>(); + String srcObjId = bottomSrcObjId; + srcSideObjects.add(srcObjId); + while (!srcObjId.equals(topObjId)) { + if (preds.get(srcObjId) != null) { + Reference maxRef = getFirstReferece(preds.get(srcObjId), referenceHistory, false); + srcSide.add(maxRef); + srcObjId = maxRef.getSrcObjectId(); + } else { + srcSide.add(null); + srcObjId = topObjId; + } + srcSideObjects.add(srcObjId); + } + + // Fix the confluent points. + List> confluPoints = new ArrayList<>(); + boolean bConfluent = false; + int hight = 0; + int width = -1; + int dstHight = 0; + int srcHight = 0; + for (String srcObj: srcSideObjects) { + if (dstSideObjects.contains(srcObj)) { + if (!bConfluent) { + int dstDiff = dstSideObjects.indexOf(srcObj) - dstHight; + int srcDiff = srcSideObjects.indexOf(srcObj) - srcHight; + dstHight += dstDiff; + srcHight += srcDiff; + if (dstDiff > srcDiff) { + hight += dstDiff; + } else { + hight += srcDiff; + } + if (width < 0) width = dstHight; + confluPoints.add(new AbstractMap.SimpleEntry(srcObj, hight)); + bConfluent = true; + } else { + hight++; + } + } else { + bConfluent = false; + } + } + coordinatorPoint.setX(coordinatorPoint.getX() + step * width + padding); + double xCor = coordinatorPoint.getX(); + double yCor = coordinatorPoint.getY(); + Set fixed = new HashSet<>(); + for (Map.Entry confluPoint: confluPoints) { + setVertexCoordinate(objectToVertexMap.get(confluPoint.getKey()), xCor, yCor + (hight - confluPoint.getValue()) * step); + fixed.add(confluPoint.getKey()); + } + + // Fix the bottom objects. + Map.Entry firstConfl = confluPoints.get(0); + dstHight = hight - firstConfl.getValue() + dstSideObjects.indexOf(firstConfl.getKey()); + srcHight = hight - firstConfl.getValue() + srcSideObjects.indexOf(firstConfl.getKey()); + int width2 = srcSideObjects.indexOf(firstConfl.getKey()); + setVertexCoordinate(objectToVertexMap.get(bottomDstObjId), padding, yCor + dstHight * step); + fixed.add(bottomDstObjId); + setVertexCoordinate(objectToVertexMap.get(bottomSrcObjId), xCor + width2 * step, yCor + srcHight * step); + fixed.add(bottomSrcObjId); + + // Fix the destination side, source side and common path. + int srcIndex = 0; + int dstIndex = 0; + double dstDirection = 60; + double srcDirection = 120; + for (Map.Entry confluPoint: confluPoints) { + String conflObj = confluPoint.getKey(); + + // Fix the destination side path. + List path = dstSideObjects.subList(dstIndex, dstSideObjects.indexOf(conflObj) + 1); + if (path.size() > 2) fixPath(path, dstDirection, objectToVertexMap, fixed, true); + dstDirection = 120; + dstIndex = dstSideObjects.indexOf(conflObj); + + // Fix the source side path. + path = srcSideObjects.subList(srcIndex, srcSideObjects.indexOf(conflObj) + 1); + if (path.size() > 2) fixPath(path, srcDirection, objectToVertexMap, fixed, true); + srcDirection = 60; + srcIndex = srcSideObjects.indexOf(conflObj); + + // Fix the common path. + int commonHight = confluPoint.getValue(); + for (;;) { + commonHight++; + srcIndex++; + dstIndex++; + if (srcIndex >= srcSideObjects.size() || dstIndex >= dstSideObjects.size()) break; + if (!srcSideObjects.get(srcIndex).equals(dstSideObjects.get(dstIndex))) break; + String commonObjId = srcSideObjects.get(srcIndex); + setVertexCoordinate(objectToVertexMap.get(commonObjId), xCor, yCor + (hight - commonHight) * step); + fixed.add(commonObjId); + } + srcIndex--; + dstIndex--; + } + + // Fix the branches from the destination side path. + for (Reference ref: dstSide) { + if (ref != null) { + List nextRefs = new ArrayList<>(preds.get(ref.getDstObjectId())); + nextRefs = new ArrayList<>(nextRefs); + nextRefs.remove(ref); + double direction = getDirection(ref, objectToVertexMap) - angleStep; + while (nextRefs.size() > 0) { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); + List path = new ArrayList<>(); + path.add(firstRef.getDstObjectId()); + traversePreds(preds, firstRef, direction, true, referenceHistory, objectToVertexMap, fixed, path); + nextRefs.remove(firstRef); + direction = getDirection(firstRef, objectToVertexMap) - angleStep; + } + } + } + + // Fix the branches from the source side path. + for (Reference ref: srcSide) { + if (ref != null) { + List nextRefs = new ArrayList<>(preds.get(ref.getDstObjectId())); + nextRefs = new ArrayList<>(nextRefs); + nextRefs.remove(ref); + double direction = getDirection(ref, objectToVertexMap) + angleStep; + while (nextRefs.size() > 0) { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, false); + List path = new ArrayList<>(); + path.add(firstRef.getDstObjectId()); + traversePreds(preds, firstRef, direction, false, referenceHistory, objectToVertexMap, fixed, path); + nextRefs.remove(firstRef); + direction = getDirection(firstRef, objectToVertexMap) + angleStep; + } + } + } + + // Fix the reverse branches from the destination side path. + Collections.reverse(dstSide); + for (Reference ref: dstSide) { + if (ref != null) { + List nextRefs = new ArrayList<>(succs.get(ref.getSrcObjectId())); + if (nextRefs.size() > 1) { + nextRefs = new ArrayList<>(nextRefs); + List nextRefs2 = new ArrayList<>(); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); + nextRefs2.add(firstRef); + nextRefs.remove(firstRef); + } while (nextRefs.size() > 1); + nextRefs2.add(nextRefs.remove(0)); + + if (nextRefs2.indexOf(ref) > 0) { + nextRefs = nextRefs2.subList(0, nextRefs2.indexOf(ref)); + double direction = getDirection(ref, objectToVertexMap) + 180 - angleStep; + Collections.reverse(nextRefs); + for (Reference r: nextRefs) { + List path = new ArrayList<>(); + path.add(r.getSrcObjectId()); + traverseSuccs(succs, r, direction, true, referenceHistory, objectToVertexMap, fixed, path); + direction = getDirection(r, objectToVertexMap) + 180 - angleStep; + } + } + + if (nextRefs2.indexOf(ref) < nextRefs2.size() - 1) { + nextRefs = nextRefs2.subList(nextRefs2.indexOf(ref) + 1, nextRefs2.size()); + double direction = getDirection(ref, objectToVertexMap) + 180 + angleStep; + for (Reference r: nextRefs) { + List path = new ArrayList<>(); + path.add(r.getSrcObjectId()); + traverseSuccs(succs, r, direction, true, referenceHistory, objectToVertexMap, fixed, path); + direction = getDirection(r, objectToVertexMap) + 180 + angleStep; + } + } + } +// nextRefs = new ArrayList<>(nextRefs); +// nextRefs.remove(ref); +// double direction = getDirection(ref, objectToVertexMap) + 180 + angleStep; +// while (nextRefs.size() > 0) { +// Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); +// List path = new ArrayList<>(); +// path.add(firstRef.getSrcObjectId()); +// traverseSuccs(succs, firstRef, direction, true, referenceHistory, objectToVertexMap, fixed, path); +// nextRefs.remove(firstRef); +// direction = getDirection(firstRef, objectToVertexMap) + 180 + angleStep; +// } + } + } + + // Fix the reverse branches from the source side path. + Collections.reverse(srcSide); + for (Reference ref: srcSide) { + if (ref != null) { + List nextRefs = new ArrayList<>(succs.get(ref.getSrcObjectId())); + if (nextRefs.size() > 1) { + nextRefs = new ArrayList<>(nextRefs); + List nextRefs2 = new ArrayList<>(); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, false); + nextRefs2.add(firstRef); + nextRefs.remove(firstRef); + } while (nextRefs.size() > 1); + nextRefs2.add(nextRefs.remove(0)); + + if (nextRefs2.indexOf(ref) > 0) { + nextRefs = nextRefs2.subList(0, nextRefs2.indexOf(ref)); + double direction = getDirection(ref, objectToVertexMap) + 180 + angleStep; + Collections.reverse(nextRefs); + for (Reference r: nextRefs) { + List path = new ArrayList<>(); + path.add(r.getSrcObjectId()); + traverseSuccs(succs, r, direction, false, referenceHistory, objectToVertexMap, fixed, path); + direction = getDirection(r, objectToVertexMap) + 180 + angleStep; + } + } + + if (nextRefs2.indexOf(ref) < nextRefs2.size() - 1) { + nextRefs = nextRefs2.subList(nextRefs2.indexOf(ref) + 1, nextRefs2.size()); + double direction = getDirection(ref, objectToVertexMap) + 180 - angleStep; + for (Reference r: nextRefs) { + List path = new ArrayList<>(); + path.add(r.getSrcObjectId()); + traverseSuccs(succs, r, direction, false, referenceHistory, objectToVertexMap, fixed, path); + direction = getDirection(r, objectToVertexMap) + 180 - angleStep; + } + } + } +// List nextRefs = new ArrayList<>(succs.get(ref.getSrcObjectId())); +// nextRefs = new ArrayList<>(nextRefs); +// nextRefs.remove(ref); +// double direction = getDirection(ref, objectToVertexMap) + 180 - angleStep; +// while (nextRefs.size() > 0) { +// Reference firstRef = getFirstReferece(nextRefs, referenceHistory, false); +// List path = new ArrayList<>(); +// path.add(firstRef.getSrcObjectId()); +// traverseSuccs(succs, firstRef, direction, false, referenceHistory, objectToVertexMap, fixed, path); +// nextRefs.remove(firstRef); +// direction = getDirection(firstRef, objectToVertexMap) + 180 - angleStep; +// } + } + } + } + + private double getDirection(Reference ref, Map objToVtx) { + ObjectVertex src = objToVtx.get(ref.getSrcObjectId()); + ObjectVertex dst = objToVtx.get(ref.getDstObjectId()); + return Math.toDegrees(Math.atan2(dst.getY() - src.getY(), src.getX() - dst.getX())); + } + + private Reference getFirstReferece(List refs, Map> referenceHistory, boolean bLeftFirst) { + double first = 0.0; + Reference firstRef = null; + for (Reference ref: refs) { + double avgOrder = 0.0; + if (referenceHistory.get(ref) != null) { + for (int ord: referenceHistory.get(ref)) { + avgOrder += (double) ord; + } + avgOrder /= ((double) referenceHistory.get(ref).size()); + } + if (firstRef == null || (bLeftFirst && avgOrder < first) || (!bLeftFirst && avgOrder > first)) { + firstRef = ref; + first = avgOrder; + } + } + return firstRef; + } + + private void traversePreds(Map> preds, Reference ref, double direction, boolean bLeftFirst, Map> referenceHistory, Map objToVtx, Set fixed, List path) { + String curObj = ref.getSrcObjectId(); + path.add(curObj); + if (fixed.contains(curObj)) { + if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, true); + return; + } + List nextRefs = preds.get(curObj); + if (nextRefs == null || nextRefs.size() == 0) { + if (path.size() >= 2) fixPath(path, direction, objToVtx, fixed, false); + return; + } + nextRefs = new ArrayList<>(nextRefs); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, bLeftFirst); + traversePreds(preds, firstRef, direction, bLeftFirst, referenceHistory, objToVtx, fixed, path); + path = new ArrayList<>(); + path.add(curObj); + nextRefs.remove(firstRef); + direction = getDirection(firstRef, objToVtx); + if (bLeftFirst) { + direction -= angleStep; + } else { + direction += angleStep; + } + } while (nextRefs.size() > 0); + return; + } + + + private void traverseSuccs(Map> succs, Reference ref, double direction, boolean bLeftFirst, Map> referenceHistory, Map objToVtx, Set fixed, List path) { + String curObj = ref.getDstObjectId(); + path.add(curObj); + if (fixed.contains(curObj)) { + if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, true); + return; + } + List nextRefs = succs.get(curObj); + if (nextRefs == null || nextRefs.size() == 0) { + if (path.size() >= 2) fixPath(path, direction, objToVtx, fixed, false); + return; + } + nextRefs = new ArrayList<>(nextRefs); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, bLeftFirst); + traverseSuccs(succs, firstRef, direction, bLeftFirst, referenceHistory, objToVtx, fixed, path); + path = new ArrayList<>(); + path.add(curObj); + nextRefs.remove(firstRef); + direction = getDirection(firstRef, objToVtx) + 180; + if (bLeftFirst) { + direction += angleStep; + } else { + direction -= angleStep; + } + } while (nextRefs.size() > 0); + return; + } + + private void fixPath(List path, double direction, Map objToVtx, Set fixed, boolean bClose) { + if (path.size() < 2) return; + ObjectVertex start = objToVtx.get(path.get(0)); + double x = start.getX(); + double y = start.getY(); + double dirY = -Math.sin(Math.toRadians(direction)); + double dirX = Math.cos(Math.toRadians(direction)); + if (!bClose) { + // straight line + for (int i = 1; i < path.size(); i++) { + x += step * dirX; + y += step * dirY; + setVertexCoordinate(objToVtx.get(path.get(i)), x, y); + fixed.add(path.get(i)); + } + } else { + ObjectVertex end = objToVtx.get(path.get(path.size() - 1)); + double diffX = end.getX() - start.getX(); + double diffY = end.getY() - start.getY(); + double distance = Math.sqrt(diffX * diffX + diffY * diffY); + diffX /= distance; + diffY /= distance; + double outer = dirX * diffY - dirY * diffX; + double centerX, centerY, vecX, vecY; + double theta = Math.acos(diffX * dirX + diffY * dirY); + double radius = distance / 2 / Math.sin(theta); + if (outer > 0) { + vecX = -dirY; + vecY = dirX; + theta = theta * 2.0 / (double) (path.size() - 1); + } else if (outer < 0) { + vecX = dirY; + vecY = -dirX; + theta = -theta * 2.0 / (double) (path.size() - 1); + } else { + // straight line + diffX *= distance / (double) (path.size() - 1); + diffY *= distance / (double) (path.size() - 1); + for (int i = 1; i < path.size(); i++) { + x += diffX; + y += diffY; + setVertexCoordinate(objToVtx.get(path.get(i)), x, y); + fixed.add(path.get(i)); + } + return; + } + // arc + centerX = x + radius * vecX; + centerY = y + radius * vecY; + for (int i = 1; i < path.size() - 1; i++) { + double tmp = vecX * Math.cos(theta) - vecY * Math.sin(theta); + vecY = vecX * Math.sin(theta) + vecY * Math.cos(theta); + vecX = tmp; + setVertexCoordinate(objToVtx.get(path.get(i)), centerX - radius * vecX, centerY - radius * vecY); + fixed.add(path.get(i)); + } + } + } + + private void setVertexCoordinate(ObjectVertex vertex, double x, double y) { + vertex.setX(x); + vertex.setY(y); + vertex.setInitialPoint(x, y); + } +} diff --git a/src/org/ntlab/deltaViewer/CollaborationViewer.java b/src/org/ntlab/deltaViewer/CollaborationViewer.java index 0fd1514..743f923 100644 --- a/src/org/ntlab/deltaViewer/CollaborationViewer.java +++ b/src/org/ntlab/deltaViewer/CollaborationViewer.java @@ -362,13 +362,17 @@ objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), vertex, 0, 0)); } } else { - String srcClassName = ref.getSrcClassName(); - if (srcClassName.contains("[L")) { - srcClassName = formatArrayName(srcClassName); + if (!objectToVertexMap.containsKey(ref.getSrcObjectId())) { + String srcClassName = ref.getSrcClassName(); + if (srcClassName.contains("[L")) { + srcClassName = formatArrayName(srcClassName); + } + Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. + objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0)); } - Object vertex = mxgraph.insertDeltaVertex(mxDefaultParent, ref.getSrcObjectId(), srcClassName, 0, 0, vertexObjWidth, vertexObjHeight, "fillColor=white"); //creates a white vertex. - objectToVertexMap.put(ref.getSrcObjectId(), new ObjectVertex(ref.getSrcClassName(), vertex, 0, 0)); - objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), null, 0, 0)); + if (!objectToVertexMap.containsKey(ref.getDstObjectId())) { + objectToVertexMap.put(ref.getDstObjectId(), new ObjectVertex(ref.getDstClassName(), null, 0, 0)); + } } } } finally { diff --git a/src/org/ntlab/deltaViewer/DeltaLayout.java b/src/org/ntlab/deltaViewer/DeltaLayout.java index a1ed444..1e61841 100644 --- a/src/org/ntlab/deltaViewer/DeltaLayout.java +++ b/src/org/ntlab/deltaViewer/DeltaLayout.java @@ -7,6 +7,7 @@ import java.util.Set; import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.trace.ArrayUpdate; import org.ntlab.trace.FieldUpdate; import org.ntlab.trace.MethodExecution; import org.ntlab.trace.MethodInvocation; @@ -25,8 +26,13 @@ String srcObjId = null; String dstObjId = null; if (relatedSt instanceof FieldUpdate) { + // container to component srcObjId = ((FieldUpdate) relatedSt).getContainerObjId(); dstObjId = ((FieldUpdate) relatedSt).getValueObjId(); + } else if (relatedSt instanceof ArrayUpdate) { + // container to component + srcObjId = ((ArrayUpdate) relatedSt).getArrayObjectId(); + dstObjId = ((ArrayUpdate) relatedSt).getValueObjectId(); } else if (relatedSt instanceof MethodInvocation) { MethodInvocation methodInvStatement = (MethodInvocation) relatedSt; MethodExecution calledMethodExec = methodInvStatement.getCalledMethodExecution(); @@ -37,10 +43,13 @@ || methodSignature.contains("put(") || methodSignature.contains("push(") || methodSignature.contains("addElement("))) { + // container to component srcObjId = calledMethodExec.getThisObjId(); dstObjId = calledMethodExec.getArguments().get(0).getId(); } else { - return; + // this to another + srcObjId = methodInvStatement.getThisObjId(); + dstObjId = calledMethodExec.getReturnValue().getId(); } } else { return; diff --git a/src/org/ntlab/deltaViewer/ForwardAliasCollector.java b/src/org/ntlab/deltaViewer/ForwardAliasCollector.java new file mode 100644 index 0000000..3df10fc --- /dev/null +++ b/src/org/ntlab/deltaViewer/ForwardAliasCollector.java @@ -0,0 +1,222 @@ +package org.ntlab.deltaViewer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.ntlab.deltaExtractor.Alias; +import org.ntlab.deltaExtractor.Alias.AliasType; +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.trace.ArrayAccess; +import org.ntlab.trace.ArrayCreate; +import org.ntlab.trace.ArrayUpdate; +import org.ntlab.trace.FieldAccess; +import org.ntlab.trace.FieldUpdate; +import org.ntlab.trace.IStatementVisitor; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.AbstractTracePointVisitor; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.ObjectReference; +import org.ntlab.trace.Reference; +import org.ntlab.trace.Statement; +import org.ntlab.trace.TracePoint; + +public class ForwardAliasCollector extends AbstractTracePointVisitor implements IAliasCollector { + private List aliasList = new ArrayList<>(); + private FullObjectCallGraph objectCallGraph; + private TracePoint firstTracePoint = null; + + public ForwardAliasCollector() { + objectCallGraph = new FullObjectCallGraph(); + } + + @Override + public boolean preVisitStatement(Statement statement, TracePoint tp) { + if (firstTracePoint == null) { + objectCallGraph.addStartPoint(tp.getMethodExecution()); + firstTracePoint = tp.duplicate(); + // for MagnetRON + Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate()); + addAlias(thisAlias); + } + if (statement instanceof MethodInvocation) { + MethodInvocation mi = (MethodInvocation) statement; + String methodSignature = mi.getCalledMethodExecution().getSignature(); + if (!methodSignature.contains("")) { + // Not a class initializer. + if (!mi.getCalledMethodExecution().isConstructor()) { + String receiver = mi.getCalledMethodExecution().getThisObjId(); + Alias recerverAlias = new Alias(AliasType.RECEIVER, 0, receiver, tp.duplicate()); + addAlias(recerverAlias); + } + int index = 0; + for (ObjectReference arg: mi.getCalledMethodExecution().getArguments()) { + Alias argAlias = new Alias(AliasType.ACTUAL_ARGUMENT, index, arg.getId(), tp.duplicate()); + addAlias(argAlias); + index++; + } + if (mi.getCalledMethodExecution().isCollectionType() + && (methodSignature.contains("add(") + || methodSignature.contains("set(") + || methodSignature.contains("put(") + || methodSignature.contains("push(") + || methodSignature.contains("addElement("))) { + objectCallGraph.addRelatedPoint(tp.duplicate()); + } + index = 0; + for (ObjectReference arg: mi.getCalledMethodExecution().getArguments()) { + Alias argAlias = new Alias(AliasType.FORMAL_PARAMETER, index, arg.getId(), mi.getCalledMethodExecution().getEntryPoint()); + addAlias(argAlias); + index++; + } + } + } else if (statement instanceof FieldAccess) { + FieldAccess fa = (FieldAccess) statement; + if (fa.getContainerObjId().equals(fa.getThisObjId())) { + Alias thisAlias = new Alias(AliasType.THIS, 0, fa.getThisObjId(), tp.duplicate()); + addAlias(thisAlias); + } else { + Alias containerAlias = new Alias(AliasType.CONTAINER, 0, fa.getContainerObjId(), tp.duplicate()); + addAlias(containerAlias); + } + Alias fieldAlias = new Alias(AliasType.FIELD, 0, fa.getValueObjId(), tp.duplicate()); + addAlias(fieldAlias); + objectCallGraph.addReference(fa.getReference()); + } else if (statement instanceof FieldUpdate) { + FieldUpdate fu = (FieldUpdate) statement; + if (!fu.getValueClassName().equals("---")) { + // Updated by a non-null value. + if (fu.getContainerObjId().equals(tp.getMethodExecution().getThisObjId())) { + Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate()); + addAlias(thisAlias); + } else { + Alias containerAlias = new Alias(AliasType.CONTAINER, 0, fu.getContainerObjId(), tp.duplicate()); + addAlias(containerAlias); + } + objectCallGraph.addRelatedPoint(tp.duplicate()); + } + } else if (statement instanceof ArrayCreate) { + ArrayCreate ac = (ArrayCreate) statement; + Alias thisAlias = new Alias(AliasType.THIS, 0, tp.getMethodExecution().getThisObjId(), tp.duplicate()); + addAlias(thisAlias); + Alias arrayCreateAlias = new Alias(AliasType.ARRAY_CREATE, 0, ac.getArrayObjectId(), tp.duplicate()); + addAlias(arrayCreateAlias); + Reference ref = new Reference(tp.getMethodExecution().getThisObjId(), ac.getArrayObjectId(), tp.getMethodExecution().getThisClassName(), ac.getArrayClassName()); + ref.setCreation(true); + objectCallGraph.addReference(ref); + } else if (statement instanceof ArrayAccess) { + ArrayAccess aa = (ArrayAccess) statement; + Alias arrayAlias = new Alias(AliasType.ARRAY, 0, aa.getArrayObjectId(), tp.duplicate()); + addAlias(arrayAlias); + Alias arrayElementAlias = new Alias(AliasType.ARRAY_ELEMENT, aa.getIndex(), aa.getValueObjectId(), tp.duplicate()); + addAlias(arrayElementAlias); + Reference ref = new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName()); + ref.setArray(true); + objectCallGraph.addReference(ref); + } else if (statement instanceof ArrayUpdate) { + ArrayUpdate au = (ArrayUpdate) statement; + Alias arrayAlias = new Alias(AliasType.ARRAY, 0, au.getArrayObjectId(), tp.duplicate()); + addAlias(arrayAlias); + objectCallGraph.addRelatedPoint(tp.duplicate()); + } + return false; + } + + @Override + public boolean postVisitStatement(Statement statement, TracePoint tp) { + if (statement instanceof MethodInvocation) { + MethodInvocation mi = (MethodInvocation) statement; + String returnValue = mi.getCalledMethodExecution().getReturnValue().getId(); + String methodSignature = mi.getCalledMethodExecution().getSignature(); + if (!methodSignature.contains("")) { + // Not a class initializer. + if (!mi.getCalledMethodExecution().isConstructor()) { + if (!mi.getCalledMethodExecution().getReturnValue().getActualType().equals("void")) { + Alias returnAlias = new Alias(AliasType.RETURN_VALUE, 0, returnValue, mi.getCalledMethodExecution().getExitPoint()); + addAlias(returnAlias); + } + Alias methodInvAlias = new Alias(AliasType.METHOD_INVOCATION, 0, returnValue, tp.duplicate()); + addAlias(methodInvAlias); + if (methodSignature.contains("List.get(") || + methodSignature.contains("Map.get(")) { + String returnClass = mi.getCalledMethodExecution().getReturnValue().getActualType(); + Reference ref = new Reference(mi.getCalledMethodExecution().getThisObjId(), returnValue, mi.getCalledMethodExecution().getThisClassName(), returnClass); + ref.setCollection(true); + objectCallGraph.addReference(ref); + } + } else { + Alias methodInvAlias = new Alias(AliasType.CONSTRACTOR_INVOCATION, 0, returnValue, tp.duplicate()); + addAlias(methodInvAlias); + String returnClass = mi.getCalledMethodExecution().getReturnValue().getActualType(); + Reference ref = new Reference(tp.getMethodExecution().getThisObjId(), returnValue, tp.getMethodExecution().getThisClassName(), returnClass); + ref.setCreation(true); + objectCallGraph.addReference(ref); + } + } + } else if (statement instanceof FieldAccess) { + + } else if (statement instanceof FieldUpdate) { + + } else if (statement instanceof ArrayCreate) { + + } else if (statement instanceof ArrayAccess) { + + } else if (statement instanceof ArrayUpdate) { + + } + return false; + } + + @Override + public void addAlias(Alias alias) { + aliasList.add(alias); + } + + @Override + public List getAliasList() { + return aliasList; + } + + public IObjectCallGraph getObjectCallGraph() { + return objectCallGraph; + } + + private class FullObjectCallGraph implements IObjectCallGraph { + private List references = new ArrayList<>(); + private List startPoints = new ArrayList<>(); + private List relatedPoints = new ArrayList<>(); + + public void addReference(Reference r) { + if (!references.contains(r)) references.add(r); + } + + public void addStartPoint(MethodExecution me) { + startPoints.add(me); + } + + public void addRelatedPoint(TracePoint tp) { + relatedPoints.add(tp); + } + + @Override + public List getReferences() { + return references; + } + + @Override + public List getStartPoints() { + return startPoints; + } + + @Override + public List getRelatedPoints() { + return relatedPoints; + } + + @Override + public Map> getCallTree() { + return null; + } + + } +} diff --git a/src/org/ntlab/deltaViewer/ForwardLayout.java b/src/org/ntlab/deltaViewer/ForwardLayout.java new file mode 100644 index 0000000..7b307df --- /dev/null +++ b/src/org/ntlab/deltaViewer/ForwardLayout.java @@ -0,0 +1,248 @@ +package org.ntlab.deltaViewer; + +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.ntlab.deltaExtractor.Alias; +import org.ntlab.deltaExtractor.Alias.AliasType; +import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.trace.ArrayAccess; +import org.ntlab.trace.ArrayCreate; +import org.ntlab.trace.ArrayUpdate; +import org.ntlab.trace.FieldAccess; +import org.ntlab.trace.FieldUpdate; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; +import org.ntlab.trace.Reference; +import org.ntlab.trace.Statement; + +import com.mxgraph.model.mxICell; +import com.mxgraph.util.mxPoint; + +public class ForwardLayout implements IObjectLayout { + private static final int angleStep = 15; + private mxPoint coordinatorPoint = new mxPoint(0, 100); + private double step; + private double padding; + + @Override + public void execute(IObjectCallGraph objectCallGraph, IAliasCollector aliasCollector, Map objectToVertexMap) { + step = 150; + padding = 200; + + // Extract the reference access history. + List references = objectCallGraph.getReferences(); + Map> referenceHistory = new HashMap<>(); + int order = 0; + for (Alias a: aliasCollector.getAliasList()) { + int idx = -1; + if (a.getAliasType() == AliasType.FIELD) { + FieldAccess f = (FieldAccess) a.getOccurrencePoint().getStatement(); + idx = references.indexOf(new Reference(f.getContainerObjId(), f.getValueObjId(), f.getContainerClassName(), f.getValueClassName())); + } else if (a.getAliasType() == AliasType.ARRAY_ELEMENT) { + ArrayAccess aa = (ArrayAccess) a.getOccurrencePoint().getStatement(); + idx = references.indexOf(new Reference(aa.getArrayObjectId(), aa.getValueObjectId(), aa.getArrayClassName(), aa.getValueClassName())); + } else if (a.getAliasType() == AliasType.RETURN_VALUE) { + MethodExecution methodExec = a.getMethodExecution(); + if (methodExec.getSignature().contains("List.get(") || + methodExec.getSignature().contains("Map.get(")) { + String srcObjId = methodExec.getThisObjId(); + String dstObjId = methodExec.getReturnValue().getId(); + String srcClassName = methodExec.getThisClassName(); + String dstClassName = methodExec.getReturnValue().getActualType(); + idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); + } + } else if (a.getAliasType() == AliasType.CONSTRACTOR_INVOCATION) { + MethodInvocation c = (MethodInvocation) a.getOccurrencePoint().getStatement(); + String srcObjId = a.getMethodExecution().getThisObjId(); + String dstObjId = c.getCalledMethodExecution().getThisObjId(); + String srcClassName = a.getMethodExecution().getThisClassName(); + String dstClassName = c.getCalledMethodExecution().getThisClassName(); + idx = references.indexOf(new Reference(srcObjId, dstObjId, srcClassName, dstClassName)); + } else if (a.getAliasType() == AliasType.ARRAY_CREATE) { + ArrayCreate ac = (ArrayCreate) a.getOccurrencePoint().getStatement(); + String srcObjId = a.getMethodExecution().getThisObjId(); + String srcClassName = a.getMethodExecution().getThisClassName(); + idx = references.indexOf(new Reference(srcObjId, ac.getArrayObjectId(), srcClassName, ac.getArrayClassName())); + } + if (idx >= 0) { + Reference r = references.get(idx); + List rHIstory = referenceHistory.get(r); + if (rHIstory == null) { + rHIstory = new ArrayList<>(); + referenceHistory.put(r, rHIstory); + } + rHIstory.add(order); + } + order++; + } + + // Construct the object graph. + Map> succs = new HashMap<>(); + for (Reference r: references) { + String srcObjId = r.getSrcObjectId(); + List suc = succs.get(srcObjId); + if (suc == null) { + suc = new ArrayList(); + succs.put(srcObjId, suc); + } + suc.add(r); + } + + // Fix the all paths from the top object. + double width = 2; + coordinatorPoint.setX(coordinatorPoint.getX() + step * width + padding); + double xCor = coordinatorPoint.getX(); + double yCor = coordinatorPoint.getY(); + Set fixed = new HashSet<>(); + + String topObjId = objectCallGraph.getStartPoints().get(0).getThisObjId(); + setVertexCoordinate(objectToVertexMap.get(topObjId), xCor, yCor); + fixed.add(topObjId); + + // Fix the reverse branches from the destination side path. + String curObjId = topObjId; + List nextRefs = new ArrayList<>(succs.get(curObjId)); + if (nextRefs.size() > 0) { + List nextRefs2 = new ArrayList<>(); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, true); + nextRefs2.add(firstRef); + nextRefs.remove(firstRef); + } while (nextRefs.size() > 1); + nextRefs2.add(nextRefs.remove(0)); + double direction = 210; + for (Reference r: nextRefs2) { + List path = new ArrayList<>(); + path.add(r.getSrcObjectId()); + traverseSuccs(succs, r, direction, true, referenceHistory, objectToVertexMap, fixed, path); + direction = getDirection(r, objectToVertexMap) + 180 + angleStep; + } + } + } + + private double getDirection(Reference ref, Map objToVtx) { + ObjectVertex src = objToVtx.get(ref.getSrcObjectId()); + ObjectVertex dst = objToVtx.get(ref.getDstObjectId()); + return Math.toDegrees(Math.atan2(dst.getY() - src.getY(), src.getX() - dst.getX())); + } + + private Reference getFirstReferece(List refs, Map> referenceHistory, boolean bLeftFirst) { + double first = 0.0; + Reference firstRef = null; + for (Reference ref: refs) { + double avgOrder = 0.0; + if (referenceHistory.get(ref) != null) { + for (int ord: referenceHistory.get(ref)) { + avgOrder += (double) ord; + } + avgOrder /= ((double) referenceHistory.get(ref).size()); + } + if (firstRef == null || (bLeftFirst && avgOrder < first) || (!bLeftFirst && avgOrder > first)) { + firstRef = ref; + first = avgOrder; + } + } + return firstRef; + } + + private void traverseSuccs(Map> succs, Reference ref, double direction, boolean bLeftFirst, Map> referenceHistory, Map objToVtx, Set fixed, List path) { + String curObj = ref.getDstObjectId(); + path.add(curObj); + if (fixed.contains(curObj)) { + if (path.size() > 2) fixPath(path, direction, objToVtx, fixed, true); + return; + } + List nextRefs = succs.get(curObj); + if (nextRefs == null || nextRefs.size() == 0) { + if (path.size() >= 2) fixPath(path, direction, objToVtx, fixed, false); + return; + } + nextRefs = new ArrayList<>(nextRefs); + do { + Reference firstRef = getFirstReferece(nextRefs, referenceHistory, bLeftFirst); + traverseSuccs(succs, firstRef, direction, bLeftFirst, referenceHistory, objToVtx, fixed, path); + path = new ArrayList<>(); + path.add(curObj); + nextRefs.remove(firstRef); + direction = getDirection(firstRef, objToVtx) + 180; + if (bLeftFirst) { + direction += angleStep; + } else { + direction -= angleStep; + } + } while (nextRefs.size() > 0); + return; + } + + private void fixPath(List path, double direction, Map objToVtx, Set fixed, boolean bClose) { + if (path.size() < 2) return; + ObjectVertex start = objToVtx.get(path.get(0)); + double x = start.getX(); + double y = start.getY(); + double dirY = -Math.sin(Math.toRadians(direction)); + double dirX = Math.cos(Math.toRadians(direction)); + if (!bClose) { + // straight line + for (int i = 1; i < path.size(); i++) { + x += step * dirX; + y += step * dirY; + setVertexCoordinate(objToVtx.get(path.get(i)), x, y); + fixed.add(path.get(i)); + } + } else { + ObjectVertex end = objToVtx.get(path.get(path.size() - 1)); + double diffX = end.getX() - start.getX(); + double diffY = end.getY() - start.getY(); + double distance = Math.sqrt(diffX * diffX + diffY * diffY); + diffX /= distance; + diffY /= distance; + double outer = dirX * diffY - dirY * diffX; + double centerX, centerY, vecX, vecY; + double theta = Math.acos(diffX * dirX + diffY * dirY); + double radius = distance / 2 / Math.sin(theta); + if (outer > 0) { + vecX = -dirY; + vecY = dirX; + theta = theta * 2.0 / (double) (path.size() - 1); + } else if (outer < 0) { + vecX = dirY; + vecY = -dirX; + theta = -theta * 2.0 / (double) (path.size() - 1); + } else { + // straight line + diffX *= distance / (double) (path.size() - 1); + diffY *= distance / (double) (path.size() - 1); + for (int i = 1; i < path.size(); i++) { + x += diffX; + y += diffY; + setVertexCoordinate(objToVtx.get(path.get(i)), x, y); + fixed.add(path.get(i)); + } + return; + } + // arc + centerX = x + radius * vecX; + centerY = y + radius * vecY; + for (int i = 1; i < path.size() - 1; i++) { + double tmp = vecX * Math.cos(theta) - vecY * Math.sin(theta); + vecY = vecX * Math.sin(theta) + vecY * Math.cos(theta); + vecX = tmp; + setVertexCoordinate(objToVtx.get(path.get(i)), centerX - radius * vecX, centerY - radius * vecY); + fixed.add(path.get(i)); + } + } + } + + private void setVertexCoordinate(ObjectVertex vertex, double x, double y) { + vertex.setX(x); + vertex.setY(y); + vertex.setInitialPoint(x, y); + } +} diff --git a/src/org/ntlab/trace/AbstractTracePointVisitor.java b/src/org/ntlab/trace/AbstractTracePointVisitor.java new file mode 100644 index 0000000..b12c12c --- /dev/null +++ b/src/org/ntlab/trace/AbstractTracePointVisitor.java @@ -0,0 +1,14 @@ +package org.ntlab.trace; + +abstract public class AbstractTracePointVisitor implements IStatementVisitor { + @Override + public boolean preVisitStatement(Statement statement) { // not called + return false; + } + @Override + public boolean postVisitStatement(Statement statement) { // not called + return false; + } + abstract public boolean preVisitStatement(Statement statement, TracePoint tp); + abstract public boolean postVisitStatement(Statement statement, TracePoint tp); +} diff --git a/src/org/ntlab/trace/Trace.java b/src/org/ntlab/trace/Trace.java index c0308ad..5b86def 100644 --- a/src/org/ntlab/trace/Trace.java +++ b/src/org/ntlab/trace/Trace.java @@ -969,9 +969,17 @@ while (curTp != null && (curTp.getStatement().getTimeStamp() <= nextThreadTime || nextThreadTime == -1)) { Statement statement = curTp.getStatement(); - if (visitor.preVisitStatement(statement)) return curTp; - if (!(statement instanceof MethodInvocation)) { - if (visitor.postVisitStatement(statement)) return curTp; + if (!(visitor instanceof AbstractTracePointVisitor)) { + if (visitor.preVisitStatement(statement)) return curTp; + if (!(statement instanceof MethodInvocation)) { + if (visitor.postVisitStatement(statement)) return curTp; + } + } else { + // �g���[�X�|�C���g�̏����K�v�ȏꍇ + if (((AbstractTracePointVisitor) visitor).preVisitStatement(statement, curTp)) return curTp; + if (!(statement instanceof MethodInvocation)) { + if (((AbstractTracePointVisitor) visitor).postVisitStatement(statement, curTp)) return curTp; + } } curTp.stepNoReturn(); // ���A�����ɌĂяo���؂�����Ă��� if (!curTp.isValid()) { @@ -979,7 +987,12 @@ while (!curTp.stepOver()) { // ���x�͕��A�͂��邪���炸�ɒT�� if (curTp.isValid()) { // �Ăяo����T���O�Ɉ�x�K��ς݂̃��\�b�h�Ăяo���s���A�T���������x�K�₷�� - if (visitor.postVisitStatement(curTp.getStatement())) return curTp; + if (!(visitor instanceof AbstractTracePointVisitor)) { + if (visitor.postVisitStatement(curTp.getStatement())) return curTp; + } else { + // �g���[�X�|�C���g�̏����K�v�ȏꍇ + if (((AbstractTracePointVisitor) visitor).postVisitStatement(curTp.getStatement(), curTp)) return curTp; + } } else { // �Ăяo���؂̊J�n���_�܂ŒT�����I�����ꍇ ArrayList roots = threadRoots.get(curThreadId); diff --git a/traces/Sample1_trace.txt b/traces/Sample1_trace.txt new file mode 100644 index 0000000..6035964 --- /dev/null +++ b/traces/Sample1_trace.txt @@ -0,0 +1,37 @@ +{"type":"classDef","name":"Main","path":"/C:/Users/student/runtime-EclipseApplication/Sample5/bin/Main.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static Main.()","class":"Main","args":[],"threadId":1,"time":655564330955600}, +{"type":"constructorExit","shortSignature":"Main.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655564357108400}, +{"type":"methodEntry","signature":"public static void Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"args":[{"class":"[Ljava.lang.String;","id":468121027}],"threadId":1,"time":655564357191000}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":5}, +{"type":"classDef","name":"A","path":"/C:/Users/student/runtime-EclipseApplication/Sample5/bin/A.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static A.()","class":"A","args":[],"threadId":1,"time":655564358427600}, +{"type":"constructorExit","shortSignature":"A.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655564358518500}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655564358534400}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655564358593700}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":2001049719},"threadId":1,"time":655564358777700}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":6}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655564358806400}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1927950199},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655564358843500}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":1927950199},"threadId":1,"time":655564358917400}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":7}, +{"type":"classDef","name":"B","path":"/C:/Users/student/runtime-EclipseApplication/Sample5/bin/B.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static B.()","class":"B","args":[],"threadId":1,"time":655564359636500}, +{"type":"constructorExit","shortSignature":"B.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655564359728000}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655564359742300}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":1746572565},"threadId":1,"time":655564359836600}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":8}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655564359867600}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":989110044},"threadId":1,"time":655564359944800}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":9}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":2001049719},"args":[{"class":"B","id":989110044}],"threadId":1,"time":655564359990300}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"B","id":989110044},"threadId":1,"lineNum":6,"time":655564360086000}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"void","id":0},"threadId":1,"time":655564360175100}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":10}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":1927950199},"args":[{"class":"B","id":1746572565}],"threadId":1,"time":655564360210300}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1927950199},"value":{"class":"B","id":1746572565},"threadId":1,"lineNum":6,"time":655564360287100}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":1927950199},"returnValue":{"class":"void","id":0},"threadId":1,"time":655564360361400}, +{"type":"methodCall","callerSideSignature":"A.getB()","threadId":1,"lineNum":11}, +{"type":"methodEntry","signature":"public B A.getB()","receiver":{"class":"A","id":2001049719},"args":[],"threadId":1,"time":655564360398300}, +{"type":"fieldGet","fieldName":"A.b","this":{"class":"A","id":2001049719},"container":{"class":"A","id":2001049719},"value":{"class":"B","id":989110044},"threadId":1,"lineNum":10,"time":655564360462500}, +{"type":"methodExit","shortSignature":"A.getB()","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"B","id":989110044},"threadId":1,"time":655564360664400}, +{"type":"methodExit","shortSignature":"Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"returnValue":{"class":"void","id":0},"threadId":1,"time":655564360719700}, diff --git a/traces/Sample2_trace.txt b/traces/Sample2_trace.txt new file mode 100644 index 0000000..8fb6800 --- /dev/null +++ b/traces/Sample2_trace.txt @@ -0,0 +1,37 @@ +{"type":"classDef","name":"Main","path":"/C:/Users/student/runtime-EclipseApplication/Sample6/bin/Main.class","loaderPath":"/"}, +{"type":"methodEntry","signature":"public static void Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"args":[{"class":"[Ljava.lang.String;","id":1160460865}],"threadId":1,"time":655617866004800}, +{"type":"blockEntry","methodSignature":"Main.main(java.lang.String[])","blockId":0,"incomings":0,"threadId":1,"lineNum":5,"time":655617866102600}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":5}, +{"type":"classDef","name":"A","path":"/C:/Users/student/runtime-EclipseApplication/Sample6/bin/A.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static A.()","class":"A","args":[],"threadId":1,"time":655617867318200}, +{"type":"constructorExit","shortSignature":"A.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655617877282800}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655617877308300}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1706377736},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655617888218000}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":1706377736},"threadId":1,"time":655617890616900}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":6}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655617890657200}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655617890876100}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":2001049719},"threadId":1,"time":655617890956900}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":7}, +{"type":"classDef","name":"B","path":"/C:/Users/student/runtime-EclipseApplication/Sample6/bin/B.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static B.()","class":"B","args":[],"threadId":1,"time":655617891867200}, +{"type":"constructorExit","shortSignature":"B.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655617891892600}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655617891905800}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":1927950199},"threadId":1,"time":655617891972900}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":8}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":1706377736},"args":[{"class":"B","id":1927950199}],"threadId":1,"time":655617892005800}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1706377736},"value":{"class":"B","id":1927950199},"threadId":1,"lineNum":6,"time":655617892182100}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":1706377736},"returnValue":{"class":"void","id":0},"threadId":1,"time":655617892264900}, +{"type":"methodCall","callerSideSignature":"A.getB()","threadId":1,"lineNum":9}, +{"type":"methodEntry","signature":"public B A.getB()","receiver":{"class":"A","id":1706377736},"args":[],"threadId":1,"time":655617892314200}, +{"type":"fieldGet","fieldName":"A.b","this":{"class":"A","id":1706377736},"container":{"class":"A","id":1706377736},"value":{"class":"B","id":1927950199},"threadId":1,"lineNum":10,"time":655617892358000}, +{"type":"methodExit","shortSignature":"A.getB()","receiver":{"class":"A","id":1706377736},"returnValue":{"class":"B","id":1927950199},"threadId":1,"time":655617892472200}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":10}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":2001049719},"args":[{"class":"B","id":1927950199}],"threadId":1,"time":655617892499400}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"B","id":1927950199},"threadId":1,"lineNum":6,"time":655617892543500}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"void","id":0},"threadId":1,"time":655617892651500}, +{"type":"methodCall","callerSideSignature":"A.getB()","threadId":1,"lineNum":11}, +{"type":"methodEntry","signature":"public B A.getB()","receiver":{"class":"A","id":2001049719},"args":[],"threadId":1,"time":655617892722200}, +{"type":"fieldGet","fieldName":"A.b","this":{"class":"A","id":2001049719},"container":{"class":"A","id":2001049719},"value":{"class":"B","id":1927950199},"threadId":1,"lineNum":10,"time":655617892799400}, +{"type":"methodExit","shortSignature":"A.getB()","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"B","id":1927950199},"threadId":1,"time":655617892848600}, +{"type":"methodExit","shortSignature":"Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"returnValue":{"class":"void","id":0},"threadId":1,"time":655617892866500}, diff --git a/traces/Sample3_trace.txt b/traces/Sample3_trace.txt new file mode 100644 index 0000000..3dc861d --- /dev/null +++ b/traces/Sample3_trace.txt @@ -0,0 +1,47 @@ +{"type":"classDef","name":"Main","path":"/C:/Users/student/runtime-EclipseApplication/Sample7/bin/Main.class","loaderPath":"/"}, +{"type":"methodEntry","signature":"public static void Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"args":[{"class":"[Ljava.lang.String;","id":1160460865}],"threadId":1,"time":655648643886100}, +{"type":"blockEntry","methodSignature":"Main.main(java.lang.String[])","blockId":0,"incomings":0,"threadId":1,"lineNum":5,"time":655648643987800}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":5}, +{"type":"classDef","name":"A","path":"/C:/Users/student/runtime-EclipseApplication/Sample7/bin/A.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655648645113600}, +{"type":"fieldSet","fieldName":"A.b1","container":{"class":"A","id":258952499},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655648645171500}, +{"type":"fieldSet","fieldName":"A.b2","container":{"class":"A","id":258952499},"value":{"class":"---","id":0},"threadId":1,"lineNum":4,"time":655648645198100}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":258952499},"threadId":1,"time":655648645220600}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":6}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655648645241100}, +{"type":"fieldSet","fieldName":"A.b1","container":{"class":"A","id":603742814},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655648645261700}, +{"type":"fieldSet","fieldName":"A.b2","container":{"class":"A","id":603742814},"value":{"class":"---","id":0},"threadId":1,"lineNum":4,"time":655648645281600}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":603742814},"threadId":1,"time":655648645294500}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":7}, +{"type":"classDef","name":"B","path":"/C:/Users/student/runtime-EclipseApplication/Sample7/bin/B.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655648646164100}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":1325547227},"threadId":1,"time":655648646192100}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":8}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655648646213600}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":980546781},"threadId":1,"time":655648646229800}, +{"type":"methodCall","callerSideSignature":"A.setB1(B)","threadId":1,"lineNum":9}, +{"type":"methodEntry","signature":"public void A.setB1(B)","receiver":{"class":"A","id":258952499},"args":[{"class":"B","id":1325547227}],"threadId":1,"time":655648646260200}, +{"type":"blockEntry","methodSignature":"A.setB1(B)","blockId":0,"incomings":0,"threadId":1,"lineNum":7,"time":655648646272400}, +{"type":"fieldSet","fieldName":"A.b1","container":{"class":"A","id":258952499},"value":{"class":"B","id":1325547227},"threadId":1,"lineNum":7,"time":655648646295900}, +{"type":"methodExit","shortSignature":"A.setB1(B)","receiver":{"class":"A","id":258952499},"returnValue":{"class":"void","id":0},"threadId":1,"time":655648646315600}, +{"type":"methodCall","callerSideSignature":"A.setB1(B)","threadId":1,"lineNum":10}, +{"type":"methodEntry","signature":"public void A.setB1(B)","receiver":{"class":"A","id":603742814},"args":[{"class":"B","id":980546781}],"threadId":1,"time":655648646338600}, +{"type":"blockEntry","methodSignature":"A.setB1(B)","blockId":0,"incomings":0,"threadId":1,"lineNum":7,"time":655648646347500}, +{"type":"fieldSet","fieldName":"A.b1","container":{"class":"A","id":603742814},"value":{"class":"B","id":980546781},"threadId":1,"lineNum":7,"time":655648646360400}, +{"type":"methodExit","shortSignature":"A.setB1(B)","receiver":{"class":"A","id":603742814},"returnValue":{"class":"void","id":0},"threadId":1,"time":655648646372900}, +{"type":"methodCall","callerSideSignature":"A.setB2(B)","threadId":1,"lineNum":11}, +{"type":"methodEntry","signature":"public void A.setB2(B)","receiver":{"class":"A","id":603742814},"args":[{"class":"B","id":1325547227}],"threadId":1,"time":655648646400400}, +{"type":"blockEntry","methodSignature":"A.setB2(B)","blockId":0,"incomings":0,"threadId":1,"lineNum":10,"time":655648646411200}, +{"type":"fieldSet","fieldName":"A.b2","container":{"class":"A","id":603742814},"value":{"class":"B","id":1325547227},"threadId":1,"lineNum":10,"time":655648646433000}, +{"type":"methodExit","shortSignature":"A.setB2(B)","receiver":{"class":"A","id":603742814},"returnValue":{"class":"void","id":0},"threadId":1,"time":655648646446400}, +{"type":"methodCall","callerSideSignature":"A.getB1()","threadId":1,"lineNum":12}, +{"type":"methodEntry","signature":"public B A.getB1()","receiver":{"class":"A","id":603742814},"args":[],"threadId":1,"time":655648646470600}, +{"type":"blockEntry","methodSignature":"A.getB1()","blockId":0,"incomings":0,"threadId":1,"lineNum":14,"time":655648646481300}, +{"type":"fieldGet","fieldName":"A.b1","this":{"class":"A","id":603742814},"container":{"class":"A","id":603742814},"value":{"class":"B","id":980546781},"threadId":1,"lineNum":14,"time":655648646499900}, +{"type":"methodExit","shortSignature":"A.getB1()","receiver":{"class":"A","id":603742814},"returnValue":{"class":"B","id":980546781},"threadId":1,"time":655648646541000}, +{"type":"methodCall","callerSideSignature":"A.setB2(B)","threadId":1,"lineNum":13}, +{"type":"methodEntry","signature":"public void A.setB2(B)","receiver":{"class":"A","id":258952499},"args":[{"class":"B","id":980546781}],"threadId":1,"time":655648646565600}, +{"type":"blockEntry","methodSignature":"A.setB2(B)","blockId":0,"incomings":0,"threadId":1,"lineNum":10,"time":655648646573300}, +{"type":"fieldSet","fieldName":"A.b2","container":{"class":"A","id":258952499},"value":{"class":"B","id":980546781},"threadId":1,"lineNum":10,"time":655648646587300}, +{"type":"methodExit","shortSignature":"A.setB2(B)","receiver":{"class":"A","id":258952499},"returnValue":{"class":"void","id":0},"threadId":1,"time":655648646624900}, +{"type":"methodExit","shortSignature":"Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"returnValue":{"class":"void","id":0},"threadId":1,"time":655648646657600}, diff --git a/traces/Sample4_trace.txt b/traces/Sample4_trace.txt new file mode 100644 index 0000000..cdc37ee --- /dev/null +++ b/traces/Sample4_trace.txt @@ -0,0 +1,38 @@ +[Console output redirected to file:C:\Users\student\runtime-EclipseApplication\Sample8\Sample8_trace.txt] +{"type":"classDef","name":"Main","path":"/C:/Users/student/runtime-EclipseApplication/Sample8/bin/Main.class","loaderPath":"/"}, +{"type":"methodEntry","signature":"public static void Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"args":[{"class":"[Ljava.lang.String;","id":1160460865}],"threadId":1,"time":655685391437200}, +{"type":"blockEntry","methodSignature":"Main.main(java.lang.String[])","blockId":0,"incomings":0,"threadId":1,"lineNum":5,"time":655685391533500}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":5}, +{"type":"classDef","name":"A","path":"/C:/Users/student/runtime-EclipseApplication/Sample8/bin/A.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655685392637300}, +{"type":"fieldSet","fieldName":"A.a","container":{"class":"A","id":258952499},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655685392774900}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":258952499},"threadId":1,"time":655685392800900}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":6}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655685392822800}, +{"type":"fieldSet","fieldName":"A.a","container":{"class":"A","id":603742814},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655685392845100}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":603742814},"threadId":1,"time":655685392858100}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":7}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655685392877700}, +{"type":"fieldSet","fieldName":"A.a","container":{"class":"A","id":1067040082},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655685392898600}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":1067040082},"threadId":1,"time":655685392911700}, +{"type":"methodCall","callerSideSignature":"A.setA(A)","threadId":1,"lineNum":8}, +{"type":"methodEntry","signature":"public void A.setA(A)","receiver":{"class":"A","id":258952499},"args":[{"class":"A","id":603742814}],"threadId":1,"time":655685392951600}, +{"type":"blockEntry","methodSignature":"A.setA(A)","blockId":0,"incomings":0,"threadId":1,"lineNum":6,"time":655685392965100}, +{"type":"fieldSet","fieldName":"A.a","container":{"class":"A","id":258952499},"value":{"class":"A","id":603742814},"threadId":1,"lineNum":6,"time":655685392985900}, +{"type":"methodExit","shortSignature":"A.setA(A)","receiver":{"class":"A","id":258952499},"returnValue":{"class":"void","id":0},"threadId":1,"time":655685393008800}, +{"type":"methodCall","callerSideSignature":"A.setA(A)","threadId":1,"lineNum":9}, +{"type":"methodEntry","signature":"public void A.setA(A)","receiver":{"class":"A","id":1067040082},"args":[{"class":"A","id":258952499}],"threadId":1,"time":655685393037400}, +{"type":"blockEntry","methodSignature":"A.setA(A)","blockId":0,"incomings":0,"threadId":1,"lineNum":6,"time":655685393047800}, +{"type":"fieldSet","fieldName":"A.a","container":{"class":"A","id":1067040082},"value":{"class":"A","id":258952499},"threadId":1,"lineNum":6,"time":655685393079200}, +{"type":"methodExit","shortSignature":"A.setA(A)","receiver":{"class":"A","id":1067040082},"returnValue":{"class":"void","id":0},"threadId":1,"time":655685393092600}, +{"type":"methodCall","callerSideSignature":"A.getA()","threadId":1,"lineNum":10}, +{"type":"methodEntry","signature":"public A A.getA()","receiver":{"class":"A","id":1067040082},"args":[],"threadId":1,"time":655685393116700}, +{"type":"blockEntry","methodSignature":"A.getA()","blockId":0,"incomings":0,"threadId":1,"lineNum":10,"time":655685393127200}, +{"type":"fieldGet","fieldName":"A.a","this":{"class":"A","id":1067040082},"container":{"class":"A","id":1067040082},"value":{"class":"A","id":258952499},"threadId":1,"lineNum":10,"time":655685393171500}, +{"type":"methodExit","shortSignature":"A.getA()","receiver":{"class":"A","id":1067040082},"returnValue":{"class":"A","id":258952499},"threadId":1,"time":655685393207000}, +{"type":"methodCall","callerSideSignature":"A.getA()","threadId":1,"lineNum":10}, +{"type":"methodEntry","signature":"public A A.getA()","receiver":{"class":"A","id":258952499},"args":[],"threadId":1,"time":655685393227400}, +{"type":"blockEntry","methodSignature":"A.getA()","blockId":0,"incomings":0,"threadId":1,"lineNum":10,"time":655685393235300}, +{"type":"fieldGet","fieldName":"A.a","this":{"class":"A","id":258952499},"container":{"class":"A","id":258952499},"value":{"class":"A","id":603742814},"threadId":1,"lineNum":10,"time":655685393251800}, +{"type":"methodExit","shortSignature":"A.getA()","receiver":{"class":"A","id":258952499},"returnValue":{"class":"A","id":603742814},"threadId":1,"time":655685393266400}, +{"type":"methodExit","shortSignature":"Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"returnValue":{"class":"void","id":0},"threadId":1,"time":655685393286600}, diff --git a/traces/Sample5_trace.txt b/traces/Sample5_trace.txt new file mode 100644 index 0000000..e2545c0 --- /dev/null +++ b/traces/Sample5_trace.txt @@ -0,0 +1,48 @@ +{"type":"classDef","name":"Main","path":"/C:/Users/student/runtime-EclipseApplication/Sample10/bin/Main.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static Main.()","class":"Main","args":[],"threadId":1,"time":655487576539300}, +{"type":"constructorExit","shortSignature":"Main.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655487588048700}, +{"type":"methodEntry","signature":"public static void Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"args":[{"class":"[Ljava.lang.String;","id":1325547227}],"threadId":1,"time":655487588359600}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":5}, +{"type":"classDef","name":"A","path":"/C:/Users/student/runtime-EclipseApplication/Sample10/bin/A.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static A.()","class":"A","args":[],"threadId":1,"time":655487601669200}, +{"type":"constructorExit","shortSignature":"A.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655487601691100}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655487601703800}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655487601769700}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":2001049719},"threadId":1,"time":655487601931900}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":6}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655487601958200}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1927950199},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655487601982900}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":1927950199},"threadId":1,"time":655487602022100}, +{"type":"methodCall","callerSideSignature":"A()","threadId":1,"lineNum":7}, +{"type":"constructorEntry","signature":"public A()","class":"A","args":[],"threadId":1,"time":655487602043000}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":868693306},"value":{"class":"---","id":0},"threadId":1,"lineNum":3,"time":655487602062900}, +{"type":"constructorExit","shortSignature":"A()","returnValue":{"class":"A","id":868693306},"threadId":1,"time":655487602110700}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":8}, +{"type":"classDef","name":"B","path":"/C:/Users/student/runtime-EclipseApplication/Sample10/bin/B.class","loaderPath":"/"}, +{"type":"constructorEntry","signature":"static B.()","class":"B","args":[],"threadId":1,"time":655487602834000}, +{"type":"constructorExit","shortSignature":"B.()","returnValue":{"class":"void","id":0},"threadId":1,"time":655487602860100}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655487602872100}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":989110044},"threadId":1,"time":655487602948300}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":9}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655487602972600}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":424058530},"threadId":1,"time":655487603011500}, +{"type":"methodCall","callerSideSignature":"B()","threadId":1,"lineNum":10}, +{"type":"constructorEntry","signature":"public B()","class":"B","args":[],"threadId":1,"time":655487603032800}, +{"type":"constructorExit","shortSignature":"B()","returnValue":{"class":"B","id":321001045},"threadId":1,"time":655487603074000}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":13}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":2001049719},"args":[{"class":"B","id":989110044}],"threadId":1,"time":655487603110900}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"B","id":989110044},"threadId":1,"lineNum":6,"time":655487603163100}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"void","id":0},"threadId":1,"time":655487603210500}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":14}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":1927950199},"args":[{"class":"B","id":424058530}],"threadId":1,"time":655487603241100}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":1927950199},"value":{"class":"B","id":424058530},"threadId":1,"lineNum":6,"time":655487603284800}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":1927950199},"returnValue":{"class":"void","id":0},"threadId":1,"time":655487603323200}, +{"type":"methodCall","callerSideSignature":"A.setB(B)","threadId":1,"lineNum":15}, +{"type":"methodEntry","signature":"public void A.setB(B)","receiver":{"class":"A","id":2001049719},"args":[{"class":"B","id":321001045}],"threadId":1,"time":655487603353800}, +{"type":"fieldSet","fieldName":"A.b","container":{"class":"A","id":2001049719},"value":{"class":"B","id":321001045},"threadId":1,"lineNum":6,"time":655487603392900}, +{"type":"methodExit","shortSignature":"A.setB(B)","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"void","id":0},"threadId":1,"time":655487603438600}, +{"type":"methodCall","callerSideSignature":"A.getB()","threadId":1,"lineNum":17}, +{"type":"methodEntry","signature":"public B A.getB()","receiver":{"class":"A","id":2001049719},"args":[],"threadId":1,"time":655487603473800}, +{"type":"fieldGet","fieldName":"A.b","this":{"class":"A","id":2001049719},"container":{"class":"A","id":2001049719},"value":{"class":"B","id":321001045},"threadId":1,"lineNum":10,"time":655487603515200}, +{"type":"methodExit","shortSignature":"A.getB()","receiver":{"class":"A","id":2001049719},"returnValue":{"class":"B","id":321001045},"threadId":1,"time":655487603641100}, +{"type":"methodExit","shortSignature":"Main.main(java.lang.String[])","receiver":{"class":"Main","id":0},"returnValue":{"class":"void","id":0},"threadId":1,"time":655487603672600},