提供公共jar包给公司内业务使用的时候,一般也希望可以观察一下jar包各个版本的使用情况,如果业务方有使用了一些比较老的有漏洞的版本就可以提示升级。要做到这一点,可以在基础类中获取被加载的jar包然后解析出版本号,同时获取main函数以及对应的jar包,这样就掌握了使用情况
获取main函数所在类
抛出异常的时候,异常栈中有所有函数栈,这样就可以找到main函数所在的类。不过也需要注意,这个异常要在主线程抛出,不能在其他线程抛出。
/**
* 获取main函数所在的类.
* [copy from spring]
*/
private static Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
获取类所在的jar包
/**
* 加载类所在的jar包信息.
*/
public static JarFileInfo getJar(Class<?> klass) throws IOException {
CodeSource cs = klass.getProtectionDomain().getCodeSource();
String file = cs.getLocation().getFile();
return parseJar(file);
}
private static final Pattern JAR_FILE_PATTERN = Pattern.compile("([^/]+\\.jar)[!/]*$");
private static String getJarFileName(String fullPath) {
int lastIndex = fullPath.lastIndexOf(".jar");
Matcher matcher = JAR_FILE_PATTERN.matcher(fullPath.substring(0, lastIndex + 4));
if (matcher.find()) {
return matcher.group(1);
}
throw new IllegalArgumentException("this is not a jar file: " + fullPath);
}
解析版本号
/**
* 版本号正则表达式提取器.
*/
private static final Pattern VERSION_PATTERN = Pattern.compile("\\w+-(\\d.*)\\.jar");
/**
* 解析版本号.
*/
public static String parseJarVersion(String simpleJarName) {
Matcher matcher = VERSION_PATTERN.matcher(simpleJarName);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
最终版本
/**
* jar包信息.
*
* @author tenmao
*/
@Data
public class JarFileInfo {
private final String jarName;
private final String version;
/**
* main函数类所在的jar包信息.
*/
public static final JarFileInfo MAIN_CLASS_JAR;
static {
Class<?> klass = deduceMainApplicationClass();
if (klass == null) {
throw new RuntimeException("fail to deduce main class");
}
JarFileInfo fileInfo;
try {
fileInfo = getJar(klass);
} catch (IOException e) {
fileInfo = null;
}
MAIN_CLASS_JAR = fileInfo;
}
/**
* 获取main函数所在的类.
* [copy from spring]
*/
private static Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
} catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
/**
* 加载类所在的jar包信息.
*/
public static JarFileInfo getJar(Class<?> klass) throws IOException {
CodeSource cs = klass.getProtectionDomain().getCodeSource();
String file = cs.getLocation().getFile();
return parseJar(file);
}
public static JarFileInfo parseJar(String name) {
String jarFileName = getJarFileName(name);
String version = parseJarVersion(jarFileName);
return new JarFileInfo(jarFileName, version);
}
private static final Pattern JAR_FILE_PATTERN = Pattern.compile("([^/]+\\.jar)[!/]*$");
private static String getJarFileName(String fullPath) {
int lastIndex = fullPath.lastIndexOf(".jar");
Matcher matcher = JAR_FILE_PATTERN.matcher(fullPath.substring(0, lastIndex + 4));
if (matcher.find()) {
return matcher.group(1);
}
throw new IllegalArgumentException("this is not a jar file: " + fullPath);
}
/**
* 版本号正则表达式提取器.
*/
private static final Pattern VERSION_PATTERN = Pattern.compile("\\w+-(\\d.*)\\.jar");
/**
* 解析版本号.
*/
public static String parseJarVersion(String simpleJarName) {
Matcher matcher = VERSION_PATTERN.matcher(simpleJarName);
if (matcher.find()) {
return matcher.group(1);
}
return null;
}
}
网友评论