使用带有java反射的libpath

使用带有java反射的libpath,java,reflection,java-native-interface,Java,Reflection,Java Native Interface,我动态加载一个类并对其调用一个方法。这个类不支持JNI。当我调用该类时,java尝试加载库。这会导致错误,因为库不在libpath上。我从一个jar调用,所以我不能轻易地更改libpath(特别是因为库不在jar的同一目录或子目录中)。我确实知道库的路径,但是如何在加载类之前加载它呢 当前代码: public Class<?> loadClass(String name) throws ClassNotFoundException { if(!CLASS_NAME.equal

我动态加载一个类并对其调用一个方法。这个类不支持JNI。当我调用该类时,java尝试加载库。这会导致错误,因为库不在libpath上。我从一个jar调用,所以我不能轻易地更改libpath(特别是因为库不在jar的同一目录或子目录中)。我确实知道库的路径,但是如何在加载类之前加载它呢

当前代码:

public Class<?> loadClass(String name) throws ClassNotFoundException {
    if(!CLASS_NAME.equals(name))
            return super.loadClass(name);

    try {
        URL myUrl = new URL(classFileUrl);
        URLConnection connection = myUrl.openConnection();
        InputStream input = connection.getInputStream();
        byte[] classData = readConnectionToArray(input);

        return defineClass(CLASS_NAME,
                classData, 0, classData.length);

    } catch (MalformedURLException e) {
        throw new UndeclaredThrowableException(e);
    } catch (IOException e) {
        throw new UndeclaredThrowableException(e); 
    }
}
公共类loadClass(字符串名称)引发ClassNotFoundException{
如果(!CLASS_NAME.equals(NAME))
返回super.loadClass(名称);
试一试{
URL myUrl=新URL(classFileUrl);
URLConnection=myUrl.openConnection();
InputStream输入=连接。getInputStream();
字节[]classData=ReadConnectionArray(输入);
返回定义类(类名称,
classData,0,classData.length);
}捕获(格式错误){
抛出新的未声明的hrowableexception(e);
}捕获(IOE异常){
抛出新的未声明的hrowableexception(e);
}
}
例外情况:

Can't find library libvcommon.so java.lang.UnsatisfiedLinkError: vcommon (A file or directory in the path name does not exist.) at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:998) at java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:962) at java.lang.System.loadLibrary(System.java:465) at vcommon.(vcommon.java:103) at java.lang.J9VMInternals.initializeImpl(Native Method) at java.lang.J9VMInternals.initialize(J9VMInternals.java:200) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37) at java.lang.reflect.Method.invoke(Method.java:599) at com.fortune500.fin.v.vunit.reflection.ReflectionvProcessor.calculateV(ReflectionvProcessor.java:36) at com.fortune500.fin.v.vunit.UTLTestCase.execute(UTLTestCase.java:42) at com.fortune500.fin.v.vunit.TestSuite.execute(TestSuite.java:15) at com.fortune500.fin.v.vunit.batch.Testvendor.execute(Testvendor.java:101) at com.fortune500.fin.v.vunit.batch.Testvendor.main(Testvendor.java:58) 找不到库libvcommon.so java.lang.UnsatisfiedLinkError:vcommon(路径名中的文件或目录不存在。) 位于java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:998) 位于java.lang.ClassLoader.loadLibraryWithClassLoader(ClassLoader.java:962) 位于java.lang.System.loadLibrary(System.java:465) 在vcommon(vcommon.java:103) 位于java.lang.J9VMInternals.initializeImpl(本机方法) 在java.lang.J9VMInternals.initialize(J9VMInternals.java:200)中 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处 位于sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)中 位于java.lang.reflect.Method.invoke(Method.java:599) 在com.fortune500.fin.v.vunit.reflection.ReflectionvProcessor.calculateV上(ReflectionvProcessor.java:36) 在com.fortune500.fin.v.vunit.UTLTestCase.execute(UTLTestCase.java:42) 在com.fortune500.fin.v.vunit.TestSuite.execute(TestSuite.java:15) 在com.fortune500.fin.v.vunit.batch.Testvendor.execute上(Testvendor.java:101) 位于com.fortune500.fin.v.vunit.batch.Testvendor.main(Testvendor.java:58) 编辑:我现在有一个64位对32位的问题。等我搞定了,我会再谈这个的。 相关的:


如果知道库的路径,可以将该路径添加到自定义类加载器中的
java.library.path
环境变量中。一种更简单的方法是计算路径并在调用
Runtime.loadLibrary
时使用它

下面的代码概述了两种方法,使用loadLibrary和设置java.library.path系统属性

 if(CLASS_NAME.equals(name)) {

    // two ways of doing this - either load the library explicitly from the full path  
    if (useFullPath) {
      Runtime.getRuntime().loadLibrary("/full/path/to/mylibrary");
    }
    else { // or tweaking the library path
      System.setProperty("java.library.path", 
         System.getProperty("java.library.path")
         + System.getProperty("file.separator")
         + "/path/to/lib");
    }
 }
 return super.loadClass(name);
您提到您的代码是从jar调用的——如果类加载器也是jar的一部分,那么使用自定义类加载器将很困难。您是否已验证您的类加载器确实正在使用

一种更简单的方法是将本机类中对loadLibrary的当前调用更改为使用完整路径。例如,如果您事先知道在哪里可以找到系统属性,请从系统属性中获取或计算它。当然,如果您拥有本机类的源,那么这只是一个选项。如果无法修改本机类,则使用类加载器中的loadLibrary调用

我的理解是,调用load library以相同的库名称(无论路径如何)加载相同的库。(至少,这是Windows上的行为-我还没有在Linux上验证过。)因此,即使classloader使用完整路径加载库,而本机类使用它的简单名称加载库,两者都应该解析为同一个库


(为了完整起见,从Win32的经验来看,解析等效库同样发生在内核中。每个库在内部都有一个名称,windows在每个进程中只加载一个具有相同内部名称的库实例。)

我尝试了loadLibrary(fullPath)方法,但这会引发一个“未找到文件”异常。请确保您不使用文件扩展名。恐怕我以前忘了提到它,我们开发人员必须记住的大量其他picodetails中一定丢失了。:-)有帮助吗?@mdma这两种方法现在都不适用于我。我还发现我的lib路径已经包含了相应的目录<代码>运行时。加载失败,路径为完整路径,或者路径为完整路径减去扩展名。
UnsatifiedLinkError
始终是“(路径名中的文件或目录不存在)。“我已经检查了完整路径,即使是在调用
load
之前从程序中检查过,并且文件确实存在。@mdma,刚刚找到了它。该库是32位的,因此需要重新编译。这是一个可怕的错误信息。非常感谢IBM(这是一个IBM Aix JVM)。