I was reading the java\lang\Throwable.java. 发现 native int getStackTraceDepth(); 但是并没有找到它的原型。所以,就想知道,如何找到java native的方法体。
private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
return stackTrace;
}
/**
* Returns the number of elements in the stack trace (or 0 if the stack
* trace is unavailable).
*
* package-protection for use by SharedSecrets.
*/
native int getStackTraceDepth();
链接: http://bbs.csdn.net/topics/220055713
===原文====
最近在学习java源码,看到很多java类在调用底层资源方法都终结在了native方法上,我突然明白了jvm之所以能跨平台是因为jvm.dll提供了native方法的实现,在其他操作系统上相应的jvm文件提供了native方法的实现,所以使用jvm.dll中定义的native函数并不会破坏平台无关性,我便将java src中的native移植到我自己的代码中
1
2
|
private
native
StackTraceElement getStackTraceElement(
int
index);
private
native
int
getStackTraceDepth();
|
这两句是从 Throwable 中抄来的,试图也能在我的程序中得到方法的栈调用层次,结果报了找不到动态链接库的异常java.lang.UnsatisfiedLinkError,然后我想这个方法应该是定义在C:\Program Files\Java\jre1.5.0_07\bin\client\jvm.dll 虚拟机种,然后加入。
1
2
3
|
static
{
System.loadLibrary(
"C:\\Program Files\\Java\\jre1.5.0_07\\bin\\client\\jvm.dll"
);
}
|
还是不对。
我开始产生疑问了
1、平时我用java lib的时候运行到最底层也是native,但是我也没有配置过库路径啊,怎么就能运行?
2、怎么能在自己的类李运行这些函数?
====原文结束====
原因是:
异常时因为函数名“getStackTraceDepth()“在加载的动态库中没有发现。你用javah会知道其函数名规则,它与定义的private native int “getStackTraceDepth()“有关。
果然,当我自己写一个JNI时,发现类似的问题:
>grep -r convertuserIdToEsid *
src/jni/libs/com_company_slingshot_test_jni_userIdToSidJNI.h: * Method: convertuserIdToEsid
src/jni/libs/com_company_slingshot_test_jni_userIdToSidJNI.h:
JNIEXPORT jstring JNICALL Java_com_company_slingshot_test_jni_userIdToSidJNI_convertuserIdToEsid
src/jni/libs/com_company_slingshot_test_jni_userIdToSidJNI.c:
JNIEXPORT jstring JNICALL Java_com_company_slingshot_test_jni_userIdToSidJNI_convertuserIdToEsid
src/main/java/com/company/slingshot/di/yuitosid/jni/userIdToSidJNI.java:
public final static native String convertuserIdToEsid(String userId);
src/main/java/com/company/slingshot/di/yuitosid/userIdToSid.java:
return userIdToSidJNI.convertuserIdToEsid(userId);
由此可见,当根据一个java头文件(带有native方法)生成一个JNI时,这个JNI对应的native方法会把java文件的package名加上的。正如上面看到的一样。
因此,native的方法,除非自己找到source code 重新编译,否者只能被原来那个java文件的方法唯一调用了。
这也就是为什么,提供*.so的库的提供者,同样需要提供一个*.h,供user再生成一个专门为java调用的jni *.so.
一. 什么是Native Method
二.为什么要使用Native Method
三.JVM怎样使Native Method跑起来: