編寫測試Jar包
1.類結構
2.類代碼
Parent.class
package com.wind.test;
abstract class Parent {
public String name() {
return "Piter";
}
}
Jim.class
package com.wind.test;
class Jim extends Parent {
public String name() {
return "My father is " + super.name() + " and my name is Jim";
}
}
Tom.class
package com.wind.test;
class Tom extends Parent{
public String name() {
return "My father is " + super.name() + " and my name is Tom";
}
}
Test.class
package com.wind.test;
public class Test {
public void print() {
Jim son1 = new Jim();
System.out.println(son1.name());
Tom son2 = new Tom();
System.out.println(son2.name());
}
}
Main.class
package com.wind.main;
import com.wind.test.Test;
public class Main {
public static void main(String[] args) {
new Test().print();
}
}
3.運行結果
4.打包
打包過程在上一篇文章有,這裏就不贅述了。
Jar包的加密類
package com.wind.load.enjar;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import com.wind.load.Base64;
public class JarEncoder {
private JarInputStream jis;
public JarEncoder(String src) throws FileNotFoundException, IOException {
this(new FileInputStream(src));
}
public JarEncoder(File file) throws FileNotFoundException, IOException {
this(new FileInputStream(file));
}
public JarEncoder(InputStream is) throws IOException {
jis = new JarInputStream(is);
}
/**
* 通過指定的路徑輸出加密後的jar
* @param target
* @throws FileNotFoundException
* @throws IOException
*/
public void write(String target) throws FileNotFoundException, IOException {
write(new FileOutputStream(target));
}
/**
* 通過指定的文件輸出加密後的jar
* @param file
* @throws FileNotFoundException
* @throws IOException
*/
public void write(File file) throws FileNotFoundException, IOException {
write(new FileOutputStream(file));
}
/**
* 通過指定的輸出流輸出加密後的jar
* @param os
* @throws FileNotFoundException
* @throws IOException
*/
public void write(OutputStream os) throws FileNotFoundException, IOException {
Manifest menifest = jis.getManifest(); //獲取jar的Manifest信息
JarOutputStream jos = null;
if(menifest == null) {
jos = new JarOutputStream(os);
} else {
//JarInputStream的getNextJarEntry()方法無法獲取Manifest信息,所以只能通過這種方式寫入Manifest信息
jos = new JarOutputStream(os, menifest);
}
JarEntry entry = null;
while((entry = jis.getNextJarEntry()) != null) {
jos.putNextEntry(entry);
if(entry.getName().endsWith(".class")) { //只加密class文件
byte[] bytes = getBytes(jis); //讀取class文件內容
byte[] enbytes = Base64.encode(bytes); //加密後的信息
jos.write(enbytes, 0, enbytes.length); //把加密後的信息寫入流
} else { //其他類型的文件直接寫入流
byte[] bytes = getBytes(jis);
jos.write(bytes, 0, bytes.length);
}
jos.flush();
}
jos.close();
jis.close();
}
/**
* 從jar輸入流中讀取信息
* @param jis
* @return
* @throws IOException
*/
private byte[] getBytes(JarInputStream jis) throws IOException {
int len = 0;
byte[] bytes = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
while((len = jis.read(bytes, 0, bytes.length)) != -1) {
baos.write(bytes, 0, len);
}
return baos.toByteArray();
}
}
Jar包的解密類
package com.wind.load.dejar;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import com.wind.load.Base64;
public class JarDecoder extends ClassLoader {
private JarInputStream jis;
private Map<String, ByteBuffer> entryMap;
public JarDecoder(String src) throws FileNotFoundException, IOException {
this(new FileInputStream(src));
}
public JarDecoder(File file) throws FileNotFoundException, IOException {
this(new FileInputStream(file));
}
public JarDecoder(InputStream is) throws IOException {
jis = new JarInputStream(is);
entryMap = new HashMap<String, ByteBuffer>();
JarEntry entry = null;
while((entry = jis.getNextJarEntry()) != null) {
String name = entry.getName();
if(name.endsWith(".class")) { //class文件解密後再緩存
byte[] bytes = getBytes(jis); //讀取class文件內容
byte[] debytes = Base64.decode(bytes); //解密class文件內容
ByteBuffer buffer = ByteBuffer.wrap(debytes); //把數據複製到ByteBuffer對象中
entryMap.put(name, buffer); //緩存數據
} else { //其他文件直接緩存
byte[] bytes = getBytes(jis);
ByteBuffer buffer = ByteBuffer.wrap(bytes);
entryMap.put(name, buffer);
}
}
jis.close();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String path = name.replace('.', '/').concat(".class");
ByteBuffer buffer = entryMap.get(path);
if(buffer == null) {
return super.findClass(name);
} else {
byte[] bytes = buffer.array();
return defineClass(name, bytes, 0, bytes.length);
}
}
/**
* 從jar輸入流中讀取信息
* @param jis
* @return
* @throws IOException
*/
private byte[] getBytes(JarInputStream jis) throws IOException {
int len = 0;
byte[] bytes = new byte[8192];
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048);
while((len = jis.read(bytes, 0, bytes.length)) != -1) {
baos.write(bytes, 0, len);
}
return baos.toByteArray();
}
/**
* 關閉Decoder
* @throws IOException
*/
public void close() throws IOException {
Iterator<ByteBuffer> iterator = entryMap.values().iterator();
while(iterator.hasNext()) {
ByteBuffer buffer = iterator.next();
buffer.clear(); //清空ByteBuffer對象緩存
}
entryMap.clear(); //清空HashMap
}
}
測試類
package com.wind.load;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.wind.load.dejar.JarDecoder;
import com.wind.load.enjar.JarEncoder;
public class Main {
public static void main(String[] args) {
encode();
decode();
}
private static void encode() {
try {
JarEncoder encoder = new JarEncoder("E:/test.jar");
encoder.write("E:/test_encode.jar");
System.out.println("encode success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void decode() {
try {
JarDecoder decoder = new JarDecoder("E:/test_encode.jar");
Class<?> cls = decoder.loadClass("com.wind.test.Test");
Method method = cls.getMethod("print", null);
method.invoke(cls.newInstance(), null);
decoder.close();
System.out.println("decode success");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}