proguard icon indicating copy to clipboard operation
proguard copied to clipboard

java.lang.VerifyError: Bad type on operand stack uninitializedThis

Open 502647092 opened this issue 5 years ago • 1 comments

if i close code/removal/advanced this error has gone

[13:05:00 ERROR]: Bad type on operand stack
Exception Details:
  Location:
    pw/yumc/SurvivalGamesKits/config/inject/InjectConfig.<init>(Lpw/yumc/SurvivalGamesKits/config/FileConfig;)V @2: invokevirtual
  Reason:
    Type uninitializedThis (current frame, stack[0]) is not assignable to 'pw/yumc/SurvivalGamesKits/config/inject/InjectConfig'
  Current Frame:
    bci: @2
    flags: { flagThisUninit }
    locals: { uninitializedThis, 'pw/yumc/SurvivalGamesKits/config/FileConfig' }
    stack: { uninitializedThis, 'pw/yumc/SurvivalGamesKits/config/FileConfig' }
  Bytecode:
    0x0000000: 2a2b b600 09b1
 initializing SurvivalGamesKits v1.3.5-git-INNER (Is it up to date?)
java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    pw/yumc/SurvivalGamesKits/config/inject/InjectConfig.<init>(Lpw/yumc/SurvivalGamesKits/config/FileConfig;)V @2: invokevirtual
  Reason:
    Type uninitializedThis (current frame, stack[0]) is not assignable to 'pw/yumc/SurvivalGamesKits/config/inject/InjectConfig'
  Current Frame:
    bci: @2
    flags: { flagThisUninit }
    locals: { uninitializedThis, 'pw/yumc/SurvivalGamesKits/config/FileConfig' }
    stack: { uninitializedThis, 'pw/yumc/SurvivalGamesKits/config/FileConfig' }
  Bytecode:
    0x0000000: 2a2b b600 09b1

        at pw.yumc.SurvivalGamesKits.SurvivalGamesKits.onLoad(SurvivalGamesKits.java:65) ~[?:?]
        at org.bukkit.craftbukkit.v1_12_R1.CraftServer.loadPlugins(CraftServer.java:310) [spigot-1.12.2.jar:git-Spigot-dcd1643-e60fc34]
        at net.minecraft.server.v1_12_R1.DedicatedServer.init(DedicatedServer.java:205) [spigot-1.12.2.jar:git-Spigot-dcd1643-e60fc34]
        at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:545) [spigot-1.12.2.jar:git-Spigot-dcd1643-e60fc34]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_221]
proguard.conf
# -----不缩小-----
#-dontshrink
# -----不优化-----
#-dontoptimize
-optimizationpasses 1
#-optimizations code/removal/advanced

# -----忽略所有警告-----
#-dontwarn
-dontnote

# -----混淆时应用侵入式重载-----
-overloadaggressively

# -----启用混淆字典-----
-dontobfuscate
-obfuscationdictionary obf.dict
-classobfuscationdictionary obf.dict
-packageobfuscationdictionary obf.dict

# -----保留所有属性
-keepattributes **

# -----保护所有实体中的字段名称-----
-keepclassmembers class * implements java.io.Serializable {<fields>;}

# -----保护监听方法不被清理-----
-keepclassmembers class * implements org.bukkit.event.Listener {
  @org.bukkit.event.EventHandler <methods>;
}
-keepclassmembers class * implements net.md_5.bungee.api.plugin.Listener {
  @net.md_5.bungee.event.EventHandler <methods>;
}

# -----保护继承事件不被清理-----
-keep class ** extends org.bukkit.event.Event {*;}

# -----保护枚举方法的完整性-----
-keepclassmembers enum * {
  public static **[] values();
  public static ** valueOf(java.lang.String);
}

# -----保护配置注入不被清理-----
-keepclassmembers class * extends **.config.inject.Inject** {
  <fields>;
  public <init>(org.bukkit.configuration.ConfigurationSection);
}

# -----保护注解命令方法不被清理-----
-keepclassmembers class **.commands.annotation.** {<methods>;}
-keepclassmembers class * implements **.commands.interfaces.Executor {<methods>;}

# -----保护注解NotProguard标记-----
-keep class **.NotProguard
-keep @**.NotProguard class * {*;}
-keepclassmembers class * {
  @**.NotProguard <fields>;
  @**.NotProguard <methods>;
}

