【问题标题】:MalformedParameterizedTypeException when using proguard使用 proguard 时出现 MalformedParameterizedTypeException
【发布时间】:2013-11-24 21:16:21
【问题描述】:

我正在使用 proguard 来缩小阴影 jar 以用作命令行工具。阴影 jar 工作正常,但在运行 proguard 创建的 jar 时出现异常。该应用程序使用 Guice 注入,我添加了我在 SO 上找到的配置,主要是在 this answer

这是例外:

Exception in thread "main" java.lang.reflect.MalformedParameterizedTypeException
        at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.validateConstructorArguments(ParameterizedTypeImpl.java:60)
        at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.<init>(ParameterizedTypeImpl.java:53)
        at sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.make(ParameterizedTypeImpl.java:95)
        at sun.reflect.generics.factory.CoreReflectionFactory.makeParameterizedType(CoreReflectionFactory.java:105)
        at sun.reflect.generics.visitor.Reifier.visitClassTypeSignature(Reifier.java:140)
        at sun.reflect.generics.tree.ClassTypeSignature.accept(ClassTypeSignature.java:49)
        at sun.reflect.generics.repository.ClassRepository.getSuperclass(ClassRepository.java:84)
        at java.lang.Class.getGenericSuperclass(Class.java:696)
        at com.google.inject.internal.MoreTypes.getGenericSupertype(MoreTypes.java:273)
        at com.google.inject.TypeLiteral.getSupertype(TypeLiteral.java:257)
        at com.google.inject.spi.InjectionPoint.hierarchyFor(InjectionPoint.java:755)
        at com.google.inject.spi.InjectionPoint.getInjectionPoints(InjectionPoint.java:635)
        at com.google.inject.spi.InjectionPoint.forInstanceMethodsAndFields(InjectionPoint.java:356)
        at com.google.inject.internal.ConstructorBindingImpl.getInternalDependencies(ConstructorBindingImpl.java:151)
        at com.google.inject.internal.InjectorImpl.getInternalDependencies(InjectorImpl.java:585)
        at com.google.inject.internal.InjectorImpl.cleanup(InjectorImpl.java:543)
        at com.google.inject.internal.InjectorImpl.initializeJitBinding(InjectorImpl.java:529)
        at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:847)
        at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772)
        at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256)
        at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205)
        at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:853)
        at com.google.inject.internal.FactoryProxy.notify(FactoryProxy.java:46)
        at com.google.inject.internal.ProcessedBindingData.runCreationListeners(ProcessedBindingData.java:50)
        at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:133)
        at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
        at com.google.inject.Guice.createInjector(Guice.java:95)
        at com.google.inject.Guice.createInjector(Guice.java:72)
        at com.google.inject.Guice.createInjector(Guice.java:62)
        at com.acme.ui.cli.Main.main(Main.java:44)

这是产生它的配置:

-injars acme-cli-0.2.1-SNAPSHOT.jar
-outjars target/acme-cli-0.2.1-SNAPSHOT.jar

-libraryjars /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre/lib/jce.jar
-libraryjars /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre/lib/jsse.jar
-libraryjars /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre/lib/rt.jar

-dontobfuscate
-dontpreverify
-dontoptimize
-printmapping mapping.map
-ignorewarnings
-keepattributes *Annotation*,Signature  


# Keep - Applications. Keep all application classes, along with their 'main' methods.
-keep public class com.acme.ui.cli.Main {
    public static void main(java.lang.String[]);
}


# Keep Guice-related classes
-keep public class javax.inject.**
-keep class com.google.inject**
-keep class * extends com.google.inject.AbstractModule

 # keeps all fields and Constructors annotated with @Inject and @AssistedInject
-keepclasseswithmembers class * {
    @com.google.inject.Inject <fields>;
    @com.google.inject.Inject <init>(...);
}

-keepclasseswithmembers class * {
    @com.google.inject.assistedinject.AssistedInject <fields>;
    @com.google.inject.assistedinject.AssistedInject <init>(...);
}

当我添加这个问题时,问题就消失了:

-keep class * {
   <init>(...);
}

但它保留了更多的类,并使 jar 的大小增加了一倍。我正在使用 proguard 4.10 并尝试过 4.9。以下是我尝试过的一些似乎最相关的选项:

    -keepattributes *
    -keepparameternames
    -keep class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl {
        <init>(...);
    }

由于它似乎与 Guice 相关并且保留所有构造函数可以解决问题,因此我还尝试了各种方法来配置保留选项而没有结果。但我必须说我并不完全理解它们。

我不确定它是否与问题有关,但看起来很奇怪的是 ParameterizedTypeImpl 类中唯一的构造函数具有这样的签名:private ParameterizedTypeImpl(java.lang.Class&lt;?&gt; aClass, java.lang.reflect.Type[] types, java.lang.reflect.Type type),但堆栈跟踪中的签名看起来像是在接受 ParameterizedTypeImpl 本身:ParameterizedTypeImpl.&lt;init&gt;(ParameterizedTypeImpl.java:53)

现在我被困住了;非常感谢任何可以进一步帮助我的建议。

【问题讨论】:

  • 你解决了这个问题吗?
  • 我还发布了same question on the proguard forum,在那里我得到了回复。您可能可以使用一些建议,但罪魁祸首似乎是一个错误。我们还没有发布示例供 proguard 的维护者调查,可能还需要两周时间。
  • 如果有用,我会在这里发布我们的发现。如果您在我们做之前发现任何有用的东西,您介意也分享一下吗?

标签: java reflection guice proguard


【解决方案1】:

这是一个在 Proguard 5.0 中修复的已知错误。见https://sourceforge.net/p/proguard/bugs/518/

【讨论】:

  • 感谢您隔离问题。几个小时后,我们没有丝毫线索。现在我们尝试了解决方法;即使我们也使用 logback,在我们的例子中它仍然给出相同的异常,没有明显的区别。毫无疑问,我们需要在解决方法中包含一个或多个其他接口,因为它是一个具有许多依赖项的大型项目;您是否通过消除过程找到了罪魁祸首,还是我们可以尝试其他方法?
  • 如果我们顺便保留所有接口,它就可以工作。所以我们知道我们的问题是由同一个问题引起的。
  • @RolfW。是的,我一直在删除 Proguard 规则和正在处理的类,直到我最终得到一个必要的最小测试用例来结束这个异常。这花费了很多工作,但值得庆幸的是,最终的努力是值得的。我比平时更加​​努力,因为我知道 Eric 在快速修复错误方面有着良好的记录:)
  • 我们做了类似的事情,但并没有一路走好。最乏味和耗时的是每次都必须重新运行该过程,不是吗?非常感谢您推动并让我知道!我很高兴这个问题一下子解决了。
猜你喜欢
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多