diff --git a/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java b/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java index 9f22d79..c1be68f 100644 --- a/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java +++ b/src/org/ntlab/deltaViewer/CollaborationAliasCollector.java @@ -7,6 +7,9 @@ import org.ntlab.deltaExtractor.Alias; import org.ntlab.deltaExtractor.IAliasCollector; +import org.ntlab.featureExtractor.Extract; +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.TracePoint; /** * CollaborationAliasCollector is IAliasCollector implementation class to merge aliasList in time stamp order. @@ -37,15 +40,32 @@ /** * Merge other into aliasList(this) in time stamp order. * @param other�@IAliasCollector to be merged into the aliasList. + * @param extract */ - public void merge(IAliasCollector other) { + public void merge(IAliasCollector other, Extract extract) { List otherAliasList = other.getAliasList(); otherAliasList = sortAliasListByTimeStamp(otherAliasList); - int otherIdx = 0; // Index of otherAliasList - int thisIdx = 0; // Index of thisAliasList + int otherIdx = 0; // Index in otherAliasList + int thisIdx = 0; // Index in thisAliasList + int thisOrgIdx = 0; // Index in the original thisAliasList while(otherIdx < otherAliasList.size()) { Alias otherAlias = otherAliasList.get(otherIdx); if (thisIdx >= aliasList.size()) { + if (extract != null && extract.isToConnect() && otherIdx == 0) { + Alias thisPrevAlias = aliasList.get(aliasList.size() - 1); + if (!otherAlias.getMethodExecution().isStatic() && otherAlias.getMethodExecution().getCallerMethodExecution() != thisPrevAlias.getMethodExecution()) { + // Add a dummy alias to connect disjunct call hierarchies. (thisPrevAlias -> otherAlias) + MethodExecution caller = thisPrevAlias.getMethodExecution(); +// MethodExecution callee = new DummyMethodExecution(otherAlias.getMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = otherAlias.getMethodExecution(); + callee.setCaller(caller, caller.getStatements().indexOf(thisPrevAlias.getOccurrencePoint().getStatement())); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, thisPrevAlias.getOccurrencePoint().getStatement().getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + aliasList.add(new Alias(Alias.AliasType.RECEIVER, 0, callee.getThisObjId(), dummyTp)); + thisIdx++; + } + } aliasList.add(otherAlias); otherIdx++; thisIdx++; continue; @@ -53,16 +73,46 @@ Alias thisAlias = aliasList.get(thisIdx); if (otherAlias.equals(thisAlias)) { - otherIdx++; thisIdx++; + otherIdx++; thisIdx++; thisOrgIdx++; } else { long otherAliasTs = otherAlias.getTimeStamp(); long thisAliasTs = thisAlias.getTimeStamp(); if (otherAliasTs < thisAliasTs) { + if (extract != null && extract.isToConnect() && otherIdx == 0 && thisIdx > 0) { + Alias thisPrevAlias = aliasList.get(thisIdx - 1); + if (!otherAlias.getMethodExecution().isStatic() && otherAlias.getMethodExecution().getCallerMethodExecution() != thisPrevAlias.getMethodExecution()) { + // Add a dummy alias to connect disjunct call hierarchies. (thisPrevAlias -> otherAlias) + MethodExecution caller = thisPrevAlias.getMethodExecution(); +// MethodExecution callee = new DummyMethodExecution(otherAlias.getMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = otherAlias.getMethodExecution(); + callee.setCaller(caller, caller.getStatements().indexOf(thisPrevAlias.getOccurrencePoint().getStatement())); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, thisPrevAlias.getOccurrencePoint().getStatement().getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + aliasList.add(new Alias(Alias.AliasType.RECEIVER, 0, callee.getThisObjId(), dummyTp)); + thisIdx++; + } + } aliasList.add(thisIdx, otherAlias); otherIdx++; thisIdx++; } else if (otherAliasTs > thisAliasTs) { - thisIdx++; + if (extract != null && extract.isToConnect() && thisOrgIdx == 0 && otherIdx > 0) { + Alias otherPrevAlias = otherAliasList.get(otherIdx - 1); + if (!thisAlias.getMethodExecution().isStatic() && thisAlias.getMethodExecution().getCallerMethodExecution() != otherPrevAlias.getMethodExecution()) { + // Add a dummy alias to connect disjunct call hierarchies. (otherPrevAlias -> thisAlias) + MethodExecution caller = otherPrevAlias.getMethodExecution(); +// MethodExecution callee = new DummyMethodExecution(thisAlias.getMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = thisAlias.getMethodExecution(); + callee.setCaller(caller, caller.getStatements().indexOf(otherPrevAlias.getOccurrencePoint().getStatement())); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, otherPrevAlias.getOccurrencePoint().getStatement().getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + aliasList.add(new Alias(Alias.AliasType.RECEIVER, 0, callee.getThisObjId(), dummyTp)); + thisIdx++; + } + } + thisIdx++; thisOrgIdx++; } else { if (aliasList.contains(otherAlias)) { otherIdx++; @@ -74,6 +124,21 @@ } } } + if (extract != null && extract.isToConnect() && thisOrgIdx == 0 && otherIdx > 0 && thisIdx < aliasList.size()) { + Alias thisAlias = aliasList.get(thisIdx); + Alias otherPrevAlias = otherAliasList.get(otherIdx - 1); + if (!thisAlias.getMethodExecution().isStatic() && thisAlias.getMethodExecution().getCallerMethodExecution() != otherPrevAlias.getMethodExecution()) { + // Add a dummy alias to connect disjunct call hierarchies. (otherPrevAlias -> thisAlias) + MethodExecution caller = otherPrevAlias.getMethodExecution(); +// MethodExecution callee = new DummyMethodExecution(thisAlias.getMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = thisAlias.getMethodExecution(); + callee.setCaller(caller, caller.getStatements().indexOf(otherPrevAlias.getOccurrencePoint().getStatement())); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, otherPrevAlias.getOccurrencePoint().getStatement().getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + aliasList.add(new Alias(Alias.AliasType.RECEIVER, 0, callee.getThisObjId(), dummyTp)); + } + } } /** diff --git a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java index adda005..ba4c972 100644 --- a/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java +++ b/src/org/ntlab/deltaViewer/CollaborationObjectCallGraph.java @@ -106,6 +106,13 @@ thisRoot = tmp; /* lowest common ancestor algorithm */ MethodExecution lca = lowestCommonAncestor(thisRoot, thisStartPoint, otherStartPoint); + if (lca == null) { + if (thisStartPoint.getEntryTime() < otherStartPoint.getEntryTime()) { + lca = thisStartPoint; + } else { + lca = otherStartPoint; + } + } startPoints.clear(); startPoints.add(lca); @@ -136,7 +143,7 @@ if (pRoots.contains(qTmp)) return qTmp; qTmp = qTmp.getParent(); } - return root; + return qTmp; } /** @@ -288,7 +295,8 @@ */ private List replaceRelatedPoints(List relatedPoints, Map> newToOldMethodExecutionMap) { List replacedRp = new ArrayList<>(relatedPoints); - for (TracePoint rp: replacedRp) { + for (int i = 0; i < replacedRp.size(); i++) { + TracePoint rp = replacedRp.get(i); Statement st = rp.getStatement(); if (st instanceof MethodInvocation) { MethodInvocation methodInv = (MethodInvocation)st; @@ -299,8 +307,15 @@ if (oldMethodExecSet.contains(calledMethodExec)) { methodInv.setCalledMethodExecution(newMethodExec); } + } + } + for (Entry> entry: newToOldMethodExecutionMap.entrySet()) { + MethodExecution newMethodExec = entry.getKey(); + Set oldMethodExecSet = entry.getValue(); + if (oldMethodExecSet.contains(rp.getMethodExecution())) { + DummyTracePoint newTp = new DummyTracePoint(rp, newMethodExec); + replacedRp.set(i, newTp); } - } } return replacedRp; diff --git a/src/org/ntlab/deltaViewer/DeltaAliasCollector.java b/src/org/ntlab/deltaViewer/DeltaAliasCollector.java index b5a4369..c55a93b 100644 --- a/src/org/ntlab/deltaViewer/DeltaAliasCollector.java +++ b/src/org/ntlab/deltaViewer/DeltaAliasCollector.java @@ -13,6 +13,7 @@ import org.ntlab.trace.MethodExecution; import org.ntlab.trace.MethodInvocation; import org.ntlab.trace.Statement; +import org.ntlab.trace.Trace; import org.ntlab.trace.TracePoint; /** @@ -88,6 +89,7 @@ List> invocationChains = collectInvocationChains(standardMethodInvocations); aliasList = replaceInvocationChains(aliasList, invocationChains); Map> newToOldMethodExecMap = collectNewToOldMethodExecutionMap(oldAliasList, aliasList); + aliasList = removeEnclosingInstanceAccessor(aliasList, newToOldMethodExecMap); // for debug. System.out.println("standardMethodInvocations: "); @@ -107,7 +109,7 @@ } return newToOldMethodExecMap; } - + private List collectStandardMethodInvocations(List aliasList) { List standardMethodInvocations = new ArrayList<>(); List standardMethodInvsIdx = new ArrayList<>(); @@ -294,6 +296,59 @@ return replacedAliasList; } + private List removeEnclosingInstanceAccessor(List aliasList, Map> newToOldMethodExecMap) { + List removedAliasList = new ArrayList<>(aliasList); + MethodExecution caller = null; + int callerStatement = 0; + MethodExecution accessor = null; + for (int i = 0; i < removedAliasList.size(); i++) { + Alias a = removedAliasList.get(i); + if (a.getAliasType() == Alias.AliasType.ACTUAL_ARGUMENT) { + Statement st = a.getOccurrencePoint().getStatement(); + if (st instanceof MethodInvocation) { + if (Trace.getMethodName(((MethodInvocation) st).getCalledMethodExecution().getSignature()).startsWith("access$")) { + caller = a.getMethodExecution(); + MethodInvocation mi = ((MethodInvocation) st); + callerStatement = mi.getCalledMethodExecution().getCallerStatementExecution(); + accessor = mi.getCalledMethodExecution(); + removedAliasList.remove(i); + i--; + continue; + } + } + } else if (a.getAliasType() == Alias.AliasType.FORMAL_PARAMETER) { + if (Trace.getMethodName(a.getMethodSignature()).startsWith("access$")) { + removedAliasList.remove(i); + i--; + continue; + } + } + if (a.getMethodExecution() == accessor) { + Statement st = a.getOccurrencePoint().getStatement(); + if (a.getAliasType() == Alias.AliasType.ACTUAL_ARGUMENT) { +// MethodExecution callee = new DummyMethodExecution(((MethodInvocation) st).getCalledMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = ((MethodInvocation) st).getCalledMethodExecution(); + callee.setCaller(caller, callerStatement); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, st.getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + Alias newAlias = new Alias(Alias.AliasType.ACTUAL_ARGUMENT, a.getIndex(), a.getObjectId(), dummyTp); + removedAliasList.set(i, newAlias); + } else if (a.getAliasType() == Alias.AliasType.RECEIVER) { +// MethodExecution callee = new DummyMethodExecution(((MethodInvocation) st).getCalledMethodExecution()); // Currently does not work because this dummy and the original one will be mixed. + MethodExecution callee = ((MethodInvocation) st).getCalledMethodExecution(); + callee.setCaller(caller, callerStatement); + DummyMethodInvocation dummyInv = new DummyMethodInvocation(callee, caller.getThisClassName(), caller.getThisObjId(), 0, st.getThreadNo()); + dummyInv.setTimeStamp(callee.getEntryTime()); + DummyTracePoint dummyTp = new DummyTracePoint(caller, dummyInv); + Alias newAlias = new Alias(Alias.AliasType.RECEIVER, a.getIndex(), a.getObjectId(), dummyTp); + removedAliasList.set(i, newAlias); + } + } + } + return removedAliasList; + } + /** * Collect methodExecutions for Alias that are not equal in oldAliasList and newAliasList. * @param oldAliasList diff --git a/src/org/ntlab/deltaViewer/DummyMethodExecution.java b/src/org/ntlab/deltaViewer/DummyMethodExecution.java new file mode 100644 index 0000000..c699264 --- /dev/null +++ b/src/org/ntlab/deltaViewer/DummyMethodExecution.java @@ -0,0 +1,18 @@ +package org.ntlab.deltaViewer; + +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.Statement; + +public class DummyMethodExecution extends MethodExecution { + public DummyMethodExecution(MethodExecution methodExec) { + super(methodExec.getSignature(), methodExec.getCallerSideSignature(), methodExec.getThisClassName(), methodExec.getThisObjId(), methodExec.isConstructor(), methodExec.isStatic(), methodExec.getEntryTime()); + setCollectionType(methodExec.isCollectionType()); + setArguments(methodExec.getArguments()); + setReturnValue(methodExec.getReturnValue()); + setCaller(methodExec.getCallerMethodExecution(), methodExec.getCallerStatementExecution()); + for (Statement st: methodExec.getStatements()) { + addStatement(st); + } + setExitTime(methodExec.getExitTime()); + } +} diff --git a/src/org/ntlab/deltaViewer/DummyMethodInvocation.java b/src/org/ntlab/deltaViewer/DummyMethodInvocation.java new file mode 100644 index 0000000..b0fca17 --- /dev/null +++ b/src/org/ntlab/deltaViewer/DummyMethodInvocation.java @@ -0,0 +1,25 @@ +package org.ntlab.deltaViewer; + +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.MethodInvocation; + +public class DummyMethodInvocation extends MethodInvocation { + private long timeStamp; + + public DummyMethodInvocation(MethodInvocation methodInvocation) { + super(methodInvocation.getCalledMethodExecution(), methodInvocation.getThisClassName(), methodInvocation.getThisObjId(), methodInvocation.getLineNo(), methodInvocation.getThreadNo()); + } + + public DummyMethodInvocation(MethodExecution methodExecution, String thisClassName, String thisObjId, int lineNo, String threadNo) { + super(methodExecution, thisClassName, thisObjId, lineNo, threadNo); + } + + public void setTimeStamp(long timeStamp) { + this.timeStamp = timeStamp; + } + + public long getTimeStamp() { + return timeStamp; + } + +} diff --git a/src/org/ntlab/deltaViewer/DummyTracePoint.java b/src/org/ntlab/deltaViewer/DummyTracePoint.java new file mode 100644 index 0000000..82f6e85 --- /dev/null +++ b/src/org/ntlab/deltaViewer/DummyTracePoint.java @@ -0,0 +1,30 @@ +package org.ntlab.deltaViewer; + +import org.ntlab.trace.MethodExecution; +import org.ntlab.trace.Statement; +import org.ntlab.trace.TracePoint; + +public class DummyTracePoint extends TracePoint { + private Statement dummyStatement = null; + private MethodExecution dummyMethodExecution = null; + + public DummyTracePoint(MethodExecution methodExecution, Statement dummyStatement) { + super(methodExecution, 0); + this.dummyStatement = dummyStatement; + } + + public DummyTracePoint(TracePoint tracePoint, MethodExecution dummyMethodExecution) { + super(tracePoint.getMethodExecution(), tracePoint.getMethodExecution().getStatements().indexOf(tracePoint.getStatement())); + this.dummyMethodExecution = dummyMethodExecution; + } + + public Statement getStatement() { + if (dummyStatement == null) return super.getStatement(); + return dummyStatement; + } + + public MethodExecution getMethodExecution() { + if (dummyMethodExecution != null) return dummyMethodExecution; + return super.getMethodExecution(); + } +} diff --git a/src/org/ntlab/deltaViewer/MagnetRONFrame.java b/src/org/ntlab/deltaViewer/MagnetRONFrame.java index fa86c7f..3601a8f 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONFrame.java +++ b/src/org/ntlab/deltaViewer/MagnetRONFrame.java @@ -213,7 +213,7 @@ if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { - cac.merge(dac); + cac.merge(dac, extract); } } cocg.shrinkAll(newToOldMethodExecMap); @@ -255,7 +255,7 @@ if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { - cac.merge(dac); + cac.merge(dac, null); } } cocg.shrinkAll(newToOldMethodExecMap); diff --git a/src/org/ntlab/deltaViewer/MagnetRONViewer.java b/src/org/ntlab/deltaViewer/MagnetRONViewer.java index 0480dd2..c991f1b 100644 --- a/src/org/ntlab/deltaViewer/MagnetRONViewer.java +++ b/src/org/ntlab/deltaViewer/MagnetRONViewer.java @@ -175,9 +175,13 @@ break; case CONSTRACTOR_INVOCATION: // TODO: Confirm the program behavior when called after RECEIVER. - createObjectVertexOnConstractor(alias); - createMethodExecutionVertex(alias.getObjectId(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCallerSideMethodName(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCalledMethodExecution()); - update(); + if (!objectToVertexMap.containsKey(alias.getObjectId()) || objectToVertexMap.get(alias.getObjectId()).getCell() == null) { + createObjectVertexOnConstractor(alias); + } + if (!methodExecToVertexMap.containsKey(((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCalledMethodExecution())) { + createMethodExecutionVertex(alias.getObjectId(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCallerSideMethodName(), ((MethodInvocation)alias.getOccurrencePoint().getStatement()).getCalledMethodExecution()); + update(); + } removeMethodExecutionVertex(alias); update(); break; @@ -198,6 +202,10 @@ case RECEIVER: // Make {@code MethodExecutionVertex} of called method execution. MethodExecution calledMethodExec = ((MethodInvocation) alias.getOccurrencePoint().getStatement()).getCalledMethodExecution(); + if (calledMethodExec.isConstructor() + && (!objectToVertexMap.containsKey(alias.getObjectId()) || objectToVertexMap.get(alias.getObjectId()).getCell() == null)) { + createObjectVertexOnConstractor(alias); + } if (!methodExecToVertexMap.containsKey(calledMethodExec)) { MethodExecution methodExec = alias.getMethodExecution(); if (!methodExecToVertexMap.containsKey(methodExec) diff --git a/src/org/ntlab/featureExtractor/Extract.java b/src/org/ntlab/featureExtractor/Extract.java index b74bff0..8c10c25 100644 --- a/src/org/ntlab/featureExtractor/Extract.java +++ b/src/org/ntlab/featureExtractor/Extract.java @@ -16,13 +16,16 @@ private int order = 0; - public Extract(String srcId, String srcClass, String dstId, String dstClass, String type, int order) { + private boolean toConnect = false; + + public Extract(String srcId, String srcClass, String dstId, String dstClass, String type, int order, boolean toConnect) { this.srcId = srcId; this.srcClass = srcClass; this.dstId = dstId; this.dstClass = dstClass; this.type = type; this.order = order; + this.toConnect = toConnect; } public String getSrcId() { @@ -49,4 +52,7 @@ return order; } + public boolean isToConnect() { + return toConnect; + } } diff --git a/src/org/ntlab/featureExtractor/MagnetronParser.java b/src/org/ntlab/featureExtractor/MagnetronParser.java index 14e284e..43bee98 100644 --- a/src/org/ntlab/featureExtractor/MagnetronParser.java +++ b/src/org/ntlab/featureExtractor/MagnetronParser.java @@ -125,13 +125,17 @@ Map srcObject = (Map) object.get("src"); Map dstObject = (Map) object.get("dst"); int order = Integer.parseInt((String) object.get("order")); + boolean isToConnect = false; + if (object.get("connect") != null) { + isToConnect = (Boolean) object.get("connect"); + } Extract extract = new Extract( (String) srcObject.get("id"), (String) srcObject.get("class"), (String) dstObject.get("id"), (String) dstObject.get("class"), (String) object.get("type"), - order); + order, isToConnect); extracts.add(extract); return residual; } @@ -194,6 +198,12 @@ } else if (line.startsWith("null")) { residual = line.substring(4); values[0] = null; + } else if (line.startsWith("true")) { + residual = line.substring(4); + values[0] = true; + } else if (line.startsWith("false")) { + residual = line.substring(5); + values[0] = false; } else { // To Do } diff --git a/src/tests/CollaborationAliasCollectorTest.java b/src/tests/CollaborationAliasCollectorTest.java index c0d52cf..f1eb166 100644 --- a/src/tests/CollaborationAliasCollectorTest.java +++ b/src/tests/CollaborationAliasCollectorTest.java @@ -30,7 +30,7 @@ if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { - cac.merge(dac); + cac.merge(dac, null); } } System.out.println("mergedAliasList: "); diff --git a/src/tests/CollaborationObjectCallGraphTest.java b/src/tests/CollaborationObjectCallGraphTest.java index 3ed9123..d6a8454 100644 --- a/src/tests/CollaborationObjectCallGraphTest.java +++ b/src/tests/CollaborationObjectCallGraphTest.java @@ -46,7 +46,7 @@ if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { - cac.merge(dac); + cac.merge(dac, null); } } } diff --git a/src/tests/MagnetRONFrameTest.java b/src/tests/MagnetRONFrameTest.java index 700ec10..4e92d54 100644 --- a/src/tests/MagnetRONFrameTest.java +++ b/src/tests/MagnetRONFrameTest.java @@ -85,7 +85,7 @@ if (cac == null) { cac = new CollaborationAliasCollector(dac); } else { - cac.merge(dac); + cac.merge(dac, null); } } // new Thread() { diff --git a/traces/EclipseDebug.magnet b/traces/EclipseDebug.magnet index dff8124..7200715 100644 --- a/traces/EclipseDebug.magnet +++ b/traces/EclipseDebug.magnet @@ -7,6 +7,18 @@ "extracts": [ { "src": { + "class": "public void org.eclipse.jdt.internal.debug.core.EventDispatcher.run(", + "id": "629542817" + }, + "dst": { + "class": "org.eclipse.jdi.internal.event.EventSetImpl", + "id": "1400795012" + }, + "type": "This-Another", + "order": "0" + }, + { + "src": { "class": "public boolean org.eclipse.jdt.internal.debug.core.breakpoints.JavaBreakpoint.handleBreakpointEvent(", "id": "666051245" }, @@ -15,7 +27,8 @@ "id": "907205473" }, "type": "This-Another", - "order": "0" + "order": "0", + "connect": true }, { "src": { @@ -41,18 +54,6 @@ "type": "Container-Component(Collection)", "order": "0" }, - { - "src": { - "class": "public void org.eclipse.jdt.internal.debug.core.EventDispatcher.run(", - "id": "629542817" - }, - "dst": { - "class": "org.eclipse.jdi.internal.event.EventSetImpl", - "id": "1400795012" - }, - "type": "This-Another", - "order": "0" - }, { "src": { "class": "public com.sun.jdi.event.EventSet org.eclipse.jdi.internal.event.EventQueueImpl.remove(",