# -----清理调试日志-----
-assumenosideeffects class **.bukkit.Log {
    public static void d(...);
}

# -----清理性能检测代码-----
-assumenosideeffects class pw.yumc.SurvivalGamesKits.listener.misc.Timings {
    <methods>;
}

SurvivalGamesKits.java

package pw.yumc.SurvivalGamesKits;

import java.io.File;

import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

import me.wazup.survivalgames.SurvivalGames;
import pw.yumc.SurvivalGamesKits.config.SGKConfig;
import pw.yumc.SurvivalGamesKits.item.ItemManager;
import pw.yumc.SurvivalGamesKits.listener.PlayerListener;
import pw.yumc.YumCore.bukkit.Log;
import pw.yumc.YumCore.commands.CommandSub;
import pw.yumc.YumCore.commands.annotation.Cmd;
import pw.yumc.YumCore.commands.annotation.Help;
import pw.yumc.YumCore.commands.interfaces.Executor;
import pw.yumc.YumCore.config.FileConfig;

public class SurvivalGamesKits extends JavaPlugin implements Executor {
    private SurvivalGames sgMain;
    private FileConfig kits;
    private SGKConfig config;

    @Override
    public FileConfiguration getConfig() {
        return config.getConfig();
    }

    public FileConfig getKits() {
        return kits;
    }

    public SGKConfig getSgkConfig() {
        return config;
    }

    public SurvivalGames getSgMain() {
        return sgMain;
    }

    @Override
    public void onEnable() {
        final Plugin plugin = Bukkit.getPluginManager().getPlugin("SurvivalGames");
        if (plugin == null) {
            setEnabled(false);
            return;
        }
        File kitsFile = new File("plugins/SurvivalGames", "kits.yml");
        if (kitsFile.exists()) {
            kits = new FileConfig(kitsFile);
            ItemManager.loadKits();
        } else {
            Log.w("未找到 SurvivalGames 目录下的 kits.yml 文件. 如果是第一次启动 请稍候执行 reload 重新加载!");
        }
        sgMain = (SurvivalGames) plugin;
        new CommandSub("SurvivalGamesKits", this);
        new PlayerListener();
    }

    @Override
    public void onLoad() {
        config = new SGKConfig();
    }

    @Cmd(permission = "SurvivalGamesKits.reload")
    @Help("重载配置文件")
    public void reload(CommandSender sender) {
        config.reload();
        kits.reload();
        ItemManager.loadKits();
        Log.sender(sender, "§a配置文件已重载!");
    }
}

SGKConfig.java
package pw.yumc.SurvivalGamesKits.config;

import pw.yumc.YumCore.config.annotation.ConfigNode;
import pw.yumc.YumCore.config.inject.InjectConfig;

/**
 * @author 喵♂呜
 * @since 2016年9月19日 下午7:35:57
 */
public class SGKConfig extends InjectConfig {
    @ConfigNode("Select.OriginTitle")
    private String sotitle;
    @ConfigNode("Select.NowTitle")
    private String sntitle;
    private Boolean GiveCompassAtStart;
    private String CompassName;
    private String Message;
    private String NoNext;
    private Boolean SavePage;

    /**
     * @return the compassName
     */
    public String getCompassName() {
        return CompassName;
    }

    /**
     * @return the giveCompassAtStart
     */
    public Boolean getGiveCompassAtStart() {
        return GiveCompassAtStart;
    }

    /**
     * @return the message
     */
    public String getMessage() {
        return Message;
    }

    /**
     * @return the noNext
     */
    public String getNoNext() {
        return NoNext;
    }

    /**
     * @return the savePage
     */
    public Boolean isSavePage() {
        return SavePage;
    }

    /**
     * @return the sntitle
     */
    public String getSelNowTitle() {
        return sntitle;
    }

    /**
     * @return the sotitle
     */
    public String getSelOriTitle() {
        return sotitle;
    }

    public Boolean isGiveCompassAtStart() {
        return GiveCompassAtStart;
    }

}

InjectConfig.java

package pw.yumc.YumCore.config.inject;

import java.io.File;

import pw.yumc.YumCore.config.FileConfig;

/**
 * 配置自动载入类
 *
 * @since 2016年7月5日 上午8:53:57
 * @author 喵♂呜
 */
public abstract class InjectConfig extends AbstractInjectConfig {
    public InjectConfig() {
        this(new FileConfig());
    }

