我的.jar文件没有常见的混淆名称,混淆的类看起来像:
nul.goto. ...\\.. .final.
(注意:第一个间隙不是正常空间,它是不间断空间)
我不能通过Class.forName
获得这个课程
我使用这样的混淆来制作我自己的代码版本,即使我使用Class.forName(SomeClass.class.getName())
(它只是代码来测试)也不起作用,在混淆之后java会抛出无法找到这个类的错误。<登记/>
如何上课?
答案 0 :(得分:0)
所以一段时间后,我决定回到这一点,我使用了如下代码进行测试:
A B C D
e -1.393951 -0.725751 -1.063748 -0.271371
:
pckg.Main
被ProGuard迷惑:
public static void main(String[] args) {
Class<ObfuscateMe> obfuscateMeClass = ObfuscateMe.class;
System.out.println("Class name: `" + obfuscateMeClass + "`");
try {
System.out.println("Class.forName: " + Class.forName(obfuscateMeClass.getName()));
}
catch (ClassNotFoundException exception) { System.out.println("Can't find class using Class.forName: `" + obfuscateMeClass.getName() + "`"); }
try {
System.out.println("ClassLoader.loadClass: " + Main.class.getClassLoader().loadClass(obfuscateMeClass.getName()));
}
catch (ClassNotFoundException exception) { System.out.println("Can't find class using ClassLoader.loadClass: `" + obfuscateMeClass.getName() + "`"); }
}
首先,我注意到这不再是Java 11中的问题:像这样的类将无法加载并显示错误:
-injars 'B:\Java\ProGuardTestApp\test.jar'
-outjars 'B:\Java\ProGuardTestApp\testObf.jar'
-dontshrink
-dontoptimize
-classobfuscationdictionary 'B:\Java\ProGuardTestApp\obfs.txt' # contains just one line "final"
-repackageclasses 'nul.goto. ...\\.. .final.'
-ignorewarnings
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
但是Error: LinkageError occurred while loading main class pckg.Main
java.lang.ClassFormatError: Illegal class name "nul/goto/▒///\\// /final//final" in
class file pckg/Main
和forName
之间仍然存在不一致,loadClass
仍然会抛出forName
,而ClassNotFoundException
会抛出loadClass
。在这两种情况下,OpenJ9都抛出ClassFormatError
。
在Java 8热点上它可以正常工作,就像@Holger在注释中建议的那样,使用ClassLoader的版本也可以正常工作。所以我决定去挖掘一下原因。
在类加载器中,它只是转到ClassFormatError
:URLClassLoader
中的一段非常简单的代码,并通过本机方法name.replace('.', '/').concat(".class");
从jar加载该类而没有任何问题。
但是defineClass
直接进入本机方法并验证类名称:http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/native/java/lang/Class.c
Class.forName
因此所有if (VerifyFixClassname(clname) == JNI_TRUE) {
/* slashes present in clname, use name b4 translation for exception */
(*env)->GetStringUTFRegion(env, classname, 0, unicode_len, clname);
JNU_ThrowClassNotFoundException(env, clname);
goto done;
}
if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
JNU_ThrowClassNotFoundException(env, clname);
goto done;
}
都更改为.
,然后在/
中我们可以找到它:
VerifyClassname
这会阻止类的加载。