From 71cbf28e3323dc9f0898deff6904cdedcbb88c59 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 5 Jun 2014 18:04:49 -0700 Subject: Improve the load/loadLibrary documentation. Also improve the exception detail message for the default case. Experience with third-party app developers is that the current documentation is unhelpful and the current exception detail message is misleading. If we didn't have to use the existing ClassLoader API, we could actually list the exact pathnames we'd tried. Change-Id: I31e1980addf34d6ada6a112949801c970f73bd2b --- luni/src/main/java/java/lang/Runtime.java | 63 +++++++++++++++++-------------- luni/src/main/java/java/lang/System.java | 36 ++++-------------- 2 files changed, 42 insertions(+), 57 deletions(-) diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java index 4b66c2d..a3cb83e 100644 --- a/luni/src/main/java/java/lang/Runtime.java +++ b/luni/src/main/java/java/lang/Runtime.java @@ -307,57 +307,64 @@ public class Runtime { } /** - * Loads and links the dynamic library that is identified through the - * specified path. This method is similar to {@link #loadLibrary(String)}, - * but it accepts a full path specification whereas {@code loadLibrary} just - * accepts the name of the library to load. + * Loads the shared library found at the given absolute path. + * This should be of the form {@code /path/to/library/libMyLibrary.so}. + * Most callers should use {@link #loadLibrary(String)} instead, and + * let the system find the correct file to load. * - * @param pathName - * the absolute (platform dependent) path to the library to load. - * @throws UnsatisfiedLinkError - * if the library can not be loaded. + * @throws UnsatisfiedLinkError if the library can not be loaded, + * either because it's not found or because there is something wrong with it. */ - public void load(String pathName) { - load(pathName, VMStack.getCallingClassLoader()); + public void load(String absolutePath) { + load(absolutePath, VMStack.getCallingClassLoader()); } /* - * Loads and links the given library without security checks. + * Loads the given shared library using the given ClassLoader. */ - void load(String pathName, ClassLoader loader) { - if (pathName == null) { - throw new NullPointerException("pathName == null"); + void load(String absolutePath, ClassLoader loader) { + if (absolutePath == null) { + throw new NullPointerException("absolutePath == null"); } - String error = doLoad(pathName, loader); + String error = doLoad(absolutePath, loader); if (error != null) { throw new UnsatisfiedLinkError(error); } } /** - * Loads and links the library with the specified name. The mapping of the - * specified library name to the full path for loading the library is - * implementation-dependent. + * Loads a shared library. Class loaders have some influence over this + * process, but for a typical Android app, it works as follows: * - * @param libName - * the name of the library to load. - * @throws UnsatisfiedLinkError - * if the library can not be loaded. + *

Given the name {@code "MyLibrary"}, that string will be passed to + * {@link System#mapLibraryName}. That means it would be a mistake + * for the caller to include the usual {@code "lib"} prefix and {@code ".so"} + * suffix. + * + *

That file will then be searched for on the application's native library + * search path. This consists of the application's own native library directory + * followed by the system's native library directories. + * + * @throws UnsatisfiedLinkError if the library can not be loaded, + * either because it's not found or because there is something wrong with it. */ - public void loadLibrary(String libName) { - loadLibrary(libName, VMStack.getCallingClassLoader()); + public void loadLibrary(String nickname) { + loadLibrary(nickname, VMStack.getCallingClassLoader()); } /* - * Searches for a library, then loads and links it without security checks. + * Searches for and loads the given shared library using the given ClassLoader. */ void loadLibrary(String libraryName, ClassLoader loader) { if (loader != null) { String filename = loader.findLibrary(libraryName); if (filename == null) { - throw new UnsatisfiedLinkError("Couldn't load " + libraryName + - " from loader " + loader + - ": findLibrary returned null"); + // It's not necessarily true that the ClassLoader used + // System.mapLibraryName, but the default setup does, and it's + // misleading to say we didn't find "libMyLibrary.so" when we + // actually searched for "liblibMyLibrary.so.so". + throw new UnsatisfiedLinkError(loader + " couldn't find \"" + + System.mapLibraryName(libraryName) + "\""); } String error = doLoad(filename, loader); if (error != null) { diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java index 2d33bc6..185701e 100644 --- a/luni/src/main/java/java/lang/System.java +++ b/luni/src/main/java/java/lang/System.java @@ -584,27 +584,14 @@ public final class System { } /** - * Loads and links the dynamic library that is identified through the - * specified path. This method is similar to {@link #loadLibrary(String)}, - * but it accepts a full path specification whereas {@code loadLibrary} just - * accepts the name of the library to load. - * - * @param pathName - * the path of the file to be loaded. + * See {@link Runtime#load}. */ public static void load(String pathName) { Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader()); } /** - * Loads and links the library with the specified name. The mapping of the - * specified library name to the full path for loading the library is - * implementation-dependent. - * - * @param libName - * the name of the library to load. - * @throws UnsatisfiedLinkError - * if the library could not be loaded. + * See {@link Runtime#loadLibrary}. */ public static void loadLibrary(String libName) { Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader()); @@ -722,24 +709,15 @@ public final class System { /** * Returns the platform specific file name format for the shared library - * named by the argument. - * - * @param userLibName - * the name of the library to look up. - * @return the platform specific filename for the library. + * named by the argument. On Android, this would turn {@code "MyLibrary"} into + * {@code "libMyLibrary.so"}. */ - public static native String mapLibraryName(String userLibName); + public static native String mapLibraryName(String nickname); /** - * Sets the value of the named static field in the receiver to the passed in - * argument. - * - * @param fieldName - * the name of the field to set, one of in, out, or err - * @param stream - * the new value of the field + * Used to set System.err, System.in, and System.out. */ - private static native void setFieldImpl(String fieldName, String signature, Object stream); + private static native void setFieldImpl(String field, String signature, Object stream); /** * A properties class that prohibits changes to any of the properties -- cgit v1.1