    public InjectConfig(File file) {
        this(new FileConfig(file));
    }

    public InjectConfig(FileConfig config) {
        inject(config);
    }

    public InjectConfig(String name) {
        this(new FileConfig(name));
    }

    /**
     * 获得配置文件
     *
     * @return 配置文件
     */
    public FileConfig getConfig() {
        return (FileConfig) config;
    }

    /**
     * 重载配置文件
     */
    public void reload() {
        getConfig().reload();
        inject(config);
    }

    /**
     * 自动化保存
     */
    public void save() {
        save(config);
        getConfig().save();
    }
}

FileConfig.java

package pw.yumc.YumCore.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.MemorySection;
import org.bukkit.configuration.file.YamlConfiguration;

import pw.yumc.YumCore.bukkit.Log;

/**
 * 一个继承于 {@link YamlConfiguration} 的配置文件类
 * 强制UTF-8编码处理所有的文件信息
 *
 * @author 喵♂呜
 * @version 1.0
 * @since 2015年11月7日 下午2:36:07
 */
public class FileConfig extends AbstractConfig {
    protected static String VERSION = "Version";

    private static char ALT_COLOR_CHAR = '&';
    private static String DEFAULT = "config.yml";
    private static String DATA_FORMANT = "yyyyMMddHHmmss";
    private static String CONFIG_BACKUP = "配置: %s 已备份为 %s !";
    private static String CONFIG_UPDATED = "配置: %s 升级成功 版本 %s !";
    private static String CONFIG_OVERRIDE = "配置: %s 将覆盖原有字段数据...";
    private static String CONFIG_NOT_FOUND = "配置: 文件 %s 不存在!";
    private static String CONFIG_READ_ERROR = "配置: %s 读取错误...";
    private static String CONFIG_SAVE_ERROR = "配置: %s 保存错误...";
    private static String CONFIG_UPDATE_WARN = "配置: %s 版本 %s 过低 正在升级到 %s ...";
    private static String CONFIG_CREATE_ERROR = "配置: %s 创建失败...";
    private static String CONFIG_FORMAT_ERROR = "配置: %s 格式错误...";
    private static String CONFIG_BACKUP_ERROR = "配置: %s 备份失败 异常: %s !";
    private static String CONFIG_UPDATE_VALUE = "配置: 更新字段 %s 的值为 %s ...";
    private static String CONFIG_BACKUP_AND_RESET = "配置: %s 格式错误 已备份为 %s 并恢复默认配置!";
    private static String CONFIG_NOT_FOUND_IN_JAR = "配置: 从插件内部未找到预置的 %s 文件!";
    private static String CONFIG_READ_COMMENT_ERROR = "配置: 读取文件注释信息失败!";
    private static String STREAM_NOT_BE_NULL = "数据流不能为 NULL";

    protected File file;

    private CommentConfig commentConfig;

    /**
     * 实例化默认配置文件
     */
    public FileConfig() {
        this(DEFAULT);
    }

    /**
     * 从文件载入配置
     *
     * @param file
     *            配置文件名称
     */
    public FileConfig(File file) {
        Validate.notNull(file, FILE_NOT_BE_NULL);
        init(file);
    }

    /**
     * 从文件载入配置
     *
     * @param parent
     *            文件夹
     * @param filename
     *            配置文件名称
     */
    public FileConfig(File parent, String filename) {
        init(new File(parent, filename), true);
    }

    /**
     * 从数据流载入配置文件
     *
     * @param stream
     *            数据流
     */
    public FileConfig(InputStream stream) {
        init(stream);
    }

    /**
     * 从文件载入配置
     *
     * @param filename
     *            配置文件名称
     */
    public FileConfig(String filename) {
        init(new File(plugin.getDataFolder(), filename), true);
    }

    /**
     * 从文件载入配置
     *
     * @param parent
     *            文件夹
     * @param filename
     *            配置文件名称
     */
    public FileConfig(String parent, String filename) {
        init(new File(parent, filename), true);
    }

    /**
     * 添加到List末尾
     *
     * @param <E>
     *            List内容类型
     * @param path
     *            路径
     * @param obj
     *            对象
     * @return {@link FileConfig}
     */
    public <E> FileConfig addToList(String path, E obj) {
        List<E> l = (List<E>) this.getList(path);
        if (null == l) {
            l = new ArrayList<>();
        }
        l.add(obj);
        return this;
    }

