Java. Декомпиляция

Пришлось мне заниматься декомпиляцией java программы. Декомпиляторов в java достаточно много, но надо было определиться с самым подходящим для меня. Надо отметить, что многие декомпиляторы очень медленно развиваются или вообще находятся в застойном положении.
Да, я долго выбирал подходящий мне декомпилятор и по итогу выбрал декомпилятор CFR. Данный декомпилятор максимально безошибочно декомпилирует многие java-программы, написанные в версиях 11 и выше. Несколько ошибок пришлось мне подкорректировать вручную, но это было не критично.
Но я тут не буду оценивать работу различных декомпиляторов. Цель у меня другая: указать параметр декомпилятора CFR который сэкономить другим время. Что означает параметр --aexagg в CFR? Запустим помощь:
java -jar cfr.jar --help --aexagg
выдает:
--aexagg - Try to extend and merge exceptions more aggressively
bytecodeviewer - поддерживает несколько декомпиляторов, выбрал CFR и декомпилировал клас используя try... with resource... (параметр --aexagg включен). Вот результат декомпиляции:
@Cacheable(value={"templates"}, key="{#profile, #range, #template}", unless="#result == null")
public Optional<Template> load(String profile, String range, String template) {
Set<String> locations = this.calculateAllLocations(profile, range, template);
Iterator<String> iterator = locations.iterator();
while (iterator.hasNext()) {
String location = iterator.next();
Resource resource = this.resourceLoader.getResource(this.templatesPath + File.separator + location);
if (!resource.exists()) continue;
try (InputStream istream = resource.getInputStream();){
String content = IOUtils.toString(istream, StandardCharsets.UTF_8);
log.info("Got template {} with content length {}", (Object)location, (Object)content.length());
log.trace("Template {} content: {}", (Object)location, (Object)content);
Optional<Template> optional = Optional.of(new Template(location, content));
return optional;
}
catch (IOException e) {
log.error("Failed to load template {}:", (Object)location, (Object)e);
}
}
return Optional.empty();
}
Самый оптимальный код получается декомпиляция с обычным CFR с параметром --aexagg, запущенный с командной строки. Код декомпилировался без единого ошибка. Версия CFR 0.152. Вот результат декомпиляции:
@Cacheable(value={"templates"}, key="{#profile, #range, #template}", unless="#result == null")
public Optional<Template> load(String profile, String range, String template) {
Set<String> locations = this.calculateAllLocations(profile, range, template);
for (String location : locations) {
Resource resource = this.resourceLoader.getResource(this.templatesPath + File.separator + location);
if (!resource.exists()) continue;
try (InputStream istream = resource.getInputStream();){
String content = IOUtils.toString((InputStream)istream, (Charset)StandardCharsets.UTF_8);
log.info("Got template {} with content length {}", (Object)location, (Object)content.length());
log.trace("Template {} content: {}", (Object)location, (Object)content);
Optional<Template> optional = Optional.of(new Template(location, content));
return optional;
}
catch (IOException e) {
log.error("Failed to load template {}:", (Object)location, (Object)e);
}
}
return Optional.empty();
}
обычный cfr без параметра --aexagg запущенный с командной строки декомпилировал так:
/*
* Enabled force condition propagation
* Lifted jumps to return sites
*/
@Cacheable(value={"templates"}, key="{#profile, #range, #template}", unless="#result == null")
public Optional<Template> load(String profile, String range, String template) {
Set<String> locations = this.calculateAllLocations(profile, range, template);
for (String location : locations) {
Optional<Template> optional;
Resource resource = this.resourceLoader.getResource(this.templatesPath + File.separator + location);
if (!resource.exists()) continue;
InputStream istream = resource.getInputStream();
try {
String content = IOUtils.toString((InputStream)istream, (Charset)StandardCharsets.UTF_8);
log.info("Got template {} with content length {}", (Object)location, (Object)content.length());
log.trace("Template {} content: {}", (Object)location, (Object)content);
optional = Optional.of(new Template(location, content));
if (istream == null) return optional;
} catch (Throwable throwable) {
try {
if (istream == null) throw throwable;
try {
istream.close();
throw throwable;
} catch (Throwable throwable2) {
throwable.addSuppressed(throwable2);
}
throw throwable;
} catch (IOException e) {
log.error("Failed to load template {}:", (Object)location, (Object)e);
}
}
istream.close();
return optional;
}
return Optional.empty();
}
Думаю, по последнему результату комментарии излишны, так как клас не возможно компилировать, из-за ошибок декомпиляции.
Subscribe to my newsletter
Read articles from Unison directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
