zoukankan      html  css  js  c++  java
  • Unload Java JNI DLL

    The problem

    Once a dll is loaded in a java program using either System.load() or System.loadLibrary(), how do we unload it? Theoretically the dll should be unloaded when the corresponding class loader is being garbage collected.

    When a class loader is garbage collected?

    A class loader is garbage collected when:

    • All objects of classes loaded by the class loader should be garbage collected.
    • All references pointing to the class loader object should be null.

    What class loader should we use?

    It is not possible to use the default class loader because it won't be garbage collected. So, we should create our own class loader and use it instead of the default one.

    Check these links for custom java class loaders implementations:

    Simple Java Custom Class Loader Implementation
    Java Custom URL Class Loader Implementation With Repository
    Java Custom URL Class Loader Implementation With Resource List

    DLL unloading example using the custom class loader

    Create a file A.java and add the following code.

    package com.codethesis.example;
    
    public class A {
        public A() {}
    
        static {
            System.loadLibrary("mydll");
        }
    
        public native void print();
    
        public void finalize() {
            System.out.println("A garbage collected");
        }
    }
    

    You'll need to have a JNI dll mydll.dll in the classpath which contains a method print() as shown in the code. Then create a file Test.java and add this code:

    package com.codethesis.example;
    
    import java.lang.reflect.Method;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            CustomClassLoader cl = new CustomClassLoader();
            Class ca = cl.findClass("com.codethesis.example.A");
            Object a = ca.newInstance();
            Method p = ca.getMethod("print");
            p.invoke(a);
            p = null;
            ca = null;
            a = null;
            cl = null;
            System.gc();
        }
    }
    

    After System.gc() is called the custom class loader will be garbage collected and the dll wlll be unloaded.

    Why do we use java reflection?

    Isn't it possile just to cast the "a" object to type "A" as it is in the code below?

    package com.codethesis.example;
    
    import java.lang.reflect.Method;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            CustomClassLoader cl = new CustomClassLoader();
            Class ca = cl.findClass("com.codethesis.example.A");
            A a = (A)ca.newInstance(); //a ClassCastException is thrown!
            a.print();
            ca = null;
            a = null;
            cl = null;
            System.gc();
        }
    }
    

    Actually, it is not possible because A class is loaded by the default class loader and therefore these are two different classes. However there is a simple solution for this problem using interfaces. Create a file IA.java and add the following code inside:

    package com.codethesis.example;
    
    public interface IA {
        public void print();
    }
    

    Then modify the A class to implement this interface:

    package com.codethesis.example;
    
    public class A implements IA {
        public A() {}
    
        static {
            System.loadLibrary("mydll");
        }
    
        public native void print();
    
        public void finalize() {
            System.out.println("A garbage collected");
        }
    }
    

    The Test class should look like this:

    package com.codethesis.example;
    
    public class Test {
        public static void main(String[] args) throws Exception {
            CustomClassLoader cl = new CustomClassLoader();
            Class ca = cl.findClass("com.codethesis.example.A");
            IA ia = (IA)ca.newInstance();
            ia.print();
            ca = null;
            ia = null;
            cl = null;
            System.gc();
        }
    }

    来源:http://www.codethesis.com/
  • 相关阅读:
    利用SQL注入漏洞登录后台
    http://www.cnblogs.com/xdp-gacl/p/4200090.html
    文件上传的三种模式-Java
    Maven多模块,Dubbo分布式服务框架,SpringMVC,前后端分离项目,基础搭建,搭建过程出现的问题
    win10 安装 mysql解压版安装步骤
    移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
    IEDA 启动main报 stock
    基于JavaMail的Java邮件发送:简单邮件发送
    如何确定一个需求是真需求
    VS中批注的使用
  • 原文地址:https://www.cnblogs.com/beautiful-scenery/p/3588834.html
Copyright © 2011-2022 走看看