如果jar太多
项目就会变得臃肿
很多功能其实并不常有
只是偶尔调用时才需要
此时需要了解jar的按需调用
使用JarInputStream调用
看代码
String url = "/home/mylib.jar";
String jarPath = "/home/runtime/test.jar";
JarInputStream jarInputStream = new JarInputStream(Files.newInputStream(Paths.get(url)));
Map<String, int[]> classByteMap = new HashMap<>();
byte[] buffer = new byte[1024 * 1024];
int head = 0;
int chunk = 256;
JarEntry jarEntry = jarInputStream.getNextJarEntry();
while (jarEntry != null) {
String name = jarEntry.getName();
if (name.endsWith(".class")) {
String className = name.replaceAll("/", ".").replaceAll(".class", "");
int size = 0, read;
while (true) {
read = jarInputStream.read(buffer, head + size, chunk);
if (read == -1) {
break;
}
size += read;
}
classByteMap.put(className, new int[]{head, size});
head += size;
}
jarEntry = jarInputStream.getNextJarEntry();
}
这就是一个基本的例子
有时无需管理整个jar
而需要class
则可以使用classLoader
SecureClassLoader classLoader = new SecureClassLoader() {
@Override
protected Class<?> findClass(String name) {
int[] arr = classByteMap.get(name);
return super.defineClass(name, buffer, arr[0], arr[1]);
}
};
Class<?> clazz = classLoader.loadClass("com.mi.Test");
Constructor<?> constructor = clazz.getConstructor();
Object demoEntry = constructor.newInstance();
Method entry = clazz.getDeclaredMethod("getId");
entry.invoke(demoEntry);
可以包装成工具类使用
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.cc.tx.util.LogUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
public interface DematicClassManager {
Logger log = LoggerFactory.getLogger(PluginClassManager.class);
static URL parseJarURL (File jar) throws IOException {
String jarFileUri = jar.toURI().toString() + "!/";
return new URL("jar", "", -1, jarFileUri);
}
static List<URL> parseLibJars (@NonNull String lib) throws IOException {
File libDir = new File(lib);
File[] jars = libDir.listFiles((dir, name) -> name.endsWith(".jar") || name.endsWith(".zip"));
List<URL> urls = Lists.newArrayList();
if (jars != null) {
for (int i = 0; i < jars.length; i++) {
if (jars[i] != null && jars[i].isFile()) {
urls.add(parseJarURL(jars[i]));
}
}
}
return urls;
}
@SneakyThrows
static void loadPluginLibJar (@NonNull String lib) throws IOException {
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
addURL.setAccessible(true);
parseLibJars(lib).forEach(e -> {
try {
addURL.invoke(classLoader, e);
LogUtils.info(log, "loadPluginLibJar addURL {}", e.getPath());
} catch (Exception e1) {
throw new RuntimeException(e1);
}
});
}
}
创建外部实现类
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@Slf4j
public class DematicClassLoader extends URLClassLoader {
private List<JarURLConnection> cachedResource = new CopyOnWriteArrayList<>();
public DematicClassLoader() {
super(new URL[] {}, ClassLoader.getSystemClassLoader());
}
public void loadLibJars (@NonNull String lib) throws IOException {
PluginClassManager.parseLibJars(lib).forEach(e -> loadResource(e));
}
public void loadResource (@NonNull URL resource) {
try {
JarFile jar = null;
log.info(resource.getPath());
URLConnection uc = resource.openConnection();
if (uc instanceof JarURLConnection) {
uc.setUseCaches(true);
((JarURLConnection) uc).getManifest();
cachedResource.add((JarURLConnection)uc);
jar = ((JarURLConnection) uc).getJarFile();
}
addURL(resource);
loadClassFromJar(jar);
} catch (Exception e) {
log.warn("Failed to cache plugin JAR file", resource.toExternalForm());
}
}
private void loadClassFromJar(JarFile jar) {
Enumeration<JarEntry> entries = jar.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
String entryName = jarEntry.getName();
if (entryName.charAt(0) == '/') {
entryName = entryName.substring(1);
}
if (jarEntry.isDirectory() || !entryName.endsWith(".class")) {
continue;
}
String className = entryName.substring(0, entryName.length() - 6);
try {
loadClass(className.replace("/", "."));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
public void unloadResource() {
for (JarURLConnection url : cachedResource) {
try {
url.getJarFile().close();
} catch (Exception e) {
log.warn("Failed to unload JAR file", e);
}
}
}
}
这样就可以实现了
学习技术可以关注我
关注我私信可以获取打包学习资料
让我们一起进步成长
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。