2010-03-03 5 views
7

Hat jemand schon einmal die Nutzung von Google Guice mit Verschleierung zu kombinieren versucht (insbesondere proguard)? Die verschleierten Version meines Code nicht mit Google Guice arbeiten als guice beschwert sich über Typ-Parameter fehlen. Diese Information scheint durch den Transformationsschritt gelöscht werden, dass proguard tut, auch wenn die entsprechenden Klassen aus der Verschleierung ausgeschlossen.Injection mit Google Guice funktioniert nicht mehr nach Verschleierung mit proguard

Der Stack-Trace sieht wie folgt aus:

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) 

Ich versuchte, ein kleines Beispiel zu erstellen (ohne guice zu verwenden) das scheint das Problem zu reproduzieren:

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(); 
     } 

    } 

} 

Wenn Sie diesen Code ausführen unsbfuscated , sieht die Ausgabe so aus:

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

Aber läuft die Version mit Pro verschleiert Wache ergibt:

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

Dies sind die Optionen, die ich für die Verschleierung verwendet:

-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); 
} 

Hat jemand eine Idee, wie diese zu lösen (abgesehen von den offensichtlichen Problemumgehung die entsprechenden Dateien in eine separate zu setzen Glas und nicht verschleiern es)?

Mit freundlichen Grüßen,
Stefan

Antwort

8

proguard für eine gute Zeit verwendet haben, hier ist, wie ich die Fragen in Bezug auf Reflexion zu lösen entschieden (und Guice ist nur ein Anwendungsfall davon).

Reflexion kann so lange mit Proguard verwendet werden, wie NO Klasse oder Methoden Name als Strings eingetragen sind.

, dass dieser Code zu sagen, ist gültig und wird

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

nach ProGuard Verschleierungs arbeiten, während dieser Code nicht

Außerdem
Class someClass = Class.forName("SomeClass"); 

funktionieren wird, wird Proguard uncalled Methoden und Konstruktor schrumpfen. Als Konsequenz wird die Class.newInstance Methode nicht funktionieren. Unglücklicherweise funktionieren übliche Guice-Bindungen mit dieser Methode.

Dies hat einige Auswirkungen auf Code Guice.

  • Alle Ihre Injektionen müssen mit @Provides annotierten Methoden erzeugt werden, da ProGuard Klassen aufgrund der Tatsache, dass ihre Konstruktoren nicht explizit aufgerufen werden, verkleinern wird.
  • Proguard müssen Sie den Code Ihrer Module Klassen nicht schrumpfen.
  • ProGuard darf keine Annotationen verkleinern, egal wo und wo sie sind (dies kann konfiguriert werden, aber ich kann mich nicht erinnern, wo).
  • +1

    Wow, das ist eine schreckliche Nachricht, dass Sie @Provides Methoden verwenden müssen, nur um ProGuard davon abzuhalten, die Abhängigkeiten zu entfernen. Dies bittet um ein Werkzeug, um zu helfen. Ich nehme an, es würde auch (fast genauso ärgerlich) funktionieren, ein paar Warteschlangen in der Proguard-Konfiguration zu halten. –

    +0

    Vielleicht, weil das Hinzufügen der -keep-Annotation Refactorings weniger effektiv macht, da wir sicherstellen müssen, dass Klassennamen im Ausgabe-Jar gültig sind. Meiner Meinung nach macht der Betrieb auf einer reinen Java-Ebene unseren Code Refactoring-kompatibel (wenn so etwas existiert) – Riduidel

    7

    Das Attribut "Signature" wird benötigt, um beim Kompilieren in JDK 5.0 und höher auf generische Typen zugreifen zu können.

    Verwenden -keepattributes Unterschrift zu beheben Fehler mit ParameterizedType

    +0

    Es behebt das Problem nicht aus dem obigen Beispiel. Ich muss es immer noch auf mein ursprüngliches Problem mit Google Guice versuchen. – sme

    +1

    Das reparierte es für mich auf Android mit dem No-Aop-Build, ich hatte das gleiche Problem wie das OP. Ich habe auch die folgenden in Proguard-Konfiguration. -keepclassmembers Klasse * { @ com.google.inject.Inject (...); } – abombss

    +0

    Dies funktionierte auch für mich, mit dem gleichen Problem wie der Fragesteller hatte !! – Peterdk

    0

    folgenden Code funktioniert für mich, das gleiche Problem gehabt zu haben.

    -keepattributes Signature war die Lösung.

    -optimizationpasses 5 
    -dontusemixedcaseclassnames 
    -dontskipnonpubliclibraryclasses 
    -dontpreverify 
    #-dontobfuscate 
    -repackageclasses '' 
    -keepattributes *Annotation* 
    -keepattributes Signature 
    -verbose 
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 
    
    -keep public class * extends android.app.Activity 
    -keep public class * extends android.app.Application 
    -keep public class * extends android.app.Service 
    -keep public class * extends android.content.BroadcastReceiver 
    -keep public class * extends android.content.ContentProvider 
    -keep public class * extends android.app.backup.BackupAgentHelper 
    -keep public class * extends android.preference.Preference 
    -keep public class com.android.vending.licensing.ILicensingService 
    
    -keepclasseswithmembernames class * { 
        native <methods>; 
    } 
    
    -keepclasseswithmembernames class * { 
        public <init>(android.content.Context, android.util.AttributeSet); 
    } 
    
    -keepclasseswithmembernames class * { 
        public <init>(android.content.Context, android.util.AttributeSet, int); 
    } 
    
    -keepclassmembers enum * { 
        public static **[] values(); 
        public static ** valueOf(java.lang.String); 
    } 
    -keepattributes Signature 
    -keep class * implements android.os.Parcelable { 
        public static final android.os.Parcelable$Creator *; 
    } 
    -keep class com.google.inject.Binder 
    -keepclassmembers class * { 
        @com.google.inject.Inject <init>(...); 
    } 
    -keep public class * extends android.view.View { 
        public <init>(android.content.Context); 
        public <init>(android.content.Context, android.util.AttributeSet); 
        public <init>(android.content.Context, android.util.AttributeSet, int); 
        public void set*(...); 
    } 
    
    # I didn't need this one, maybe you need it. 
    #-keep public class roboguice.** 
    
    -keepclassmembers class **.R$* { 
        public static <fields>; 
    } 
    
    3

    Mit der aktuellen Version von Proguard (4.7) konnte ich es, indem Sie die folgenden zum Laufen bringen: -

    -keepattributes *Annotation*,Signature 
    -keep class com.google.inject.Binder  
    -keep public class com.google.inject.Inject 
    # keeps all fields and Constructors with @Inject 
    -keepclassmembers,allowobfuscation class * { 
        @com.google.inject.Inject <fields>; 
        @com.google.inject.Inject <init>(...); 
    } 
    

    Zusätzlich jede Klasse explizit zu halten, die von Guice zB

    erstellt
    -keep class com.example.Service 
    
    +0

    Diese Änderung erfordert nicht explizit Ihre @Inject Klassen hinzugefügt (die wie in anderen Beiträgen festgestellt, ist fehleranfällig): '-keepclasseswithmembers, allowoptimization, allowobfuscation Klasse * { @ com.google.inject.Inject ; } -keepclassmembers, allowobfuscation, allowoptimization class * { @ com.google.inject.Provides ; } ' – enl8enmentnow

    Verwandte Themen