我們先寫一個URLClassLoader的子類,這樣我們就可以用定義在其中的一些protected方法了.
/*
* Test6.java
*
* Created on 2007-9-24, 10:57:57
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test1;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author hadeslee
*/
@SuppressWarnings(value = "unchecked")
public class Test6 extends URLClassLoader {
public Test6() {
super(new URL[0]);
Thread.currentThread().setContextClassLoader(this);
ClassLoader cl = this.getClass().getClassLoader();
if (cl instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) cl;
URL[] urls = loader.getURLs();
for (URL u : urls) {
System.out.println(u);
this.addURL(u);
}
}
}
//根據類的全限定名得到類的字節數組
private byte[] getClassData(String name) {
try {
InputStream is = this.getClass().getResourceAsStream(getPathName(name));
byte[] temp = new byte[is.available()];
is.read(temp);
is.close();
return temp;
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
//要隱藏的類
private void hideClasses(String
className) {
DataOutputStream dout = null;
try {
dout = new DataOutputStream(new FileOutputStream("hide.dat"));
for (String s : className) {
dout.writeUTF(s);
byte[] data = this.getClassData(s);
dout.writeInt(data.length);
dout.write(data);
}
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
dout.close();
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private Class findClass0(String className){
DataInputStream din = null;
try {
din = new DataInputStream(new FileInputStream("hide.dat"));
while (true) {
String name = din.readUTF();
System.out.println("find name=" + name);
int length = din.readInt();
byte[] data = new byte[length];
din.read(data);
if (name.equals(className)) {
return this.defineClass(name, data, 0, length);
}
}
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassFormatError classFormatError) {
} finally {
try {
if (din != null) {
din.close();
}
} catch (Exception exe) {
exe.printStackTrace();
}
}
return null;
}
protected Class findClass(String className) throws ClassNotFoundException {
Class c=this.findClass0(className);
if(c==null){
return super.findClass(className);
}else{
return c;
}
}
//根據類名得到完整的加載路徑名
private String getPathName(String name) {
StringBuilder sb = new StringBuilder();
String[] names = name.split("\\.");
for (String s : names) {
sb.append("/").append(s);
}
sb.append(".class");
return sb.toString();
}
public static void main(String[] args) throws Exception {
Test6 t = new Test6();
t.hideClasses("test2.A", "test2.B");
Class c = t.findClass("test2.B");
Object o = c.newInstance();
test2.B b=(test2.B)o;
Method m = c.getDeclaredMethod("print", String.class);
m.invoke(o, "我是中國人");
System.out.println(c);
}
}
* Test6.java
*
* Created on 2007-9-24, 10:57:57
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test1;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author hadeslee
*/
@SuppressWarnings(value = "unchecked")
public class Test6 extends URLClassLoader {
public Test6() {
super(new URL[0]);
Thread.currentThread().setContextClassLoader(this);
ClassLoader cl = this.getClass().getClassLoader();
if (cl instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) cl;
URL[] urls = loader.getURLs();
for (URL u : urls) {
System.out.println(u);
this.addURL(u);
}
}
}
//根據類的全限定名得到類的字節數組
private byte[] getClassData(String name) {
try {
InputStream is = this.getClass().getResourceAsStream(getPathName(name));
byte[] temp = new byte[is.available()];
is.read(temp);
is.close();
return temp;
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
//要隱藏的類
private void hideClasses(String

DataOutputStream dout = null;
try {
dout = new DataOutputStream(new FileOutputStream("hide.dat"));
for (String s : className) {
dout.writeUTF(s);
byte[] data = this.getClassData(s);
dout.writeInt(data.length);
dout.write(data);
}
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
dout.close();
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private Class findClass0(String className){
DataInputStream din = null;
try {
din = new DataInputStream(new FileInputStream("hide.dat"));
while (true) {
String name = din.readUTF();
System.out.println("find name=" + name);
int length = din.readInt();
byte[] data = new byte[length];
din.read(data);
if (name.equals(className)) {
return this.defineClass(name, data, 0, length);
}
}
} catch (IOException ex) {
Logger.getLogger(Test6.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassFormatError classFormatError) {
} finally {
try {
if (din != null) {
din.close();
}
} catch (Exception exe) {
exe.printStackTrace();
}
}
return null;
}
protected Class findClass(String className) throws ClassNotFoundException {
Class c=this.findClass0(className);
if(c==null){
return super.findClass(className);
}else{
return c;
}
}
//根據類名得到完整的加載路徑名
private String getPathName(String name) {
StringBuilder sb = new StringBuilder();
String[] names = name.split("\\.");
for (String s : names) {
sb.append("/").append(s);
}
sb.append(".class");
return sb.toString();
}
public static void main(String[] args) throws Exception {
Test6 t = new Test6();
t.hideClasses("test2.A", "test2.B");
Class c = t.findClass("test2.B");
Object o = c.newInstance();
test2.B b=(test2.B)o;
Method m = c.getDeclaredMethod("print", String.class);
m.invoke(o, "我是中國人");
System.out.println(c);
}
}
以下是A和B類的代碼
/*
* A.java
*
* Created on 2007-9-24, 10:26:47
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test2;
/**
*
* @author hadeslee
*/
public class A {
private int index=10;
public void doSth(){
}
}
* A.java
*
* Created on 2007-9-24, 10:26:47
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test2;
/**
*
* @author hadeslee
*/
public class A {
private int index=10;
public void doSth(){
}
}
/*
* B.java
*
* Created on 2007-9-24, 10:29:04
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test2;
/**
*
* @author hadeslee
*/
public class B extends A{
public void print(String s){
System.out.println(s);
}
}
* B.java
*
* Created on 2007-9-24, 10:29:04
*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package test2;
/**
*
* @author hadeslee
*/
public class B extends A{
public void print(String s){
System.out.println(s);
}
}
此程序的實現思路是:先寫一個繼承自URLClassLoader的類加載器,然后我們要類的時候,就從這個類加載器去加載,我們要隱藏類的時候,也是由這個類加載器去實現隱藏, 其實隱藏就是把很多類放到一個文件里面去,然后加上自己的IO寫法,然后在需要的時候,又可以又自己寫進去的方法,把類的字節數組讀出來,把它還原成一個類.在這里我們還需要重寫一個方法,那就是定義在ClassLoader里面的findClass(String name)的方法,讓它在找類的時候,不要亂找,而是用我們自己的方法來找,當我們自己的方法找不到的時候,才由它來找,這樣的話,就可以實現先找我們自己的方式隱藏的類,再找一般情況下面的類.
對于類的加載,有很多東西是可以研究和學習的,希望在以后的學習過程中,能夠慢慢了解它.
盡管千里冰封
依然擁有晴空
你我共同品味JAVA的濃香.