Инжекция с обликом Google не работает больше после путаницы с прозащитой

Кто-либо когда-либо пытался объединить использование облика Google с путаницей (в особенности прозащита)? Запутываемая версия моего кода не работает с обликом Google, поскольку облик жалуется на недостающие параметры типа. Эта информация, кажется, стирается шагом преобразования, который делает прозащита, даже когда соответствующие классы исключены из путаницы.

Отслеживание стека похоже на это:

com.google.inject.CreationException: Guice creation errors:

1) Cannot inject a Provider that has no type parameter
  while locating com.google.inject.Provider
    for parameter 0 at de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel.setPasswordPanelProvider(SourceFile:499)
  at de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel.setPasswordPanelProvider(SourceFile:499)
  while locating de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel
    for parameter 0 at de.repower.lvs.client.admin.user.administration.b.k.setParentPanel(SourceFile:65)
  at de.repower.lvs.client.admin.user.administration.b.k.setParentPanel(SourceFile:65)
  at de.repower.lvs.client.admin.user.administration.o.a(SourceFile:38)

2) Cannot inject a Provider that has no type parameter
  while locating com.google.inject.Provider
    for parameter 0 at de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel.setWindTurbineAccessGroupProvider(SourceFile:509)
  at de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel.setWindTurbineAccessGroupProvider(SourceFile:509)
  while locating de.repower.lvs.client.admin.user.administration.AdminUserCommonPanel
    for parameter 0 at de.repower.lvs.client.admin.user.administration.b.k.setParentPanel(SourceFile:65)
  at de.repower.lvs.client.admin.user.administration.b.k.setParentPanel(SourceFile:65)
  at de.repower.lvs.client.admin.user.administration.o.a(SourceFile:38)

2 errors
    at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:354)
    at com.google.inject.InjectorBuilder.initializeStatically(InjectorBuilder.java:152)
    at com.google.inject.InjectorBuilder.build(InjectorBuilder.java:105)
    at com.google.inject.Guice.createInjector(Guice.java:92)
    at com.google.inject.Guice.createInjector(Guice.java:69)
    at com.google.inject.Guice.createInjector(Guice.java:59)

Я пытался создать небольшой пример (не используя облик), который, кажется, воспроизводит проблему:

package de.repower.common;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

class SomeClass<S> { 
}

public class ParameterizedTypeTest {

    public void someMethod(SomeClass<Integer> param) {
        System.out.println("value: " + param);
        System.setProperty("my.dummmy.property", "hallo");
    }

    private static void checkParameterizedMethod(ParameterizedTypeTest testObject) {
        System.out.println("checking parameterized method ...");
        Method[] methods = testObject.getClass().getMethods();
        for (Method method : methods) {
            if (method.getName().equals("someMethod")) {
                System.out.println("Found method " + method.getName());
                Type[] types = method.getGenericParameterTypes();
                Type parameterType = types[0];
                if (parameterType instanceof ParameterizedType) {
                    Type parameterizedType = ((ParameterizedType) parameterType).getActualTypeArguments()[0];
                    System.out.println("Parameter: " + parameterizedType);
                    System.out.println("Class: " + ((Class) parameterizedType).getName());
                } else {
                    System.out.println("Failed: type ist not instance of ParameterizedType");
                }
            }
        }
    }

    public static void main(String[] args) {
        System.out.println("Starting ...");
        try {
            ParameterizedTypeTest someInstance = new ParameterizedTypeTest();
            checkParameterizedMethod(someInstance);
        } catch (SecurityException e) {
            e.printStackTrace();
        }

    }

}

При выполнении этого кода unsbfuscated вывод похож на это:

Starting ...
checking parameterized method ...
Found method someMethod
Parameter: class java.lang.Integer
Class: java.lang.Integer

Но выполнение версии запутало с прозащитными урожаями:

Starting ...
checking parameterized method ...
Found method someMethod
Failed: type ist not instance of ParameterizedType

Это опции, которые я использовал для путаницы:

-injars classes_eclipse\methodTest.jar
-outjars classes_eclipse\methodTestObfuscated.jar

-libraryjars 'C:\Program Files\Java\jre6\lib\rt.jar'

-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontshrink
-printusage classes_eclipse\shrink.txt
-dontoptimize
-dontpreverify
-verbose


-keep class **.ParameterizedTypeTest.class {
    <fields>;
    <methods>;
}

-keep class ** {
    <fields>;
    <methods>;
}

# Keep - Applications. Keep all application classes, along with their 'main'
# methods.
-keepclasseswithmembers public class * {
    public static void main(java.lang.String[]);
}

# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum  * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
-keep class * extends java.sql.Driver

# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
# along with the special 'createUI' method.
-keep class * extends javax.swing.plaf.ComponentUI {
    public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
}

# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,allowshrinking class * {
    native <methods>;
}

# Keep names - _class method names. Keep all .class method names. This may be
# useful for libraries that will be obfuscated again with different obfuscators.
-keepclassmembers,allowshrinking class * {
    java.lang.Class class$(java.lang.String);
    java.lang.Class class$(java.lang.String,boolean);
}

У кого-либо есть идея того, как решить это (кроме очевидного обходного решения, чтобы поместить соответствующие файлы в отдельную банку и не запутать его)?

С уважением,
Stefan

7
задан sme 3 March 2010 в 09:48
поделиться

2 ответа

Атрибут "Signature" необходим для доступа к общим типам при компиляции в JDK 5.0 и выше.

Используйте -keepattributes Signature для исправления ошибки с ParameterizedType

7
ответ дан 6 December 2019 в 10:49
поделиться

После длительного использования proguard, вот как я решил решить проблемы, связанные с отражением (и Guice является лишь одним из вариантов его использования).

Отражение может использоваться с Proguard до тех пор, пока НИКАКИЕ имена классов или методов не вводятся как строки.

Это означает, что этот код действителен и будет работать после обфускации ProGuard

Class someClass = Class.forName(SomeClass.class.getName());

, в то время как этот код не будет работать

Class someClass = Class.forName("SomeClass");

Кроме того, Proguard будет сжимать невызванные методы и конструктор. Как следствие, метод Class.newInstance работать не будет. К сожалению, обычные привязки Guice работают с этим методом.

Это имеет некоторые последствия для кода Guice.

  • Все ваши инъекции должны производиться с использованием аннотированных методов @Provides, поскольку ProGuard будет сжимать классы из-за того, что их конструкторы не вызываются явно.
  • Proguard не должен сжимать код классов ваших модулей.
  • ProGuard не должен сжимать аннотации, какие бы они ни были и где бы они ни находились (это можно настроить, но я не могу вспомнить, где).
8
ответ дан 6 December 2019 в 10:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: