in analysis/thread-dump/src/main/java/org/eclipse/jifa/tda/parser/JStackParser.java [554:740]
Trace parseStackTrace(Thread thread, boolean deadLockThread, List<String> stackTraces) {
Pool<String> symbolPool = snapshot.getSymbols();
Pool<Frame> framePool = snapshot.getFrames();
Pool<Monitor> monitorPool = snapshot.getMonitors();
Trace trace = new Trace();
List<Frame> frames = new ArrayList<>();
List<Monitor> monitors = new ArrayList<>();
Frame last = null;
for (int i = 0; i < stackTraces.size(); i++) {
Matcher m;
String line = stackTraces.get(i);
if (line.startsWith("at")) {
m = PATTERNS.JAVA_FRAME.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal java frame: " + line);
}
if (!monitors.isEmpty()) {
last.setMonitors(monitors.toArray(new Monitor[0]));
monitors.clear();
}
if (last != null) {
// add frame here since all related information has been processed
frames.add(framePool.add(last));
}
last = new Frame();
last.setClazz(symbolPool.add(m.group("class")));
last.setMethod(symbolPool.add(m.group("method")));
String module = m.group("module");
if (module != null) {
// strip '/'
last.setModule(symbolPool.add(module.substring(0, module.length() - 1)));
}
String source = m.group("source");
SourceType sourceType = SourceType.judge(source);
last.setSourceType(sourceType);
if (sourceType == SourceType.SOURCE_FILE_WITH_LINE_NUMBER) {
int index = source.indexOf(":");
last.setLine(Integer.parseInt(source.substring(index + 1)));
source = source.substring(0, index);
last.setSource(symbolPool.add(source));
} else if (sourceType == SourceType.SOURCE_FILE) {
last.setSource(symbolPool.add(source));
}
} else {
if (line.startsWith(MonitorState.PARKING.prefix())) {
assert last != null;
m = PATTERNS.PARKING.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal parking line: " + line);
}
monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.PARKING,
Long.decode(m.group("address")),
false, symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.WAITING_ON.prefix())) {
assert last != null;
if (line.contains("<no object reference available>")) {
monitors
.add(assembleMonitor(thread, !deadLockThread,
MonitorState.WAITING_ON_NO_OBJECT_REFERENCE_AVAILABLE,
-1, false, null));
} else {
m = PATTERNS.WAITING_ON.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal waiting line: " + line);
}
monitors
.add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_ON,
Long.decode(m.group("address")),
m.group("isClass") != null,
symbolPool.add(m.group("class"))));
}
} else if (line.startsWith(MonitorState.WAITING_TO_RE_LOCK.prefix())) {
assert last != null;
m = PATTERNS.WAITING_TO_RE_LOCK.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal waiting to re-lock line: " + line);
}
monitors
.add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_TO_RE_LOCK,
Long.decode(m.group("address")),
m.group("isClass") != null,
symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.WAITING_ON_CLASS_INITIALIZATION.prefix())) {
assert last != null;
m = PATTERNS.WAITING_ON_CLASS_INITIALIZATION.matcher(line);
if (!m.matches()) {
throw new ParserException(
"Illegal waiting on class initialization line: " + line);
}
monitors
.add(assembleMonitor(thread, !deadLockThread,
MonitorState.WAITING_ON_CLASS_INITIALIZATION,
-1, true, symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.LOCKED.prefix())) {
checkLastFrameNotNull(last, line);
m = PATTERNS.LOCKED.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal locked line: " + line);
}
monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.LOCKED,
Long.decode(m.group("address")),
m.group("isClass") != null,
symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.WAITING_TO_LOCK.prefix())) {
checkLastFrameNotNull(last, line);
m = PATTERNS.WAITING_TO_LOCK.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal waiting to lock line: " + line);
}
monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_TO_LOCK,
Long.decode(m.group("address")),
m.group("isClass") != null,
symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.ELIMINATED.prefix())) {
checkLastFrameNotNull(last, line);
m = PATTERNS.ELIMINATED.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal eliminated lock line: " + line);
}
monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.ELIMINATED,
Long.decode(m.group("address")),
m.group("isClass") != null,
symbolPool.add(m.group("class"))));
} else if (line.startsWith(MonitorState.ELIMINATED_SCALAR_REPLACED.prefix())) {
checkLastFrameNotNull(last, line);
m = PATTERNS.ELIMINATED_SCALAR_REPLACED.matcher(line);
if (!m.matches()) {
throw new ParserException(
"Illegal eliminated(scalar replaced) lock line: " + line);
}
monitors.add(assembleMonitor(thread, !deadLockThread,
MonitorState.ELIMINATED_SCALAR_REPLACED,
-1,
false,
symbolPool.add(m.group("class"))));
} else if (line.equals(PATTERNS.LOCKED_OWNABLE_SYNCHRONIZERS)) {
// concurrent locks
int lockIndex = i + 1;
line = stackTraces.get(lockIndex);
if (PATTERNS.NONE.equals(line)) {
if (lockIndex + 1 != stackTraces.size()) {
throw new ParserException("Should not have content after: " + line);
}
} else {
Pool<ConcurrentLock> concurrentPool = snapshot.getConcurrentLocks();
List<ConcurrentLock> concurrentLocks = new ArrayList<>();
do {
m = PATTERNS.LOCKED_SYNCHRONIZER.matcher(line);
if (!m.matches()) {
throw new ParserException("Illegal lock synchronizer line: " + line);
}
ConcurrentLock concurrentLock = new ConcurrentLock();
concurrentLock.setAddress(Long.decode(m.group("address")));
concurrentLock.setClazz(symbolPool.add(m.group("class")));
concurrentLocks.add(concurrentPool.add(concurrentLock));
if (++lockIndex < stackTraces.size()) {
line = stackTraces.get(lockIndex);
} else {
break;
}
} while (true);
trace.setConcurrentLocks(
concurrentLocks.toArray(new ConcurrentLock[0]));
}
break;
} else {
throw new ParserException("Unrecognized line: " + line);
}
}
}
if (last != null) {
if (!monitors.isEmpty()) {
last.setMonitors(monitors.toArray(new Monitor[0]));
}
frames.add(framePool.add(last));
}
trace.setFrames(frames.toArray(new Frame[0]));
return trace;
}