minecraft-source/src/net/minecraft/CrashReport.java

254 lines
11 KiB
Java

package net.minecraft;
import org.apache.logging.log4j.LogManager;
import java.util.concurrent.CompletionException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.io.FileOutputStream;
import java.util.Date;
import java.text.SimpleDateFormat;
import org.apache.commons.io.IOUtils;
import java.io.Writer;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Iterator;
import org.apache.commons.lang3.ArrayUtils;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import com.google.common.collect.Lists;
import java.io.File;
import java.util.List;
import org.apache.logging.log4j.Logger;
public class CrashReport {
private static final Logger LOGGER;
private final String title;
private final Throwable exception;
private final CrashReportCategory systemDetails;
private final List<CrashReportCategory> details;
private File saveFile;
private boolean trackingStackTrace;
private StackTraceElement[] uncategorizedStackTrace;
public CrashReport(final String string, final Throwable throwable) {
this.systemDetails = new CrashReportCategory(this, "System Details");
this.details = Lists.newArrayList();
this.trackingStackTrace = true;
this.uncategorizedStackTrace = new StackTraceElement[0];
this.title = string;
this.exception = throwable;
this.initDetails();
}
private void initDetails() {
this.systemDetails.setDetail("Minecraft Version", () -> SharedConstants.getCurrentVersion().getName());
this.systemDetails.setDetail("Minecraft Version ID", () -> SharedConstants.getCurrentVersion().getId());
this.systemDetails.setDetail("Operating System", () -> System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ") version " + System.getProperty("os.version"));
this.systemDetails.setDetail("Java Version", () -> System.getProperty("java.version") + ", " + System.getProperty("java.vendor"));
this.systemDetails.setDetail("Java VM Version", () -> System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor"));
final Runtime runtime1;
final long long2;
final long long3;
final long long4;
final long long5;
final long long6;
final long long7;
this.systemDetails.setDetail("Memory", () -> {
runtime1 = Runtime.getRuntime();
long2 = runtime1.maxMemory();
long3 = runtime1.totalMemory();
long4 = runtime1.freeMemory();
long5 = long2 / 1024L / 1024L;
long6 = long3 / 1024L / 1024L;
long7 = long4 / 1024L / 1024L;
return long4 + " bytes (" + long7 + " MB) / " + long3 + " bytes (" + long6 + " MB) up to " + long2 + " bytes (" + long5 + " MB)";
});
this.systemDetails.setDetail("CPUs", Runtime.getRuntime().availableProcessors());
final List<String> list1;
this.systemDetails.setDetail("JVM Flags", () -> {
list1 = Util.getVmArguments().collect(Collectors.toList());
return String.format("%d total; %s", list1.size(), list1.stream().collect(Collectors.joining(" ")));
});
}
public String getTitle() {
return this.title;
}
public Throwable getException() {
return this.exception;
}
public void getDetails(final StringBuilder stringBuilder) {
if ((this.uncategorizedStackTrace == null || this.uncategorizedStackTrace.length <= 0) && !this.details.isEmpty()) {
this.uncategorizedStackTrace = (StackTraceElement[])ArrayUtils.subarray((Object[])this.details.get(0).getStacktrace(), 0, 1);
}
if (this.uncategorizedStackTrace != null && this.uncategorizedStackTrace.length > 0) {
stringBuilder.append("-- Head --\n");
stringBuilder.append("Thread: ").append(Thread.currentThread().getName()).append("\n");
stringBuilder.append("Stacktrace:\n");
for (final StackTraceElement stackTraceElement6 : this.uncategorizedStackTrace) {
stringBuilder.append("\t").append("at ").append(stackTraceElement6);
stringBuilder.append("\n");
}
stringBuilder.append("\n");
}
for (final CrashReportCategory i4 : this.details) {
i4.getDetails(stringBuilder);
stringBuilder.append("\n\n");
}
this.systemDetails.getDetails(stringBuilder);
}
public String getExceptionMessage() {
StringWriter stringWriter2 = null;
PrintWriter printWriter3 = null;
Throwable throwable4 = this.exception;
if (throwable4.getMessage() == null) {
if (throwable4 instanceof NullPointerException) {
throwable4 = new NullPointerException(this.title);
}
else if (throwable4 instanceof StackOverflowError) {
throwable4 = new StackOverflowError(this.title);
}
else if (throwable4 instanceof OutOfMemoryError) {
throwable4 = new OutOfMemoryError(this.title);
}
throwable4.setStackTrace(this.exception.getStackTrace());
}
try {
stringWriter2 = new StringWriter();
printWriter3 = new PrintWriter(stringWriter2);
throwable4.printStackTrace(printWriter3);
return stringWriter2.toString();
}
finally {
IOUtils.closeQuietly((Writer)stringWriter2);
IOUtils.closeQuietly((Writer)printWriter3);
}
}
public String getFriendlyReport() {
final StringBuilder stringBuilder2 = new StringBuilder();
stringBuilder2.append("---- Minecraft Crash Report ----\n");
stringBuilder2.append("// ");
stringBuilder2.append(getErrorComment());
stringBuilder2.append("\n\n");
stringBuilder2.append("Time: ");
stringBuilder2.append(new SimpleDateFormat().format(new Date()));
stringBuilder2.append("\n");
stringBuilder2.append("Description: ");
stringBuilder2.append(this.title);
stringBuilder2.append("\n\n");
stringBuilder2.append(this.getExceptionMessage());
stringBuilder2.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n");
for (int integer3 = 0; integer3 < 87; ++integer3) {
stringBuilder2.append("-");
}
stringBuilder2.append("\n\n");
this.getDetails(stringBuilder2);
return stringBuilder2.toString();
}
public File getSaveFile() {
return this.saveFile;
}
public boolean saveToFile(final File file) {
if (this.saveFile != null) {
return false;
}
if (file.getParentFile() != null) {
file.getParentFile().mkdirs();
}
Writer writer3 = null;
try {
writer3 = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
writer3.write(this.getFriendlyReport());
this.saveFile = file;
return true;
}
catch (Throwable throwable4) {
CrashReport.LOGGER.error("Could not save crash report to {}", file, throwable4);
return false;
}
finally {
IOUtils.closeQuietly(writer3);
}
}
public CrashReportCategory getSystemDetails() {
return this.systemDetails;
}
public CrashReportCategory addCategory(final String string) {
return this.addCategory(string, 1);
}
public CrashReportCategory addCategory(final String string, final int integer) {
final CrashReportCategory i4 = new CrashReportCategory(this, string);
if (this.trackingStackTrace) {
final int integer2 = i4.fillInStackTrace(integer);
final StackTraceElement[] arr6 = this.exception.getStackTrace();
StackTraceElement stackTraceElement7 = null;
StackTraceElement stackTraceElement8 = null;
final int integer3 = arr6.length - integer2;
if (integer3 < 0) {
System.out.println("Negative index in crash report handler (" + arr6.length + "/" + integer2 + ")");
}
if (arr6 != null && 0 <= integer3 && integer3 < arr6.length) {
stackTraceElement7 = arr6[integer3];
if (arr6.length + 1 - integer2 < arr6.length) {
stackTraceElement8 = arr6[arr6.length + 1 - integer2];
}
}
this.trackingStackTrace = i4.validateStackTrace(stackTraceElement7, stackTraceElement8);
if (integer2 > 0 && !this.details.isEmpty()) {
final CrashReportCategory i5 = this.details.get(this.details.size() - 1);
i5.trimStacktrace(integer2);
}
else if (arr6 != null && arr6.length >= integer2 && 0 <= integer3 && integer3 < arr6.length) {
System.arraycopy(arr6, 0, this.uncategorizedStackTrace = new StackTraceElement[integer3], 0, this.uncategorizedStackTrace.length);
}
else {
this.trackingStackTrace = false;
}
}
this.details.add(i4);
return i4;
}
private static String getErrorComment() {
final String[] arr1 = { "Who set us up the TNT?", "Everything's going to plan. No, really, that was supposed to happen.", "Uh... Did I do that?", "Oops.", "Why did you do that?", "I feel sad now :(", "My bad.", "I'm sorry, Dave.", "I let you down. Sorry :(", "On the bright side, I bought you a teddy bear!", "Daisy, daisy...", "Oh - I know what I did wrong!", "Hey, that tickles! Hehehe!", "I blame Dinnerbone.", "You should try our sister game, Minceraft!", "Don't be sad. I'll do better next time, I promise!", "Don't be sad, have a hug! <3", "I just don't know what went wrong :(", "Shall we play a game?", "Quite honestly, I wouldn't worry myself about that.", "I bet Cylons wouldn't have this problem.", "Sorry :(", "Surprise! Haha. Well, this is awkward.", "Would you like a cupcake?", "Hi. I'm Minecraft, and I'm a crashaholic.", "Ooh. Shiny.", "This doesn't make any sense!", "Why is it breaking :(", "Don't do that.", "Ouch. That hurt :(", "You're mean.", "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", "There are four lights!", "But it works on my machine." };
try {
return arr1[(int)(Util.getNanos() % arr1.length)];
}
catch (Throwable throwable2) {
return "Witty comment unavailable :(";
}
}
public static CrashReport forThrowable(Throwable throwable, final String string) {
while (throwable instanceof CompletionException && throwable.getCause() != null) {
throwable = throwable.getCause();
}
CrashReport h3;
if (throwable instanceof ReportedException) {
h3 = ((ReportedException)throwable).getReport();
}
else {
h3 = new CrashReport(string, throwable);
}
return h3;
}
public static void preload() {
new CrashReport("Don't panic!", new Throwable()).getFriendlyReport();
}
static {
LOGGER = LogManager.getLogger();
}
}