diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
index ca4281bcc..55e37974e 100644
--- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
+++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java
@@ -15,6 +15,8 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.beust.jcommander.DynamicParameter;
import com.beust.jcommander.IStringConverter;
@@ -43,6 +45,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.FileUtils;
public class JadxCLIArgs implements IJadxConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(JadxCLIArgs.class);
@JadxConfigExclude
@Parameter(description = " (.apk, .dex, .jar, .class, .smali, .zip, .aar, .arsc, .aab, .xapk, .apkm, .jadx.kts)")
@@ -376,11 +379,15 @@ public class JadxCLIArgs implements IJadxConfig {
}
if (!argsObj.config.equalsIgnoreCase("none")) {
// load config file and merge with command line args
- configAdapter.useConfigRef(argsObj.config);
- T configObj = configAdapter.load();
- if (configObj != null) {
- jcw.overrideProvided(configObj);
- argsObj = configObj;
+ try {
+ configAdapter.useConfigRef(argsObj.config);
+ T configObj = configAdapter.load();
+ if (configObj != null) {
+ jcw.overrideProvided(configObj);
+ argsObj = configObj;
+ }
+ } catch (Exception e) {
+ LOG.error("Config load failed, continue with default values", e);
}
}
}
diff --git a/jadx-cli/src/main/java/jadx/cli/config/JadxConfigAdapter.java b/jadx-cli/src/main/java/jadx/cli/config/JadxConfigAdapter.java
index cdb74af64..5c4edd3db 100644
--- a/jadx-cli/src/main/java/jadx/cli/config/JadxConfigAdapter.java
+++ b/jadx-cli/src/main/java/jadx/cli/config/JadxConfigAdapter.java
@@ -1,6 +1,5 @@
package jadx.cli.config;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;
@@ -12,17 +11,12 @@ import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonWriter;
import jadx.commons.app.JadxCommonFiles;
import jadx.core.utils.GsonUtils;
import jadx.core.utils.exceptions.JadxArgsValidateException;
import jadx.core.utils.exceptions.JadxRuntimeException;
-import static java.nio.file.StandardOpenOption.CREATE;
-import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
-import static java.nio.file.StandardOpenOption.WRITE;
-
public class JadxConfigAdapter {
private static final ExclusionStrategy GSON_EXCLUSION_STRATEGY = new ExclusionStrategy() {
@Override
@@ -81,9 +75,10 @@ public class JadxConfigAdapter {
}
public void save(T configObject) {
- try (JsonWriter writer = gson.newJsonWriter(
- Files.newBufferedWriter(configPath, StandardCharsets.UTF_8, WRITE, CREATE, TRUNCATE_EXISTING))) {
- gson.toJson(configObject, configCls, writer);
+ try {
+ String jsonStr = gson.toJson(configObject, configCls);
+ // don't use stream writer here because serialization errors will corrupt config
+ Files.writeString(configPath, jsonStr);
} catch (Exception e) {
throw new JadxRuntimeException("Failed to save config file: " + configPath, e);
}
diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
index 9a4df2830..c70b84cf5 100644
--- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
+++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
@@ -51,6 +51,7 @@ public class JadxSettings {
private static final int RECENT_PROJECTS_COUNT = 30;
private final JadxConfigAdapter configAdapter;
+ private final Object dataWriteSync = new Object();
private final ShortcutsWrapper shortcutsWrapper = new ShortcutsWrapper();
private final FontSettings fontSettings = new FontSettings();
@@ -112,7 +113,9 @@ public class JadxSettings {
}
public void sync() {
- configAdapter.save(settingsData);
+ synchronized (dataWriteSync) {
+ configAdapter.save(settingsData);
+ }
}
public String exportSettingsString() {
@@ -218,8 +221,10 @@ public class JadxSettings {
}
public void saveWindowPos(Window window) {
- WindowLocation pos = new WindowLocation(window.getClass().getSimpleName(), window.getBounds());
- settingsData.getWindowPos().put(pos.getWindowId(), pos);
+ synchronized (dataWriteSync) {
+ WindowLocation pos = new WindowLocation(window.getClass().getSimpleName(), window.getBounds());
+ settingsData.getWindowPos().put(pos.getWindowId(), pos);
+ }
}
public boolean loadWindowPos(Window window) {
diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
index ac4e6bba2..df3dde984 100644
--- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
@@ -1613,7 +1613,9 @@ public class MainWindow extends JFrame {
if (debuggerPanel != null) {
saveSplittersInfo();
}
- settings.sync();
+ // block UI thread to avoid settings data changes during sync
+ UiUtils.uiRunAndWait(settings::sync);
+
closeAll();
UiUtils.uiRunAndWait(() -> {
heapUsageBar.reset();