com.loocme.sys.classloader.AppClassLoader Maven / Gradle / Ivy
package com.loocme.sys.classloader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import com.loocme.sys.util.ClassModfier;
import com.loocme.sys.util.StringUtil;
import com.loocme.sys.util.SystemUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 自定义类加载器
*
* 继承自工程app ClassLoader。破坏了双亲委派模型,以便保存自定义class类,并实现动态加载/卸载
*
* @author loocmeinstallClass
*
*/
@Slf4j
public class AppClassLoader extends ClassLoader
{
private static AppClassLoader priThis = new AppClassLoader();
private static Map> priNameMap = new HashMap>();
private static AtomicLong count = new AtomicLong(0);
/**
* 获取本类加载器,单例模式
*
* @return 类加载器实例
*/
public static AppClassLoader getInstance()
{
return priThis;
}
private AppClassLoader()
{
super(AppClassLoader.class.getClassLoader());
}
/**
* 重写获取class方法:
*
* 根据类名获取clz:
* 若类加载器中存在该类的实例,则直接返回,
* 否则调用父类加载器的方法
*/
@Override
public Class> loadClass(String name) throws ClassNotFoundException
{
if (priNameMap.containsKey(name))
{
return priNameMap.get(name);
}
return super.loadClass(name);
}
/**
* 根据类名卸载class
*
* @param name 类名
* @return 该类的class
*/
public Class> uninstallClass(String name)
{
return this.uninstallClass(name, null, null);
}
public Class> uninstallClass(String name, String className)
{
return this.uninstallClass(name, className, null);
}
public Class> uninstallClass(String name, String className, InputStream is)
{
Class> clz = priNameMap.get(name);
if (StringUtil.isNull(className))
{
priNameMap.put(name, null);
}
else
{
Class> tempClz = priNameMap.get(className);
if (null != tempClz)
{
priNameMap.put(name, tempClz);
}
else
{
if (null == is)
{
priNameMap.put(name, null);
}
else
{
tempClz = this.installClass(className, is);
priNameMap.put(name, tempClz);
}
}
}
return clz;
}
/**
* 通过类名加载class
*
* @param name 类名
* @return 加载的class
*/
public Class> installClass(String name)
{
return this.installClass(name, null);
}
/**
* 通过io流,加载class,并与相应的类名对应
*
* @param name 类名
* @param is io流
* @return 加载的class
*/
public Class> installClass(String name, InputStream is)
{
boolean created = false;
try
{
String filePath = name.replaceAll("\\.", "/");
if (null == is)
{
is = new FileInputStream(new File(SystemUtil.getClassesPath()
+ filePath + ".class"));
created = true;
}
int len = is.available();
byte[] b = new byte[len];
is.read(b, 0, len);
ClassModfier cm = new ClassModfier(b);
b = cm.modifyUTF8Constant(filePath, this.reverseName());
Class> clz = super.defineClass(null, b, 0, b.length);
priNameMap.put(name, clz);
return clz;
}
catch (ClassFormatError e)
{
log.error("", e);
}
catch (IOException e)
{
log.error("", e);
}
finally
{
if (created && null != is)
{
try
{
is.close();
}
catch (IOException e)
{
log.error("", e);
}
}
}
return null;
}
/**
* 通过类名将class移除该类加载器,若再次调用,则调用父类加载器的类查找方法
*
* @param name 类名
* @return 移除的class
*/
public Class> removeClassFromThis(String name)
{
if (priNameMap.containsKey(name))
{
Class> clz = priNameMap.get(name);
priNameMap.remove(name);
return clz;
}
else
{
return null;
}
}
private String reverseName()
{
return "_com/loocme/object" + count.getAndIncrement();
}
}