How do I get a list of JNI libraries which are loaded?

前端 未结 7 1982
半阙折子戏
半阙折子戏 2020-11-28 07:54

Just what the subject says, is there a way in Java to get a list of all the JNI native libraries which have been loaded at any given time?

7条回答
  •  暗喜
    暗喜 (楼主)
    2020-11-28 08:24

    I've built on top of jitter's solution. This allows you to find out who (ClassLoader, Class) loaded each native library.

    import java.lang.reflect.Field;
    import java.util.*;
    import java.util.Map.Entry;
    
    /**
     * Helper functions for native libraries.
     * 

    * @author Gili Tzabari */ public class NativeLibraries { private final Field loadedLibraryNames; private final Field systemNativeLibraries; private final Field nativeLibraries; private final Field nativeLibraryFromClass; private final Field nativeLibraryName; /** * Creates a new NativeLibraries. *

    * @throws NoSuchFieldException if one of ClassLoader's fields cannot be found */ public NativeLibraries() throws NoSuchFieldException { this.loadedLibraryNames = ClassLoader.class.getDeclaredField("loadedLibraryNames"); loadedLibraryNames.setAccessible(true); this.systemNativeLibraries = ClassLoader.class.getDeclaredField("systemNativeLibraries"); systemNativeLibraries.setAccessible(true); this.nativeLibraries = ClassLoader.class.getDeclaredField("nativeLibraries"); nativeLibraries.setAccessible(true); Class nativeLibrary = null; for (Class nested : ClassLoader.class.getDeclaredClasses()) { if (nested.getSimpleName().equals("NativeLibrary")) { nativeLibrary = nested; break; } } this.nativeLibraryFromClass = nativeLibrary.getDeclaredField("fromClass"); nativeLibraryFromClass.setAccessible(true); this.nativeLibraryName = nativeLibrary.getDeclaredField("name"); nativeLibraryName.setAccessible(true); } /** * Returns the names of native libraries loaded across all class loaders. *

    * @return a list of native libraries loaded */ public List getLoadedLibraries() { try { @SuppressWarnings("UseOfObsoleteCollectionType") final Vector result = (Vector) loadedLibraryNames.get(null); return result; } catch (IllegalArgumentException | IllegalAccessException e) { throw new AssertionError(e); } } /** * Returns the native libraries loaded by the system class loader. *

    * @return a Map from the names of native libraries to the classes that loaded them */ public Map> getSystemNativeLibraries() { try { Map> result = new HashMap<>(); @SuppressWarnings("UseOfObsoleteCollectionType") final Vector libraries = (Vector) systemNativeLibraries.get(null); for (Object nativeLibrary : libraries) { String libraryName = (String) nativeLibraryName.get(nativeLibrary); Class fromClass = (Class) nativeLibraryFromClass.get(nativeLibrary); result.put(libraryName, fromClass); } return result; } catch (IllegalArgumentException | IllegalAccessException e) { throw new AssertionError(e); } } /** * Returns a Map from the names of native libraries to the classes that loaded them. *

    * @param loader the ClassLoader that loaded the libraries * @return an empty Map if no native libraries were loaded */ public Map> getNativeLibraries(final ClassLoader loader) { try { Map> result = new HashMap<>(); @SuppressWarnings("UseOfObsoleteCollectionType") final Vector libraries = (Vector) nativeLibraries.get(loader); for (Object nativeLibrary : libraries) { String libraryName = (String) nativeLibraryName.get(nativeLibrary); Class fromClass = (Class) nativeLibraryFromClass.get(nativeLibrary); result.put(libraryName, fromClass); } return result; } catch (IllegalArgumentException | IllegalAccessException e) { throw new AssertionError(e); } } /** * The same as {@link #getNativeLibraries()} except that all ancestor classloaders are processed * as well. *

    * @param loader the ClassLoader that loaded (or whose ancestors loaded) the libraries * @return an empty Map if no native libraries were loaded */ public Map> getTransitiveNativeLibraries(final ClassLoader loader) { Map> result = new HashMap<>(); ClassLoader parent = loader.getParent(); while (parent != null) { result.putAll(getTransitiveNativeLibraries(parent)); parent = parent.getParent(); } result.putAll(getNativeLibraries(loader)); return result; } /** * Converts a map of library names to the classes that loaded them to a map of library names to * the classloaders that loaded them. *

    * @param libraryToClass a map of library names to the classes that loaded them * @return a map of library names to the classloaders that loaded them */ public Map getLibraryClassLoaders(Map> libraryToClass) { Map result = new HashMap<>(); for (Entry> entry : libraryToClass.entrySet()) result.put(entry.getKey(), entry.getValue().getClassLoader()); return result; } /** * Returns a list containing the classloader and its ancestors. *

    * @param loader the classloader * @return a list containing the classloader, its parent, and so on */ public static List getTransitiveClassLoaders(ClassLoader loader) { List result = new ArrayList<>(); ClassLoader parent = loader.getParent(); result.add(loader); while (parent != null) { result.add(parent); parent = parent.getParent(); } return result; } }

    提交回复
    热议问题