我将实现一个典型的本机库加载。目标进程:
核心问题是删除临时提取的本机库文件。DELETE_ON_EXIT方法不起作用。原因是,如果没有从JVM卸载库,文件就不能删除。但在ClassLoader被垃圾收集之前不会卸载。
我读到的一个提示是使用自定义的ClassLoader(http://www.codethesis.com/blog/unload-java-jni-dll)。我用自定义ClassLoader实现了一个简单的测试,但是它不会垃圾收集自定义ClassLaoder。下面是示例代码:
自定义类装载机
package minloader;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class NativeLibraryLoaderClassLoader extends ClassLoader
{
@Override
public Class<?> findClass(final String name) throws ClassNotFoundException
{
try
{
final byte[] classData = loadClassData(name);
final Class<?> clazz = defineClass(name, classData, 0, classData.length);
resolveClass(clazz);
return clazz;
}
catch (final IOException ex)
{
throw new ClassNotFoundException("Class [" + name+ "] could not be found", ex);
}
}
/**
* Loads the class file into <code>byte[]</code>.
* @param name The name of the class e.g. de.sitec.nativelibraryloadert.LoadEngine}
* @return The class file as <code>byte[]</code>
* @throws IOException If the reading of the class file has failed
* @since 1.0
*/
private static byte[] loadClassData(String name) throws IOException
{
try(final BufferedInputStream in = new BufferedInputStream(
ClassLoader.getSystemResourceAsStream(name.replace(".", "/")
+ ".class"));
final ByteArrayOutputStream bos = new ByteArrayOutputStream())
{
int i;
while ((i = in.read()) != -1)
{
bos.write(i);
}
return bos.toByteArray();
}
}
@Override
public String toString()
{
return NativeLibraryLoaderClassLoader.class.getName();
}
@Override
public void finalize() {
System.out.println("A garbage collected - LOADER");
}
}
本机接口
package minloader;
/**
*
* @author RD3
*/
public interface Native
{
public boolean initializeAPI();
}
原生Impl
package minloader;
public class NativeImpl implements Native
{
/**
* Initializes the NativeImpl API
*
* @return a boolean to indicate if API is successfully loaded
*/
@Override
public boolean initializeAPI(){return true;}
@Override
public void finalize() {
System.out.println("A garbage collected - Native");
}
主
package minloader;
/**
*
* @author RD3
*/
public class MinLoader
{
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
NativeLibraryLoaderClassLoader nl = null;
Class pc = null;
Native pcan = null;
try
{
nl = new NativeLibraryLoaderClassLoader();
pc = nl.findClass("minloader.NativeImpl");
pcan = (Native)pc.newInstance();
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
System.out.println("CLEAN UP");
if(pcan != null)
{
pcan = null;
}
if(pc != null)
{
pc = null;
}
if(nl != null)
{
nl = null;
}
System.gc();
System.gc();
System.gc();
try
{
Thread.sleep(10);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
System.out.println("CLEANED");
}
try
{
Thread.sleep(10000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
System.out.println("Finished");
}
}
如果我删除行pcan=(Native)pc.newInstance();
然后自定义ClassLoder将垃圾收集。
什么是错的?
问候
没有办法做你想做的事。您可以尝试在系统之间混合使用runFinalization()调用。gc(),但最终仍然不能保证类加载器将被垃圾收集。
(请注意,直接使用findClass是不方便的。可能您使用findClass是因为该类不是由NativeLibraryLoaderClassLoader实际加载的。这是因为您使用的是无参数ClassLoader构造函数,默认情况下该构造函数将应用程序类装入器用作父类。如果添加NativeLibraryLoaderClassLoader(){super(null);}
,那么您应该能够切换到loadClass。)
我正在尝试在Spring Boot项目中加载应用程序属性进行测试。我也在使用@DataJpaTest注释。许多人建议使用@TestProperty tySource注释与@datajpaTest的组合,但它不是加载属性。如果我使用@SpringBooTest,它就是加载属性。 我的应用程序属性文件位于主/资源/文件夹中。如果我使用,它正在工作,但我有 这未能使用Spring启动测试进行自动配置。我
框架中所有的类都是通过类加载器(ClassLoader)加载的,通过Loader我们可以实现类的统一管理。下面我们一起来看看Loader提供了哪些加载方法: 1. Loader::import 加载一个类或者加载一个包 方法原型 import( $classPath, $type = IMPORT_APP, $extension=EXT_PHP ) 参数名称 参数说明 $classPath 文件的
加载器,顾名思义,是用于加载元素的,加载的元素可以是库(类),视图文件 , 驱动器 ,辅助函数 , 模型 或其他你自己的文件。 注解 该类由系统自动加载,你无需手工加载。 应用程序"包" 包的视图文件 类参考 应用程序"包" 应用程序包(Package)可以很便捷的将你的应用部署在一个独立的目录中, 以实现自己整套的类库,模型,辅助函数,配置,文件和语言包。 建议将这些应用程序包放置在 appli
在J2EE中,可能无法正常工作。改用。 多少能说明他们在想些什么?这里的“J2EE”环境到底是什么意思?
PMD规则如下: 使用合适的类加载器(关键) 在J2EE中,可能无法按预期工作。使用。 你能解释一下他们的想法吗?这里“J2EE”环境的确切含义是什么?
我正试图通过Glide将图像加载到。但是图像没有加载-我得到一个错误。我正在使用以下代码 日志