Кто-либо когда-либо пытался объединить использование облика 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
Атрибут "Signature" необходим для доступа к общим типам при компиляции в JDK 5.0 и выше.
Используйте -keepattributes Signature для исправления ошибки с ParameterizedType
После длительного использования proguard, вот как я решил решить проблемы, связанные с отражением (и Guice является лишь одним из вариантов его использования).
Отражение может использоваться с Proguard до тех пор, пока НИКАКИЕ имена классов или методов не вводятся как строки.
Это означает, что этот код действителен и будет работать после обфускации ProGuard
Class someClass = Class.forName(SomeClass.class.getName());
, в то время как этот код не будет работать
Class someClass = Class.forName("SomeClass");
Кроме того, Proguard будет сжимать невызванные методы и конструктор. Как следствие, метод Class.newInstance
работать не будет. К сожалению, обычные привязки Guice работают с этим методом.
Это имеет некоторые последствия для кода Guice.