java中toadd方法java中冒号是什么意思思

Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.
Where to add this:
so, when I highlight a word in eclipse ide, I will get the help.
To add Javadoc to Eclipse:
as many Javadoc packages as you want (they should be in zip or jar archives).
Open your Eclipse preferences, and navigate to Java -& Installed JREs. Click on the default JRE you use, and click the Edit button on the right.
In the window that pops up, click Add External JARs in the right column, and navigate to where you have the archives saved (you may want to save them somewhere out-of-the-way because if you delete the archives, your Javadoc won't work anymore).
Select the archives, and click Open. This should recognize the Javadoc archives and help you with code-completion and documentation (you may have to restart your IDE for this to take effect).
You can find Java SE development kit 7 Documentation
**You didn't specify what operating system you were on, so each OS may vary slightly.*
5,03832353
Right Click the JAR file in Project Explorer -> Properties -> From the left pane choose Javadoc Location -> enter the URL of your jar documentation.
Generally you can Google for: javadoc lib-name and then pickup the URL of the first site suggested by Google - going up a level.
For example Google returned this:
so by going up one level, I mean:
5,92342142
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Stack Exchange
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
Super User works best with JavaScript enabled303112345678910111213141516171819202122232425262728293012345678910
阅读排行榜
评论排行榜当前访客身份:游客 [
sudo apt-get install ia32-libs
:引用来自“ameihualudeai1”的评论请问下 如泰语...
:引用来自“ameihualudeai1”的评论请问下 如泰语...
:请问下 如泰语、印度语、缅甸语等,需要放在一起...
:引用来自“ameihualudeai1”的评论 能否问下,在...
:能否问下,在android上面如何添加一种有字型变换...
:引用来自“Catelyn”的评论翻译的官方的吗是,官...
:翻译的官方的吗
:真是什么鬼?
:先存下了!
今日访问:164
昨日访问:48
本周访问:164
本月访问:2750
所有访问:78341
Java中System.loadLibrary() 的执行过程
发表于2年前( 09:32)&&
阅读(29012)&|&评论()
0人收藏此文章,
System.loadLibrary()是我们在使用Java的JNI机制时,会用到的一个非常重要的函数,它的作用即是把实现了我们在Java code中声明的native方法的那个libraryload进来,或者load其他什么动态连接库。
算是处于好奇吧,我们可以看一下这个方法它的实现,即执行流程。(下面分析的那些code,来自于android 4.2.2 aosp版。)先看一下这个方法的code(在libcore/luni/src/main/java/java/lang/System.java这个文件中):
* 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.
public static void loadLibrary(String libName) {
Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
由上面的那段code,可以看到,它的实现非常简单,就只是先调用VMStack.getCallingClassLoader()获取到ClassLoader,然后再把实际要做的事情委托给了Runtime来做而已。接下来我们再看一下Runtime.loadLibrary()的实现(在libcore/luni/src/main/java/java/lang/Runtime.java这个文件中):
* Loads and links a library without security checks.
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");
String error = nativeLoad(filename, loader);
if (error != null) {
throw new UnsatisfiedLinkError(error);
String filename = System.mapLibraryName(libraryName);
List&String& candidates = new ArrayList&String&();
String lastError =
for (String directory : mLibPaths) {
String candidate = directory +
candidates.add(candidate);
if (new File(candidate).exists()) {
String error = nativeLoad(candidate, loader);
if (error == null) {
// We successfully loaded the library. Job done.
lastError =
if (lastError != null) {
throw new UnsatisfiedLinkError(lastError);
throw new UnsatisfiedLinkError("Library " + libraryName + " tried " + candidates);
由上面的那段code,我们看到,loadLibrary()可以被看作是一个2步走的过程:
获取到library path。对于这一点,上面的那个函数,依据于所传递的ClassLoader的不同,会有两种不同的方法。如果ClassLoader非空,则会利用ClassLoader的findLibrary()方法来获取library的path。而如果ClassLoader为空,则会首先依据传递进来的library name,获取到library file的name,比如传递“hello”进来,它的library file name,经过System.mapLibraryName(libraryName)将会是“libhello.so”;然后再在一个path list(即上面那段code中的mLibPaths)中查找到这个library file,并最终确定library 的path。
调用nativeLoad()这个native方法来load library
这段code,又牵出几个问题,首先,可用的library path都是哪些,这实际上也决定了,我们的so文件放在哪些folder下,才可以被真正load起来?其次,在native层load library的过程,又实际做了什么事情?下面会对这两个问题,一一的作出解答。
系统的library path
我们由简单到复杂的来看这个问题。先来看一下,在传入的ClassLoader为空的情况(尽管我们知道,在System.loadLibrary()这个case下不会发生),前面Runtime.loadLibrary()的实现中那个mLibPaths的初始化的过程,在Runtime的构造函数中,如下:
* Prevent this class from being instantiated.
private Runtime(){
String pathList = System.getProperty("java.library.path", ".");
String pathSep = System.getProperty("path.separator", ":");
String fileSep = System.getProperty("file.separator", "/");
mLibPaths = pathList.split(pathSep);
// Add a '/' to the end so we don't have to do the property lookup
// and concatenation later.
for (int i = 0; i & mLibPaths. i++) {
if (!mLibPaths[i].endsWith(fileSep)) {
mLibPaths[i] += fileS
可以看到,那个library path list实际上读取自一个system property。那在android系统中,这个system property的实际内容又是什么呢?dump这些内容出来,就像下面这样:
05-11 07:51:40.974: V/QRCodeActivity(11081): pathList = /vendor/lib:/system/lib
05-11 07:51:40.974: V/QRCodeActivity(11081): pathSep = :
05-11 07:51:40.974: V/QRCodeActivity(11081): fileSep = /
然后是传入的ClassLoader非空的情况,ClassLoader的findLibrary()方法的执行过程。首先看一下它的实现(在libcore/luni/src/main/java/java/lang/ClassLoader.java这个文件中):
* Returns the absolute path of the native library with the specified name,
* or {@code null}. If this method returns {@code null} then the virtual
* machine searches the directories specified by the system property
* "java.library.path".
* This implementation always returns {@code null}.
* @param libName
the name of the library to find.
* @return the absolute path of the library.
protected String findLibrary(String libName) {
竟然是一个空函数。那系统中实际运行的ClassLoader就是这个吗?我们可以做一个小小的实验,打印系统中实际运行的ClassLoader的String:
ClassLoader classLoader = getClassLoader();
Log.v(TAG, "classLoader = " + classLoader.toString());
在Galaxy Nexus上执行的结果如下:
05-11 08:18:57.857: V/QRCodeActivity(11556): classLoader = dalvik.system.PathClassLoader[dexPath=/data/app/com.qrcode.qrcode-1.apk,libraryPath=/data/app-lib/com.qrcode.qrcode-1]
看到了吧,android系统中的
ClassLoader真正的实现
在dalvik的dalvik.system.PathClassLoader。打开libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java来看
PathClassLoader这个class
的实现,可以看到,就只是简单的继承
BaseDexClassLoader而已,没有任何实际的内容
。接下来我们就来看一下
BaseDexClassLoader中
findLibrary()
真正的实现(
在libcore/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java这个文件中
public String findLibrary(String name) {
return pathList.findLibrary(name);
这个方法看上去倒挺简单,不用多做解释。然后来看那个pathList的初始化的过程,在BaseDexClassLoader的构造函数里:
* Constructs an instance.
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android
* @param optimizedDirectory directory where optimized dex files
* may be {@code null}
* @param libraryPath the list of directories containing native
* libraries, delimited by {@code File.pathSeparator}; may be
* {@code null}
* @param parent the parent class loader
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String libraryPath, ClassLoader parent) {
super(parent);
this.originalPath = dexP
this.originalLibraryPath = libraryP
this.pathList =
new DexPathList(this, dexPath, libraryPath, optimizedDirectory);
BaseDexClassLoader的构造函数也不用多做解释吧。然后是DexPathList的构造函数:
* Constructs an instance.
* @param definingContext the context in which any as-yet unresolved
* classes should be defined
* @param dexPath list of dex/resource path elements, separated by
* {@code File.pathSeparator}
* @param libraryPath list of native library directory path elements,
* separated by {@code File.pathSeparator}
* @param optimizedDirectory directory where optimized {@code .dex} files
* should be found and written to, or {@code null} to use the default
* system directory for same
public DexPathList(ClassLoader definingContext, String dexPath,
String libraryPath, File optimizedDirectory) {
if (definingContext == null) {
throw new NullPointerException("definingContext == null");
if (dexPath == null) {
throw new NullPointerException("dexPath == null");
if (optimizedDirectory != null) {
if (!optimizedDirectory.exists())
throw new IllegalArgumentException(
"optimizedDirectory doesn't exist: "
+ optimizedDirectory);
if (!(optimizedDirectory.canRead()
&& optimizedDirectory.canWrite())) {
throw new IllegalArgumentException(
"optimizedDirectory not readable/writable: "
+ optimizedDirectory);
this.definingContext = definingC
this.dexElements =
makeDexElements(splitDexPath(dexPath), optimizedDirectory);
this.nativeLibraryDirectories = splitLibraryPath(libraryPath);
关于我们的library path的问题,可以只关注最后的那个splitLibraryPath(),这个地方,实际上即是把传进来的libraryPath 又丢给splitLibraryPath来获取library path 的list。可以看一下DexPathList.splitLibraryPath()的实现:
* Splits the given library directory path string into elements
* using the path separator ({@code File.pathSeparator}, which
* defaults to {@code ":"} on Android, appending on the elements
* from the system library path, and pruning out any elements that
* do not refer to existing and readable directories.
private static File[] splitLibraryPath(String path) {
* Native libraries may exist in both the system and
* application library paths, and we use this search order:
1. this class loader's library path for application
2. the VM's library path from the system
property for system libraries
* This order was reversed prior to G see http://b/2933456.
ArrayList&File& result = splitPaths(
path, System.getProperty("java.library.path", "."), true);
return result.toArray(new File[result.size()]);
这个地方,是在用两个部分的library path list来由splitPaths构造最终的那个path list,一个部分是,传进来的library path,另外一个部分是,像我们前面看到的那个,是system property。然后再来看一下DexPathList.splitPaths()的实现:
* Splits the given path strings into file elements using the path
* separator, combining the results and filtering out elements
* that don't exist, aren't readable, or aren't either a regular
* file or a directory (as specified). Either string may be empty
* or {@code null}, in which case it is ignored. If both strings
* are empty or {@code null}, or all elements get pruned out, then
* this returns a zero-element list.
private static ArrayList&File& splitPaths(String path1, String path2,
boolean wantDirectories) {
ArrayList&File& result = new ArrayList&File&();
splitAndAdd(path1, wantDirectories, result);
splitAndAdd(path2, wantDirectories, result);
总结一下,ClassLoader的那个findLibrary()实际上会在两个部分的folder中去寻找System.loadLibrary()要load的那个library,一个部分是,构造ClassLoader时,传进来的那个library path,即是app folder,另外一个部分是system property。在android系统中,查找要load的library,实际上会在如下3个folder中进行:
/vendor/lib
/system/lib
/data/app-lib/com.qrcode.qrcode-1
上面第3个item只是一个例子,每一个app,它的那个app library path的最后一个部分都会是特定于那个app的。至于说,构造BaseDexClassLoader时的那个libraryPath 到底是怎么来的,那可能就会牵扯到android本身更复杂的一些过程了,在此不再做更详细的说明。
Native 层load library的过程
然后来看一下native层,把so文件load起的过程,先来一下nativeLoad()这个函数的实现(在JellyBean/dalvik/vm/native/java_lang_Runtime.cpp这个文件中):
* static String nativeLoad(String filename, ClassLoader loader)
* Load the specified full path as a dynamic library filled with
* JNI-compatible methods. Returns null on success, or a failure
* message on failure.
static void Dalvik_java_lang_Runtime_nativeLoad(const u4* args,
JValue* pResult)
StringObject* fileNameObj = (StringObject*) args[0];
Object* classLoader = (Object*) args[1];
char* fileName = NULL;
StringObject* result = NULL;
char* reason = NULL;
assert(fileNameObj != NULL);
fileName = dvmCreateCstrFromString(fileNameObj);
success = dvmLoadNativeCode(fileName, classLoader, &reason);
if (!success) {
const char* msg = (reason != NULL) ? reason : "unknown failure";
result = dvmCreateStringFromCstr(msg);
dvmReleaseTrackedAlloc((Object*) result, NULL);
free(reason);
free(fileName);
RETURN_PTR(result);
可以看到,nativeLoad()实际上只是完成了两件事情,第一,是调用dvmCreateCstrFromString()将Java 的library path String 转换到native的String,然后将这个path传给dvmLoadNativeCode()做load,dvmLoadNativeCode()这个函数的实现在dalvik/vm/Native.cpp中,如下:
* Load native code from the specified absolute pathname.
Per the spec,
* if we've already loaded a library with the specified pathname, we
* return without doing anything.
* TODO? for better results we should absolutify the pathname.
* correct results we should stat to get the inode and compare that.
* existing implementation is fine so long as everybody is using
* System.loadLibrary.
* The library will be associated with the specified class loader.
* spec says we can't load the same library into more than one class loader.
* Returns "true" on success. On failure, sets *detail to a
* human-readable description of the error or NULL if no detail is
* ownership of the string is transferred to the caller.
bool dvmLoadNativeCode(const char* pathName, Object* classLoader,
char** detail)
SharedLib* pE
/* reduce noise by not chattering about system libraries */
verbose = !!strncmp(pathName, "/system", sizeof("/system")-1);
verbose = verbose && !!strncmp(pathName, "/vendor", sizeof("/vendor")-1);
if (verbose)
ALOGD("Trying to load lib %s %p", pathName, classLoader);
*detail = NULL;
* See if we've already loaded it.
If we have, and the class loader
* matches, return successfully without doing anything.
pEntry = findSharedLibEntry(pathName);
if (pEntry != NULL) {
if (pEntry-&classLoader != classLoader) {
ALOGW("Shared lib '%s' already opened by CL %p; can't open in %p",
pathName, pEntry-&classLoader, classLoader);
if (verbose) {
ALOGD("Shared lib '%s' already loaded in same CL %p",
pathName, classLoader);
if (!checkOnLoadResult(pEntry))
* Open the shared library.
Because we're using a full path, the system
* doesn't have to search through LD_LIBRARY_PATH.
(It may do so to
* resolve this library's dependencies though.)
* Failures here are expected when java.library.path has several entries
* and we have to hunt for the lib.
* The current version of the dynamic linker prints detailed information
* about dlopen() failures.
Some things to check if the message is
* cryptic:
- make sure the library exists on the device
- verify that the right path is being opened (the debug log message
above can help with that)
- check to see if the library is valid (e.g. not zero bytes long)
- check config/prelink-linux-arm.map to ensure that the library
is listed and is not being overrun by the previous entry (if
loading suddenly stops working on a prelinked library, this is
a good one to check)
- write a trivial app that calls sleep() then dlopen(), attach
to it with "strace -p &pid&" while it sleeps, and watch for
attempts to open nonexistent dependent shared libs
* This can execute slowly for a large library on a busy system, so we
* want to switch from RUNNING to VMWAIT while it executes.
This allows
* the GC to ignore us.
Thread* self = dvmThreadSelf();
ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
handle = dlopen(pathName, RTLD_LAZY);
dvmChangeStatus(self, oldStatus);
if (handle == NULL) {
*detail = strdup(dlerror());
ALOGE("dlopen(\"%s\") failed: %s", pathName, *detail);
/* create a new entry */
SharedLib* pNewE
pNewEntry = (SharedLib*) calloc(1, sizeof(SharedLib));
pNewEntry-&pathName = strdup(pathName);
pNewEntry-&handle =
pNewEntry-&classLoader = classL
dvmInitMutex(&pNewEntry-&onLoadLock);
pthread_cond_init(&pNewEntry-&onLoadCond, NULL);
pNewEntry-&onLoadThreadId = self-&threadId;
/* try to add it to the list */
SharedLib* pActualEntry = addSharedLibEntry(pNewEntry);
if (pNewEntry != pActualEntry) {
ALOGI("WOW: we lost a race to add a shared lib (%s CL=%p)",
pathName, classLoader);
freeSharedLibEntry(pNewEntry);
return checkOnLoadResult(pActualEntry);
if (verbose)
ALOGD("Added shared lib %s %p", pathName, classLoader);
bool result =
void* vonL
vonLoad = dlsym(handle, "JNI_OnLoad");
if (vonLoad == NULL) {
ALOGD("No JNI_OnLoad found in %s %p, skipping init",
pathName, classLoader);
* Call JNI_OnLoad.
We have to override the current class
* loader, which will always be "null" since the stuff at the
* top of the stack is around Runtime.loadLibrary().
* the comments in the JNI FindClass function.)
OnLoadFunc func = (OnLoadFunc)vonL
Object* prevOverride = self-&classLoaderO
self-&classLoaderOverride = classL
oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
if (gDvm.verboseJni) {
ALOGI("[Calling JNI_OnLoad for \"%s\"]", pathName);
version = (*func)(gDvmJni.jniVm, NULL);
dvmChangeStatus(self, oldStatus);
self-&classLoaderOverride = prevO
if (version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 &&
version != JNI_VERSION_1_6)
ALOGW("JNI_OnLoad returned bad version (%d) in %s %p",
version, pathName, classLoader);
* It's unwise to call dlclose() here, but we can mark it
* as bad and ensure that future load attempts will fail.
* We don't know how far JNI_OnLoad got, so there could
* be some partially-initialized stuff accessible through
* newly-registered native method calls.
We could try to
* unregister them, but that doesn't seem worthwhile.
if (gDvm.verboseJni) {
ALOGI("[Returned from JNI_OnLoad for \"%s\"]", pathName);
if (result)
pNewEntry-&onLoadResult = kOnLoadO
pNewEntry-&onLoadResult = kOnLoadF
pNewEntry-&onLoadThreadId = 0;
* Broadcast a wakeup to anybody sleeping on the condition variable.
dvmLockMutex(&pNewEntry-&onLoadLock);
pthread_cond_broadcast(&pNewEntry-&onLoadCond);
dvmUnlockMutex(&pNewEntry-&onLoadLock);
哇塞,dvmLoadNativeCode()这个函数还真的是有点复杂,那就挑那些跟我们的JNI比较紧密相关的逻辑来看吧。可以认为这个函数做了下面的这样一些事情:
调用dlopen() 打开一个so文件,创建一个handle。
调用dlsym()函数,查找到so文件中的JNI_OnLoad()这个函数的函数指针。
执行上一步找到的那个JNI_OnLoad()函数。
至此,大体可以结束System.loadLibrary()的执行过程的分析。
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读33326人阅读
Java Calendar 类时间操作,代码很简单。
演示了获取时间,日期时间的累加和累减。
package MyT
* 演示 Calendar 的一般操作
import java.util.D
import java.text.SimpleDateF
import java.text.DateF
import java.util.C
public class Test
public Test()
public static void main(String[] args)
// 字符串转换日期格式
// DateFormat fmtDateTime = new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss&);
// 得到日期格式对象
// Date date = fmtDateTime.parse(strDateMake);
// 完整显示日期时间
String str = (new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss:SSS&)).format(new Date());
System.out.println(str);
// 创建 Calendar 对象
Calendar calendar = Calendar.getInstance();
// 初始化 Calendar 对象,但并不必要,除非需要重置时间
calendar.setTime(new Date());
// setTime 类似上面一行
// Date date = new Date();
// calendar.setTime(date);
// 显示年份
int year = calendar.get(Calendar.YEAR);
System.out.println(&YEAR is = & + String.valueOf(year));
// 显示月份 (从0开始, 实际显示要加一)
int MONTH = calendar.get(Calendar.MONTH);
System.out.println(&MONTH is = & + (MONTH + 1));
// 今年的第 N 天
int DAY_OF_YEAR = calendar.get(Calendar.DAY_OF_YEAR);
System.out.println(&DAY_OF_YEAR is = & + DAY_OF_YEAR);
// 本月第 N 天
int DAY_OF_MONTH = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(&DAY_OF_MONTH = & + String.valueOf(DAY_OF_MONTH));
// 3小时以后
calendar.add(Calendar.HOUR_OF_DAY, 3);
int HOUR_OF_DAY = calendar.get(Calendar.HOUR_OF_DAY);
System.out.println(&HOUR_OF_DAY + 3 = & + HOUR_OF_DAY);
// 当前分钟数
int MINUTE = calendar.get(Calendar.MINUTE);
System.out.println(&MINUTE = & + MINUTE);
// 15 分钟以后
calendar.add(Calendar.MINUTE, 15);
MINUTE = calendar.get(Calendar.MINUTE);
System.out.println(&MINUTE + 15 = & + MINUTE);
// 30分钟前
calendar.add(Calendar.MINUTE, -30);
MINUTE = calendar.get(Calendar.MINUTE);
System.out.println(&MINUTE - 30 = & + MINUTE);
// 格式化显示
str = (new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss:SS&)).format(calendar.getTime());
System.out.println(str);
// 重置 Calendar 显示当前时间
calendar.setTime(new Date());
str = (new SimpleDateFormat(&yyyy-MM-dd HH:mm:ss:SS&)).format(calendar.getTime());
System.out.println(str);
// 创建一个 Calendar 用于比较时间
Calendar calendarNew = Calendar.getInstance();
// 设定为 5 小时以前,后者大,显示 -1
calendarNew.add(Calendar.HOUR, -5);
System.out.println(&时间比较:& + pareTo(calendar));
// 设定7小时以后,前者大,显示 1
calendarNew.add(Calendar.HOUR, +7);
System.out.println(&时间比较:& + pareTo(calendar));
// 退回 2 小时,时间相同,显示 0
calendarNew.add(Calendar.HOUR, -2);
System.out.println(&时间比较:& + pareTo(calendar));
&#65279;&#65279;
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:288269次
积分:3354
积分:3354
排名:第5016名
原创:74篇
转载:28篇
评论:29条
(1)(1)(2)(2)(3)(2)(3)(3)(1)(2)(1)(7)(5)(5)(3)(2)(5)(2)(3)(2)(1)(1)(2)(1)(2)(1)(4)(1)(1)(3)(8)(2)(4)(1)(1)(1)(1)(2)(1)(2)(1)(2)(1)(4)(1)

我要回帖

更多关于 java中src是什么意思 的文章

 

随机推荐