1、自定义Classloader的代码如下:
package com.test.start;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.Manifest;
import sun.misc.Resource;
import sun.misc.URLClassPath;
public class CommonClassLoader extends URLClassLoader
{
private URLClassPath ucp;
private AccessControlContext acc;
private Method getProtectionDomainMethod;
public CommonClassLoader(URL[] urls)
{
super(urls);
}
public CommonClassLoader(URL[] urls, ClassLoader parent) {
super(urls);
}
protected void addURL(URL arg0)
{
super.addURL(arg0);
}
//系统方法
protected Class> findClass(String name)
throws ClassNotFoundException
{
try
{
check();
return
((Class)AccessController.doPrivileged(new PrivilegedExceptionAction(this, name) {
public Object run() throws ClassNotFoundException {
String path = this.val$name.replace('.', '/').concat(".class");
Resource res = CommonClassLoader.access$0(this.this$0).getResource(path, false);
if (res != null)
try {
return CommonClassLoader.access$1(this.this$0, this.val$name, res);
} catch (IOException e) {
throw new ClassNotFoundException(this.val$name, e);
}
throw new ClassNotFoundException(this.val$name);
}
}
, this.acc));
} catch (PrivilegedActionException pae) {
throw ((ClassNotFoundException)pae.getException());
}
}
//修改后的系统方法
private Class defineClass(String name, Resource res)
throws IOException
{
int i = name.lastIndexOf(46);
URL url = res.getCodeSourceURL();
if (i != -1) {
String pkgname = name.substring(0, i);
Package pkg = getPackage(pkgname);
Manifest man = res.getManifest();
if (pkg != null)
{
if (pkg.isSealed())
{
if (pkg.isSealed(url)) break label172;
throw new SecurityException(
"sealing violation: package " + pkgname + " is sealed");
}
if ((man == null) || (!(isSealed(pkgname, man)))) break label172;
throw new SecurityException(
"sealing violation: can't seal package " + pkgname +
": already loaded");
}
if (man != null)
definePackage(pkgname, man, url);
else {
definePackage(pkgname, null, null, null, null, null, null, null);
}
}
label172: ByteBuffer bb = res.getByteBuffer();
if (bb != null)
{
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
byte[] b = getBytes(bb);
return defineClassInternal(name, b, 0, b.length, cs);
}
byte[] b = res.getBytes();
CodeSigner[] signers = res.getCodeSigners();
CodeSource cs = new CodeSource(url, signers);
return defineClassInternal(name, b, 0, b.length, cs);
}
//系统方法
private boolean isSealed(String name, Manifest man)
{
String path = name.replace('.', '/').concat("/");
Attributes attr = man.getAttributes(path);
String sealed = null;
if (attr != null)
sealed = attr.getValue(Attributes.Name.SEALED);
if (sealed == null)
if ((attr = man.getMainAttributes()) != null)
sealed = attr.getValue(Attributes.Name.SEALED);
return "true".equalsIgnoreCase(sealed);
}
//自定义方法 检测父类的属性初始化给子类调用,使用java反射技术实现。
private void check()
{
try {
if (this.ucp == null)
{
Field fieldOfucp = getClass().getSuperclass().getDeclaredField("ucp");//获取private类型的字段
fieldOfucp.setAccessible(true);//设置private类型修饰的字段可以访问
this.ucp = ((URLClassPath)fieldOfucp.get(this));//访问private类型修饰的字段
}
if (this.acc == null)
{
Field fieldOfacc = getClass().getSuperclass().getDeclaredField("acc");
fieldOfacc.setAccessible(true);
this.acc = ((AccessControlContext)fieldOfacc.get(this));
}
if (this.getProtectionDomainMethod != null) return;
this.getProtectionDomainMethod = getClass().getSuperclass().getSuperclass().getDeclaredMethod("getProtectionDomain", new Class[] { CodeSource.class });
this.getProtectionDomainMethod.setAccessible(true);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
//自定义方法 字节缓冲中的字节获取
private byte[] getBytes(ByteBuffer b)
{
int len = b.remaining();
byte[] tb = new byte[len];
if (!(b.isDirect()))
if (b.hasArray()) {
System.arraycopy(b.array(), b.position() + b.arrayOffset(), tb, 0, len);
}
else
b.get(tb);
return tb;
}
//自定义方法 让加密的的class文件交给解密方法来执行装载否则由系统来装载
protected final Class> defineClassInternal(String name, byte[] b, int off, int len, CodeSource cs)
{
Class clz = null;
try
{
if (cs == null) {
clz = defineClass0(name, b, off, len); break label75:
}
clz = defineClass1(name, b, off, len, getProtectionDomainInternal(cs));
}
catch (ClassFormatError ex)
{
if (cs == null)
return super.defineClass(name, b, off, len);
return super.defineClass(name, b, off, len, getProtectionDomainInternal(cs));
}
if (clz == null)
{
if (cs == null)
label75: return super.defineClass(name, b, off, len);
return super.defineClass(name, b, off, len, getProtectionDomainInternal(cs));
}
return clz;
}
//系统方法
protected ProtectionDomain getProtectionDomainInternal(CodeSource cs)
{
try {
return ((ProtectionDomain)this.getProtectionDomainMethod.invoke(this, new Object[] { cs }));
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
//自定义方法 调用dll文件中的解密算法来解密class文件并装载到jvm中
private native Class> defineClass0(String paramString, byte[] paramArrayOfByte, int paramInt1, int paramInt2);
private native Class> defineClass1(String paramString, byte[] paramArrayOfByte, int paramInt1, int paramInt2, ProtectionDomain paramProtectionDomain);
}
2、c++实现加密和解密算法以及JNI技术的应用实例:
#include"jni.h"
#include"com_test_start_CommonClassLoader.h"
static void arraycopy(JNIEnv *env,jbyteArray sb,int spo,jbyteArray db,int start,int len);
static jbyteArray encrypt(JNIEnv *env,jbyteArray b,jint len);
static jbyteArray getValidateCode(JNIEnv *env);
static jbyteArray getCode(JNIEnv *env);
/*
* Clasbs: com_test_start_CommonClassLoader
* Method: defineClass0
* Signature: (Ljava/lang/String;[BII)Ljava/lang/Class;
*/
JNIEXPORT jclass JNICALL Java_com_test_start_CommonClassLoader_defineClass0
(JNIEnv *env, jobject loader, jstring name, jbyteArray buffer, jint start, jint len)
{
jbyteArray temp=env->NewByteArray(len);//new一个数组,并申请一块内存
arraycopy(env,buffer,start,temp,start,len);//数组的复制相当于System.copy()方法
jbyteArray byte0=encrypt(env,temp,len);//进行class文件的解密操作
if(byte0==NULL)
{
env->DeleteLocalRef(temp);//释放内存
return NULL;
}
jsize size=env->GetArrayLength(byte0);//技术数组的长度相当于Array的length属性
jclass classLoader=env->GetSuperclass(env->GetSuperclass(env->GetSuperclass(env->GetObjectClass(loader))));//获取父类装载器
jmethodID mid=env->GetMethodID(classLoader,"defineClass","(Ljava/lang/String;[BII)Ljava/lang/Class;");//获取defineClass方法
defineClass jclass cls=(jclass)env->CallObjectMethod(loader,mid,name,byte0,start,size);//调用Classloader的defineClass定义一个类到jvm中
env->DeleteLocalRef(byte0);//释放内存
return cls;
}
/*
* Class: com_test_start_CommonClassLoader
* Method: defineClass1
* Signature: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
*/
JNIEXPORT jclass JNICALL Java_com_test_start_CommonClassLoader_defineClass1
(JNIEnv *env, jobject loader, jstring name, jbyteArray buffer, jint start, jint len, jobject pro)
{
jbyteArray temp=env->NewByteArray(len);
arraycopy(env,buffer,start,temp,start,len);
jbyteArray byte0=encrypt(env,temp,len);
if(byte0==NULL)
{
env->DeleteLocalRef(temp);
return NULL;
}
jsize size=env->GetArrayLength(byte0);
jclass classLoader=env->GetSuperclass(env->GetSuperclass(env->GetSuperclass(env->GetObjectClass(loader))));
jmethodID mid=env->GetMethodID(classLoader,"defineClass","(Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;");
jclass cls=(jclass)env->CallObjectMethod(loader,mid,name,byte0,start,size,pro);
env->DeleteLocalRef(byte0);
return cls;
}
/*
getCode,密钥,用于加密
*/
static jbyteArray getCode(JNIEnv *env)
{
char char0[]={'0','1','2','3','4','5','6','7','8','9'};
char char1[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','s','y','z'};
char char2[36];
int i=0;
int j=0;
int k=0;
while(i<36)
{
if(i>=12&&j<10)
{
char2[i]=char0[j];
j++;
}
else if(i>=23&&k<26)
{
char2[i]=char1[k];
k++;
}
else
{
char2[i]=char1[k];
k++;
}
i++;
}
jbyteArray code=env->NewByteArray(36);
env->SetByteArrayRegion(code,0,36,(jbyte*)char2);
return code;
}
/*
getValidateCode,验证码用于区分是否是加密文件
*/
static jbyteArray getValidateCode(JNIEnv *env)
{
char char0[]={'0','1','2','3','4','5','6','7'};
jbyteArray char1=env->NewByteArray(8);
env->SetByteArrayRegion(char1,0,8,(jbyte *)char0);
return char1;
}
/*
encrypt,解密操作
*/
static jbyteArray encrypt(JNIEnv *env,jbyteArray b,jint len)
{
int i = 0;
jint j = 0;
int k =len;
jbyte* bb = (env->GetByteArrayElements(b,JNI_FALSE));
while (i < k) {
j = bb[i];
if ((j >= 48) && (j <= 57)) {
j = (((j - 48) + 5) % 10) + 48;
} else if ((j >= 65) && (j <= 90)) {
j = (((j - 65) + 13) % 26) + 65;
} else if ((j >= 97) && (j <= 122)) {
j = (((j - 97) + 13) % 26) + 97;
}
bb[i]=(jbyte)j;
i++;
}
env->SetByteArrayRegion(b,0,k,bb);
int length=500;//长度
int start=0;//起始次数
jbyteArray temp=getCode(env);//密钥
int mode=(k-8)%(length+36);//剩余部分
int count=(k-8)/(length+36);//总次数
int spo=0;//源位置
int dpo=0;//目标位置
int size=count*length+mode;//大小
jbyteArray byte0=env->NewByteArray(size);//密文大小
if(count>0)
{//进行解密
while(start {
arraycopy(env,b, spo, byte0, dpo, length);
spo=spo+length+36;
dpo=dpo+length;
start++;
}
}
if(mode>0)
{//复制剩余部分
arraycopy(env,b, spo, byte0, dpo, mode);
spo=spo+mode;
}
//校验码
jbyteArray validateCode0=getValidateCode(env);
jbyte* validateCode=env->GetByteArrayElements(validateCode0,JNI_FALSE);
jbyteArray validate0=env->NewByteArray(8);
arraycopy(env,b, spo, validate0, 0,8);
jbyte* validate=env->GetByteArrayElements(validate0,JNI_FALSE);
for(int index=0;index<8;index++)
{//校验解码是否成功
if(validate[index]!=validateCode[index])
{
return NULL;
}
}
env->DeleteLocalRef(validate0);
env->DeleteLocalRef(validateCode0);
env->DeleteLocalRef(temp);
return byte0;
}
/*
decrypt,加密操作
*/
static jbyteArray decrypt(JNIEnv *env,jbyteArray b,jboolean end)
{
int length=500;//长度
int start=0;//起始次数
int count=env->GetArrayLength(b)/length;//总次数
jbyteArray temp=getCode(env);//密钥
int spo=0;//源位置
int dpo=0;//目标位置
int mode=env->GetArrayLength(b)%length;//剩余部分
int size=count*(length+36)+mode;//大小
if(end==JNI_TRUE)
{//是否结束
size=size+8;
}
jbyteArray byte0=env->NewByteArray(size);//密文大小
if(count>0)
{//进行加密
while(start {
arraycopy(env,b, spo, byte0, dpo, length);
arraycopy(env,temp, 0, byte0, dpo+length, 36);
spo=spo+length;
dpo=dpo+length+36;
start++;
}
}
if(mode>0)
{//复制剩余部分
arraycopy(env,b, spo, byte0, dpo, mode);
dpo=dpo+mode;
}
if(end==JNI_TRUE)
{//结束位置加校验码
jbyteArray validateCode=getValidateCode(env);
arraycopy(env,validateCode, 0, byte0, dpo, 8);
env->DeleteLocalRef(validateCode);
}
jbyte * byte1=env->GetByteArrayElements(byte0,0);
//转换字节位置
int i = 0;
int j = 0;
int k = size;
while (i < k) {
j = byte1[i];
if ((j >= 48) && (j <= 57)) {
j = (((j - 48) + 5) % 10) + 48;
} else if ((j >= 65) && (j <= 90)) {
j = (((j - 65) + 13) % 26) + 65;
} else if ((j >= 97) && (j <= 122)) {
j = (((j - 97) + 13) % 26) + 97;
}
byte1[i]=(jbyte)j;
i++;
}
env->SetByteArrayRegion(byte0,0,size,byte1);
env->DeleteLocalRef(temp);
return byte0;
}
/*
arraycopy,自定义的数组赋值方法相当于System.copy()
*/
static void arraycopy(JNIEnv *env,jbyteArray sb,int spo,jbyteArray db,int start,int len)
{
jbyte * t=new jbyte[len];
env->GetByteArrayRegion(sb,spo,len,t);
env->SetByteArrayRegion(db,start,len,t);
delete t;
}