    /**
     * 添加到StringList末尾
     *
     * @param path
     *            路径
     * @param obj
     *            字符串
     * @return {@link FileConfig}
     */
    public FileConfig addToStringList(String path, String obj) {
        addToStringList(path, obj, true);
        return this;
    }

    /**
     * 添加到StringList末尾
     *
     * @param path
     *            路径
     * @param obj
     *            字符串
     * @param allowrepeat
     *            是否允许重复
     * @return {@link FileConfig}
     */
    public FileConfig addToStringList(String path, String obj, boolean allowrepeat) {
        List<String> l = this.getStringList(path);
        if (null == l) {
            l = new ArrayList<>();
        }
        if (allowrepeat || !l.contains(obj)) {
            l.add(obj);
        }
        this.set(path, l);
        return this;
    }

    /**
     * 获得已颜色转码的文本
     *
     * @param cfgmsg
     *            待转码的List
     * @return 颜色转码后的文本
     */
    public List<String> getColorList(List<String> cfgmsg) {
        List<String> message = new ArrayList<>();
        if (cfgmsg == null) { return Collections.emptyList(); }
        for (String msg : cfgmsg) {
            message.add(ChatColor.translateAlternateColorCodes('&', msg));
        }
        return message;
    }

    /**
     * 获得配置文件名称
     *
     * @return 配置文件名称
     */
    public String getConfigName() {
        return file.getName();
    }

    /**
     * 获得Location
     *
     * @param key
     *            键
     * @return {@link Location}
     */
    public Location getLocation(String key) {
        return getLocation(key, null);
    }

    /**
     * 获得Location
     *
     * @param path
     *            键
     * @param def
     *            默认地点
     * @return {@link Location}
     */
    public Location getLocation(String path, Location def) {
        Object val = get(path, def);
        return val instanceof Location ? (Location) val : def;
    }

    /**
     * 获得已颜色转码的文本
     *
     * @param path
     *            配置路径
     * @return 颜色转码后的文本
     */
    public String getMessage(String path) {
        return getMessage(path, null);
    }

    /**
     * 获得已颜色转码的文本
     *
     * @param path
     *            配置路径
     * @param def
     *            默认文本
     * @return 颜色转码后的文本
     */
    public String getMessage(String path, String def) {
        String message = this.getString(path, def);
        if (message != null) {
            message = ChatColor.translateAlternateColorCodes('&', message);
        }
        return message;
    }

    /**
     * 获得已颜色转码的文本
     *
     * @param path
     *            配置路径
     * @return 颜色转码后的文本
     */
    public List<String> getMessageList(String path) {
        List<String> cfgmsg = this.getStringList(path);
        if (cfgmsg == null) { return Collections.emptyList(); }
        for (int i = 0; i < cfgmsg.size(); i++) {
            cfgmsg.set(i, ChatColor.translateAlternateColorCodes(ALT_COLOR_CHAR, cfgmsg.get(i)));
        }
        return cfgmsg;
    }

    /**
     * 获得字符串数组
     *
     * @param path
     *            配置路径
     * @return 字符串数组
     */
    public String[] getStringArray(String path) {
        return this.getStringList(path).toArray(new String[0]);
    }

    @Override
    public void loadFromString(String contents) throws InvalidConfigurationException {
        try {
            commentConfig = new CommentConfig();
            commentConfig.loadFromString(contents);
        } catch (Exception e) {
            Log.d(CONFIG_READ_COMMENT_ERROR);
            commentConfig = null;
        }
        super.loadFromString(contents);
    }

    /**
     * 比较版本号
     *
     * @param newver
     *            新版本
     * @param oldver
     *            旧版本
     * @return 是否需要更新
     */
    public boolean needUpdate(String newver, String oldver) {
        if (newver == null) { return false; }
        if (oldver == null) { return true; }
        String[] va1 = newver.split("\\.");// 注意此处为正则匹配,不能用".";
        String[] va2 = oldver.split("\\.");
        int idx = 0;
        int minLength = Math.min(va1.length, va2.length);// 取最小长度值
        int diff = 0;
        while (idx < minLength && (diff = va1[idx].length() - va2[idx].length()) == 0// 先比较长度
                && (diff = va1[idx].compareTo(va2[idx])) == 0) {// 再比较字符
            ++idx;
        }
        // 如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
        diff = (diff != 0) ? diff : va1.length - va2.length;
        return diff > 0;
    }

