【问题标题】:Why do I get an error with ProGuard obfuscation, but not without the obfuscation?为什么我在使用 ProGuard 混淆时会出错,但在没有混淆时却没有?
【发布时间】:2015-05-03 04:56:26
【问题描述】:

NPE - http://pastebin.com/gzuf3x1k(当我执行混淆文件时出现)。 (带有 LineNumber 的 StackTrace:http://pastebin.com/ddY3Ei9G

(混淆后的堆栈跟踪:http://pastebin.com/svipdakN

addRefreshedVersionsListener(VersionManager.java):

public void addRefreshedVersionsListener(RefreshedVersionsListener listener){
    this.refreshedVersionsListeners.add(listener);
}

getResourceFiles(VersionManager.java):

private Set<Downloadable> getResourceFiles(Proxy proxy, File baseDirectory, CompleteVersion version)
    {
        Set result = new HashSet();
        InputStream inputStream = null;
        File assets = new File(baseDirectory, "assets");
        File objectsFolder = new File(assets, "objects");
        File indexesFolder = new File(assets, "indexes");
        String indexName = version.getAssets();
        long start = System.nanoTime();
        if (indexName == null) {
            indexName = "legacy";
        }
        File indexFile = new File(indexesFolder, indexName + ".json");
        try
        {
            URL indexUrl = new URL("https://s3.amazonaws.com/Minecraft.Download/indexes/" + indexName + ".json");
            inputStream = indexUrl.openConnection(proxy).getInputStream();
            String json = IOUtils.toString(inputStream);
            FileUtils.writeStringToFile(indexFile, json);
            AssetIndex index = (AssetIndex)this.gson.fromJson(json, AssetIndex.class);
            for (AssetIndex.AssetObject object : index.getUniqueObjects())
            {
                String filename = object.getHash().substring(0, 2) + "/" + object.getHash();
                File file = new File(objectsFolder, filename);
                if ((!file.isFile()) || (FileUtils.sizeOf(file) != object.getSize()))
                {
                    Downloadable downloadable = new AssetDownloadable(proxy, new URL("http://resources.download.minecraft.net/" + filename), file, false, object.getHash(), object.getSize());
                    downloadable.setExpectedSize(object.getSize());
                    result.add(downloadable);
                }
            }
            long end = System.nanoTime();
            long delta = end - start;
            Launcher.getInstance().println("Delta time to compare resources: " + delta / 1000000L + " ms ");
        }
        catch (IOException|JsonSyntaxException ex)
        {
            Launcher.getInstance().println("Couldn't download resources", ex);
        }
        finally
        {
            IOUtils.closeQuietly(inputStream);
        }
        return result;
    }

& 第一个原因 [at net.minecraft.launcher.updater.VersionManager.refreshVersions(VersionManager.java)]

   public void refreshVersions() throws IOException {
      this.clearCache();
      File[] files = this.baseVersionsDir.listFiles();
      if(files != null) {
         File[] i$ = files;
         int version = files.length;

         for(int type = 0; type < version; ++type) {
            File directory = i$[type];
            String id = directory.getName();
            File jsonFile = new File(directory, id + ".json");
            if(directory.isDirectory() && jsonFile.exists()) {
               try {
                  String ex = "versions/" + id + "/" + id + ".json";
                  CompleteVersion version1 = (CompleteVersion)this.gson.fromJson(this.getContent(ex), CompleteVersion.class);
                  if(version1.getId().equals(id)) {
                     this.addVersion(version1);
                  } else if(Launcher.getInstance() != null) {
                     Launcher.getInstance().println("Ignoring: " + ex + "; it contains id: \'" + version1.getId() + "\' expected \'" + id + "\'");
                  }
               } catch (RuntimeException var10) {
                  if(Launcher.getInstance() == null) {
                     throw new JsonSyntaxException("Loading file: " + jsonFile.toString(), var10);
                  }
                  Launcher.getInstance().println("Couldn\'t load local version " + jsonFile.getAbsolutePath(), var10);
               }
            }
         }

堆栈跟踪上的原因位置:

CompleteVersion version1 = (CompleteVersion)this.gson.fromJson(this.getContent(ex), CompleteVersion.class);
                  if(version1.getId().equals(id)) {
                     this.addVersion(version1);
                  } else if(Launcher.getInstance() != null) {
                     Launcher.getInstance().println("Ignoring: " + ex + "; it contains id: \'" + version1.getId() + "\' expected \'" + id + "\'");
                  }

出于某种奇怪的原因,GSON API 中的 fromJson 方法总是会发生这种情况(在混淆后执行时)。

CompleteVersion 类:http://pastebin.com/dF6aXCjS

【问题讨论】:

  • 源代码的哪一行发生异常?
  • 那么......哪一行>>是
  • if(version1.getId().equals(id)) { 是行
  • 似乎是因为 version1 可能为空。 as version1 = (CompleteVersion)this.gson.fromJson(this.getContent(ex), CompleteVersion.class);这是没有意义的,因为它在没有被混淆时有效,但在被混淆时无效。

标签: java proguard obfuscation


【解决方案1】:

我猜这是因为当 GSON 尝试解析 JSON 时,它使用 CompleteVersion 类中的属性名称。如果这些名称被破坏,GSON 将无法在 JSON 中找到属性名称,因此属性将简单地为空。

Another StackOverflow question 似乎有几个解决这个问题的方法。我个人从未使用过 ProGuard,但看起来您可以尝试在 proguard.cfg 中添加类似 -keep class net.minecraft.launcher.versions.CompleteVersion { *; } 的内容,这样 ProGuard 就不会触及 CompleteVersion 类。

【讨论】:

  • 如果您愿意,可以通过记录version1.toString()来确认这是否属实
  • 是的。感谢您的回答,我已应用您的回答来尝试解决另一个问题。虽然在这种情况下不起作用:(StackTrace)pastebin.com/iUE0KzMT
  • 指向 net.minecraft.launcher.profile.ProfileManager.loadProfiles(ProfileManager.java:128) 指向这一行:final RawProfileList rawProfileList = gson.fromJson(fileData, type);
  • 我用过-keep class net.minecraft.launcher.profile.RawProfileList { *; } 虽然我遇到了这个错误,但它并没有解决它@gengkev
  • 也许你可以对 Profile 类做同样的事情?有关更多指导,请参阅链接的 SO 问题;就像我说的,我从来没有真正使用过 Proguard ;)
猜你喜欢
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 2016-07-04
  • 2012-03-27
  • 2019-03-15
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多