随笔 - 3  文章 - 10  trackbacks - 0
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用链接

留言簿(3)

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

最近有做个C++ for JNI 的辅助类库和工具的想法,使得在JNI里可以用对象化的模式来访问java对象。例如java::lang::System::out->println();

这个类库和辅助工具除了支持对象化访问外,还可以带来的方便有:
 原来需要手工写入代码中的大量的classname/membername和type sig可以自动生成
 原来经常需要检查java exception,可以利用C++的try/catch模式做Exception处理
 原来手工javah生成include文件的方法可以通过辅助工具自动生成和java class对应的C++ 类函数定义,开发者只需要实现这个函数即可。
 提供一些辅助函数、宏定义和模板使得开发JNI更加方便。例如ansi/unicode/jstring字符串转换、C++版本的StringBuilder、外部动态加载jvm等。

在gnu的gcj里采用的就是类似的模式。我看到的sun的jdk源代码里也普遍采用了这种模式,也许将来sun会发布一个JNI的C++版本。
posted @ 2009-09-17 05:51 TaoLei 阅读(1486) | 评论 (2)编辑 收藏

jni的几个基本的性能测试分析

今天对jvm运行jni做了几个基本的性能测试,测试的jvm有jdk1.4.2_19、jdk1.5.0_04和jdk1.6.0_14,测试的重复次数都是一亿次,测试结果的绝对数值意义不大,仅供参考。
java调用jni空函数和调用java方法的性能(比较):
java.version = 1.6.0_14
 Java空方法调用  耗时 329 ms   平均每秒  303951367
 JNI空方法调用   耗时 1531 ms  平均每秒  65316786

java.version = 1.5.0_04
 java空方法调用  耗时 312 ms   平均每秒  320512820
 JNI空方法调用   耗时 1891 ms  平均每秒  52882072

java.version = 1.4.2_19
 java空方法调用  耗时 312 ms   平均每秒  320512820
 JNI空方法调用   耗时 3672 ms  平均每秒  27233115
 
 jdk版本越高,JNI调用的性能越好,这点要感谢sun的努力了。
在jdk1.6下,仅仅是空方法调用,JNI的性能就要比java内部调用慢将近5倍,而在jdk1.4下更是慢了十多倍。

 

jni里查找class(JNIEnv.FindClass)和fieldid(JNIEnv.GetFieldID)和jni读取java Field(JNIEnv.GetFieldValue)的性能:
缓存表示只调用一次,不缓存就是每次都调用。

java.version = 1.6.0_14
JNI 字段读取 (缓存Class=false ,缓存字段ID=false) 耗时 : 79172 ms    平均每秒 : 1263072
JNI 字段读取 (缓存Class=true ,缓存字段ID=false)  耗时 : 25015 ms    平均每秒 : 3997601
JNI 字段读取 (缓存Class=false ,缓存字段ID=true)  耗时 : 50765 ms    平均每秒 : 1969861
JNI 字段读取 (缓存Class=true ,缓存字段ID=true)   耗时 : 2125 ms     平均每秒 : 47058823

java.version = 1.5.0_04
JNI 字段读取 (缓存Class=false ,缓存字段ID=false) 耗时 : 87109 ms    平均每秒 : 1147987
JNI 字段读取 (缓存Class=true ,缓存字段ID=false)  耗时 : 32031 ms    平均每秒 : 3121975
JNI 字段读取 (缓存Class=false ,缓存字段ID=true)  耗时 : 51657 ms    平均每秒 : 1935846
JNI 字段读取 (缓存Class=true ,缓存字段ID=true)   耗时 : 2187 ms     平均每秒 : 45724737

java.version = 1.4.2_19
JNI 字段读取 (缓存Class=false ,缓存字段ID=false) 耗时 : 97500 ms    平均每秒 : 1025641
JNI 字段读取 (缓存Class=true ,缓存字段ID=false)  耗时 : 38110 ms    平均每秒 : 2623983
JNI 字段读取 (缓存Class=false ,缓存字段ID=true)  耗时 : 55204 ms    平均每秒 : 1811462
JNI 字段读取 (缓存Class=true ,缓存字段ID=true)   耗时 : 4187 ms     平均每秒 : 23883448

 查找class和ID(field和method)消耗大量的时间。只是读取字段值的时间基本上跟上面的JNI空方法是一个数量级。
 而如果每次都根据名称查找class和field的话,性能要下降高达40倍。
 读取一个字段值的性能在百万级上,在交互频繁的JNI应用中是不能忍受的。
 消耗时间最多的就是查找class,因此在Native里保存class和member id是必要的。
 class和member id在一定范围内是稳定的,但在动态加载的class loader下,保存全局的class要么可能失效,要么可能造成无法卸载classloader,
 在诸如OSGI框架下的JNI应用还要特别注意这方面的问题。

 在读取字段值和查找FieldID上,jdk1.4和1.5、1.6的差距是非常明显的。但在最耗时的查找class上,三个版本没有明显差距。

 

 

基于线程变量(TlsSetValue/TlsGetValue)的JNIEnv读取和基于JavaVM的JNIEnv读取(JavaVM.GetEnv)

JNIEnv读取 (线程变量)   耗时 : 516 ms      平均每秒 : 193798449

java.version = 1.6.0_14
JNIEnv读取 (JavaVM)     耗时 : 1985 ms     平均每秒 : 50377833

java.version = 1.5.0_04
JNIEnv读取 (JavaVM)     耗时 : 2218 ms     平均每秒 : 45085662

java.version = 1.4.2_19
JNIEnv读取 (JavaVM)     耗时 : 2234 ms     平均每秒 : 44762757


为什么要做这个JNIEnv读取测试:
 JavaVM是进程全局有效的,而JNIEnv是线程相关的,
 但JNI编程是可以不用这样的模式来获得JNIEnv的,需要在所有相关的函数调用里带JNIEnv参数。
 在C++编程模式下,大量的对象方法调用都要带JNIEnv的参数确实不如动态获得它方便。
 在性能可以接受的范围内是可以考虑用其他的模式来随时获得JNIEnv的。因此我才会做这个测试。

 从上面的测试数据看,用线程变量的性能是优于JavaVM.GetEnv的,而且从相对的数量级上看,个人认为是完全可以接受这种JNIEnv的获得模式的。

 

希望以上的测试分析对大家的JNI应用开发和优化有一定的参考价值。

 

posted @ 2009-09-17 05:39 TaoLei 阅读(4124) | 评论 (2)编辑 收藏

java反编译+UI辅助工具
反编译引擎是自己写的,一次发布到公共网络上,
UI辅助工具包含很多方便的功能,可以直接查看jar文件、可以模糊查找类名、查看继承关系、查找引用、查找字符串等。
欢迎大家去试用一下。

第一次使用BlogJava,不知道怎样提供下载地址,哪位朋友介绍一下
http://www.blogjava.net/Files/taolei/classexplorer.zip

如果这个不行可以在
http://taolei.download.csdn.net/
下载

posted @ 2009-09-15 11:34 TaoLei 阅读(1682) | 评论 (6)编辑 收藏
仅列出标题