インタビューの前に、インタビュアーに関連する多くの問題がある場合、クラスローダを要求するので、これは非常に重要なポイントです。そして、高度なアンドロイドの研究開発の面で、より多くのクラスローディング関連の事を知って、開発が暗号のようなホットな更新など多くの援助、となります。
実際に、私は一種の、ビットに少し研究を興味を持って暗号化。クラス暗号化事実は、APPの逆コンパイルを防ぐために、多くは、このような混乱、補強逆コンパイル方法として、があります防ぎます。自分のクラスファイルは暗号化され、カスタムクラスローダは一つの方法です。
まず、我々のコードはコンパイルパッケージの後にバイナリバイトコードを読み取ることが困難になる、との.classファイルになります。コンパイラは、単純なAPPを逆コンパイルすることができた後しかし、あなたが書いたとしても、コードが完全に露出されます。あなたのコードは、おそらく、実際にAPPのビジネス情報が漏洩することがあなたのことが重要である、コピーが小さい、コピーされます!
単純な例シーンが逆コンパイルされ、次の:
したがって、ユーザー容易に逆コンパイルソースコードファイルを防止するために、.classファイルは、暗号解読するために必要なファイルと、その後特別なクラスによってロードされ、クラスのロードメモリに。
まずその暗号化、いくつかの.classバイトコードファイルの変換よりも暗号何の、暗号の知識が伴うだろう!プライバシーを向上させるためには、DES、AES、RSA暗号化を検討する多くの方法があります。ソースコードの暗号化アルゴリズムが開示されると、実際には、亀裂があなたがまだ時間タイムリーな交換用キーに、安全性の高いパスワードシステムを使用することが推奨され、非常にシンプルなものです。それはある程度推測することの難しさを向上させることができます。
暗号化アルゴリズムを使用すると、次のステップは、バイトコードファイルを暗号化することです。
private static File file = null;
private static String path = null;
// 读取已经编译好的正常的class字节码文件
public static void readClass(String filePath) throws Exception {
file = new File(filePath);
path = filePath;
}
// 加密生成已加密的class字节码文件
public static void encrypt() throws Exception {
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(path.substring(0,
path.lastIndexOf(".class"))
+ "附件.class");
byte[] b = new byte[1024];
int ch = 0;
while ((ch = fis.read(b)) != -1) {
// 变换b
b=crypt(b, "encrypt");
fos.write(b, 0, ch);
}
}
このとき、READCLASS方法と暗号化メソッドを呼び出して、元のディレクトリXX.classファイル内の.class附属書XXを生成することができます。この時点で、我々は、バイトコードファイルのこのコピーを使用して、元のを削除し、次の実行は、これがどうなるときに復号化されます。
暗号化のクラスの後、クラスにあなたの方法を確認し、それをロードします。我々はまた、クラスローダのクラスを記述する必要があり、通常の時間がメモリにロードされます。だから、それはクラスローダの知識に来ます:
3つのデフォルトクラスローダ、すなわち:ブートストラップ、ExtClassLoader、AppClassLoader。したがって、これらのクラスローダは、それがどのような違いを生むのでしょうか?
ファーストクラスローダは親子関係を持っています。祖父(C ++で記述されたが、負荷のjre / libに/ rt.jarのために主に責任がある)、ブートストラップ、ExtClassLoaderお父さんは(主にロードJRE / libに/内線/ *。ジャーのため)、AppClassLoaderは、指定されたディレクトリのCLASSPATHをロードするための責任の息子(ありますすべてのjarファイル)の下で。
だから我々は、一般的にAppClassLoaderクラスファイルがロードされている書き込み。我々は、我々はこのクラスのコピーを持っているクラスを書いた場合、ExtClassLoaderディレクトリを置くこと、そしてクラスローダはそれをロードする方法でしょうか?クラスローダの委譲メカニズムを言及する必要があります。
デリゲートクラスローダのメカニズム:スレッドがクラスをロードするために、現在のスレッドの最初のクラスローダと、クラスを呼び出すと、クラスローダが最初にロードされないが、負荷に親クラスローダの彼を通知しますタイムブートストラップローダーまで、場合のは、下のローダがロードするために呼び出すことはできませ。それは、ClassNotFoundExceptionが報告しなかった場合。あなたは直接ロードするためにクラスローダを指定することができます。
だから我々は、これが私たちの暗号化されたクラスをロードするために、このクラスローダを作成してみましょう、あなた自身のクラスローダを定義することができます。カスタムクラスローダはClassLoaderクラスの継承を必要とし、にfindClassメソッドを書き換えます。
class MyClassLoader extends ClassLoader {
private String path = null;
// 设置自定义类加载器的目录
public MyClassLoader(String path) {
this.path = path;
}
/*
* findClass和loadClass的区别?
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
File f = new File(path, name.substring(name.lastIndexOf('.') + 1)
+ ".class");
FileInputStream fis = new FileInputStream(f);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch = 0;
while ((ch = fis.read()) != -1) {
bos.write(ch);
}
byte[] buf = bos.toByteArray();
//解密.class
buf = Z1Encrypt.crypt(buf, "decrypt");
fis.close();
bos.close();
//根据字节码返回这个类
return defineClass(name, buf, 0, buf.length);
} catch (Exception e) {
throw new ClassNotFoundException(name + " is not found!");
}
}
}
その後、我々は我々の暗号化ファイルのバイトコードを解読ロードするために、当社のカスタムクラスローダを使用しました
public static void main(String[] args) throws Exception {
/*Z1Encrypt.readClass("F:\\WorkSpace\\classLoader\\DemoTemp.class");
Z1Encrypt.encrypt();
*/
MyClassLoader mcl = new MyClassLoader("F:\\WorkSpace\\classLoader\\");
Class clazz = mcl.findClass("DemoTemp");
Method me = clazz.getMethod("say",null);
Object obj = clazz.newInstance();
me.invoke(obj, null);
}
その後成功したバイトコードファイルを復号化してメモリにロードし、呼関連法の成功。
上記の非常に簡単なコードの暗号化で、アイデアや知識での研究のためのカスタムクラスローダの方法。