根据问题的复杂性,这可能适用也可能不适用。
在没有反射的上下文中,标准 java 代码很难复制调用者敏感性,更难将其“模拟”为调用者敏感函数。即使完成了,在我看来,代码也会非常晦涩难懂,或者会处理我认为不必要的深层黑暗语言功能。
您在这里遇到的基本问题是呼叫者敏感,并且您正在尝试通过在呼叫自己之前执行一堆其他任务System.load()
来构建自己的“增强” 。为什么不完全离开你开始时的位置?System.load()
System.load()
System.load()
与其尝试替换 的功能,不如用你的类来System.load()
补充它。JniUtils
编写一个JniUtils.fetchLibrary()
返回一个字符串,原始调用者可以从中加载。更好的是,返回一个自定义对象Library
(或其他等效名称),其中包含一个方法,该方法允许检索应传递给的字符串System.load()
。由此,调用load()
可以来自需要点,而您的调用者不敏感代码可以单独进行所有初始化。
这个例子的东西会很好:
public class JniUtils {
private static final HashMap<String, JniLibrary> cachedLibs = new HashMap<>();
public static JniLibrary fetchLibrary(String libname){
// Check cache for library
if(cachedLibs.containsKey(libname)){
return cachedLibs.get(libname);
}else{
JniLibrary lib = preloadLibrary(libname);
if(lib != null){
cachedLibs.put(libname, lib);
}
return lib;
}
}
/**
* Internal logic to prepare and generate a library instance
*
* @return JNI library on success, null on failure.
*/
private static JniLibrary preloadLibrary(String libname){
// Find lib
// Extract
// Get path
// Construct JniLibrary instance
// Return library as appropriate
}
/**
* Class representing a loadable JniLibrary
*/
public class JniLibrary{
public String getLibraryPath();
// Other potentially useful methods
}
}
public class NeedsJni {
static {
JniLibrary lib = JniUtils.fetchLibrary("nameoflibrary");
if(lib != null){
System.load(lib.getLibraryPath()); // Caller-sensitivity respected
}else{
// Well.... this is awkward.
}
}
}
这不仅解决了调用者敏感性问题,额外的缓存可以防止额外的提取/架构查找和最终失败(因为您提取到的文件可能已经在使用中),允许System.load()
从不同类加载器下的不同类进行多次调用(视情况而定) .
这种方法的反例是,如果System.load()
在您的自定义loadLibrary()
方法中必须立即执行重要的代码(突然间,您希望 java 会有某种“OnLibraryLoad”事件)。在这种情况下,也许添加一个方法来在你的主类或返回的库类中运行加载后代码JniUtils
(我知道这更难看,但有了清晰的文档,它不会那么糟糕)。