    /**
     * 重新载入配置文件
     *
     * @return 是否载入成功
     */
    public boolean reload() {
        return init(file) != null;
    }

    /**
     * 从List移除对象
     *
     * @param <E>
     *            List内容对象类型
     * @param path
     *            路径
     * @param obj
     *            对象
     * @return {@link FileConfig}
     */
    public <E> FileConfig removeFromList(String path, E obj) {
        List<E> l = (List<E>) this.getList(path);
        if (null != l) {
            l.remove(obj);
        }
        return this;
    }

    /**
     * 从StringList移除对象
     *
     * @param path
     *            路径
     * @param obj
     *            对象
     * @return {@link FileConfig}
     */
    public FileConfig removeFromStringList(String path, String obj) {
        List<String> l = this.getStringList(path);
        if (null != l) {
            l.remove(obj);
        }
        this.set(path, obj);
        return this;
    }

    /**
     * 快速保存配置文件
     *
     * @return 是否成功
     */
    public boolean save() {
        try {
            this.save(file);
            return true;
        } catch (IOException e) {
            Log.w(CONFIG_SAVE_ERROR, file.getName());
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public void save(File file) throws IOException {
        Validate.notNull(file, FILE_NOT_BE_NULL);
        if (commentConfig != null) {
            data = commentConfig.saveToString();
        } else {
            data = saveToString();
        }
        super.save(file);
    }

    @Override
    public void set(String path, Object value) {
        if (commentConfig != null) {
            commentConfig.set(path, value);
        }
        super.set(path, value);
    }

    /**
     * 从Jar保存配置文件
     */
    private void saveFromJar() {
        if (plugin != null && file != null) {
            try {
                String filename = file.getName();
                InputStream filestream = plugin.getResource(file.getName());
                String errFileName = this.getErrName(filename);
                file.renameTo(new File(file.getParent(), errFileName));
                if (filestream == null) {
                    file.createNewFile();
                } else {
                    plugin.saveResource(filename, true);
                }
                Log.w(CONFIG_BACKUP_AND_RESET, filename, errFileName);
            } catch (IOException | IllegalArgumentException e) {
                throw new IllegalArgumentException(e);
            }
        } else {
            Log.w(CONFIG_NOT_FOUND_IN_JAR, file != null ? file.getName() : "");
        }
    }

    /**
     * 备份配置文件
     *
     * @param oldcfg
     *            配置文件
     */
    protected void backupConfig(FileConfig oldcfg) {
        String filename = oldcfg.getConfigName();
        try {
            String newCfgName = this.getBakName(filename);
            File newcfg = new File(file.getParent(), newCfgName);
            oldcfg.save(newcfg);
            Log.w(CONFIG_BACKUP, filename, newCfgName);
        } catch (IOException e) {
            Log.w(CONFIG_BACKUP_ERROR, filename, e.getMessage());
            Log.d(oldcfg.getConfigName(), e);
        }
    }

    /**
     * 检查配置文件
     *
     * @param file
     *            配置文件
     */
    protected void check(File file) {
        String filename = file.getName();
        InputStream stream = plugin.getResource(filename);
        try {
            if (!file.exists()) {
                file.getParentFile().mkdirs();
                if (stream == null) {
                    file.createNewFile();
                } else {
                    plugin.saveResource(filename, true);
                }
            } else {
                if (stream == null) { return; }
                FileConfig newcfg = new FileConfig(stream);
                FileConfig oldcfg = new FileConfig(file);
                if (needUpdate(newcfg, oldcfg)) {
                    backupConfig(oldcfg);
                    updateConfig(newcfg, oldcfg).save(file);
                }
            }
        } catch (IOException e) {
            Log.w(CONFIG_CREATE_ERROR, filename);
        }
    }

    protected String getBakName(String cfgname) {
        return cfgname + "." + getStringDate(DATA_FORMANT) + ".bak";
    }

    protected String getErrName(String cfgname) {
        return cfgname + "." + getStringDate(DATA_FORMANT) + ".err";
    }

    /**
     * 获取现在时间
     * 
     * @param format
     *            字符串格式
     * @return yyyy-MM-dd HH:mm:ss
     */
    protected String getStringDate(String format) {
        if (format == null) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        return new SimpleDateFormat(format).format(new Date());
    }

    /**
     * 初始化FileConfig
     *
     * @param file
     *            配置文件
     * @return FileConfig
     */
    protected FileConfig init(File file) {
        init(file, false);
        return this;
    }

    /**
     * 初始化FileConfig
     *
     * @param file
     *            配置文件
     * @param check
     *            是否检查文件
     * @return FileConfig
     */
    protected FileConfig init(File file, boolean check) {
        Validate.notNull(file, FILE_NOT_BE_NULL);
        this.file = file;
        if (check) {
            check(file);
        }
        try {
            init(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            Log.d(CONFIG_NOT_FOUND, file.toPath());
        }
        return this;
    }

    /**
     * 初始化FileConfig
     *
     * @param stream
     *            输入流
     * @return FileConfig
     */
    protected FileConfig init(InputStream stream) {
        Validate.notNull(stream, STREAM_NOT_BE_NULL);
        try {
            this.load(new InputStreamReader(stream, UTF_8));
        } catch (InvalidConfigurationException | IllegalArgumentException ex) {
            if (file == null) { throw new IllegalArgumentException(ex); }
            Log.w(CONFIG_FORMAT_ERROR, file.getName());
            Log.w(ex.getMessage());
            saveFromJar();
        } catch (IOException ex) {
            if (file == null) { throw new IllegalStateException(ex); }
            Log.w(CONFIG_READ_ERROR, file.getName());
        }
        return this;
    }

    /**
     * 检查配置文件版本
     *
     * @param newcfg
     *            新配置文件
     * @param oldcfg
     *            旧配置文件
     * @return 是否需要升级
     */
    protected boolean needUpdate(FileConfig newcfg, FileConfig oldcfg) {
        return needUpdate(newcfg.getString(VERSION), oldcfg.getString(VERSION));
    }

    /**
     * 更新配置文件
     *
     * @param newCfg
     *            新配置文件
     * @param oldCfg
     *            旧配置文件
     * @return 更新以后的配置文件
     */
    protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg) {
        return updateConfig(newCfg, oldCfg, false);
    }

    /**
     * 更新配置文件
     *
     * @param newCfg
     *            新的配置文件
     * @param oldCfg
     *            老的配置文件
     * @param force
     *            是否强制更新
     * @return 更新以后的配置文件
     */
    protected FileConfig updateConfig(FileConfig newCfg, FileConfig oldCfg, boolean force) {
        String filename = oldCfg.getConfigName();
        String newver = newCfg.getString(VERSION);
        String oldver = oldCfg.getString(VERSION);
        Set<String> oldConfigKeys = oldCfg.getKeys(true);
        Log.w(CONFIG_UPDATE_WARN, filename, oldver, newver);
        // 保留版本字段 不更新
        oldConfigKeys.remove(VERSION);
        // 强制更新 去除新版本存在的字段
        if (force) {
            Log.w(CONFIG_OVERRIDE, filename);
            oldConfigKeys.removeAll(newCfg.getKeys(true));
        }
        // 复制旧的数据
        for (String string : oldConfigKeys) {
            Object var = oldCfg.get(string);
            // 需要进行节点检查 还有类型检查 不同类型情况下 使用新配置
            if (var != null && !(var instanceof MemorySection)) {
                Object newVer = newCfg.get(string);
                if (newVer != null && !newVer.getClass().equals(var.getClass())) {
                    Log.w("警告! 旧数据类型与新配置类型不匹配!");
                }
                Log.d(CONFIG_UPDATE_VALUE, string, var);
                newCfg.set(string, var);
            }
        }
        Log.i(CONFIG_UPDATED, filename, newver);
        return newCfg;
    }
}

502647092 avatar Jul 27 '20 05:07 502647092

Thanks for your report. The problem is probably caused by ProGuard inlining inject from the superclass AbstractInjectConfig in InjectConfig:

    public InjectConfig(FileConfig config) {
        inject(config);
    }

I can't reproduce it yet. If you can share these two compiled class files, that may help.

For now, you can probably work around it by keeping the inject method

-keepclassmembers class pw.yumc.SurvivalGamesKits.config.inject.AbstractInjectConfig { *** inject(...); }

or by disabling method inlining

-optimizations !method/inlining/*

EricLafortune avatar Aug 24 '20 22:08 EricLafortune