LuaJava:跟着LuaJava一步一步学习JNI -1
来源:互联网 发布:手机android编程软件 编辑:程序博客网 时间:2024/05/19 18:40
Java 测试代码案例1如下:
LuaState L = LuaStateFactory.newLuaState(); L.openLibs(); LuaObject global_a = L.getLuaObject("global_a");
使用LuaJava第一步就是创建Lua VM虚拟机LuaState . LuaState 由LuaStateFactory 管理。
LuaState L = LuaStateFactory.newLuaState(); 可以创建一个新LuaState。
但是在LuaState 构造函数中使用_open()本地方法创建LuaVM.
/**
* Constructor to instance a new LuaState and initialize it with LuaJava's functions
* @param stateId
*/
protected LuaState(int stateId)
{
luaState = _open();
luajava_open(luaState, stateId);
this.stateId = stateId;
}
使用的本地方法为:private synchronized native CPtr _open();
在c代码 实现代码为:
************************************************************************///由java本地方法生成:LuaState类private synchronized native CPtr _open();JNIEXPORT jobject JNICALL Java_org_keplerproject_luajava_LuaState__1open(JNIEnv * env , jobject jobj){ //通过Lua C API创建LuaVM lua_State * L = lua_open(); jobject obj; jclass tempClass; //通过FindClass()来查找CPtr java类 tempClass = ( *env )->FindClass( env , "org/keplerproject/luajava/CPtr" ); //创建新Java对象 obj = ( *env )->AllocObject( env , tempClass ); if ( obj ) { //根据类和类字段签名获取类字段 jfieldID _fieldID=( *env )->GetFieldID( env , tempClass , "peer", "J" ); //设置类字段值,这里设置类CPtr 对象obj 字段peer 的值为 L的指针地址。 ( *env )->SetLongField( env , obj ,_fieldID , ( jlong ) L ); } //同时返回CPtr局部对象。 return obj;}
在JNI.H头文件中:
class _jobject {};
typedef _jobject *jobject;
在__open()返回值为 jobject obj; 其实就是指针的地址。
/** * An abstraction for a C pointer data type. A CPtr instance represents, on * the Java side, a C pointer. The C pointer could be any <em>type</em> of C * pointer. */public class CPtr{ /** * Compares this <code>CPtr</code> to the specified object. * * @param other a <code>CPtr</code> * @return true if the class of this <code>CPtr</code> object and the * class of <code>other</code> are exactly equal, and the C * pointers being pointed to by these objects are also * equal. Returns false otherwise. */public boolean equals(Object other){if (other == null)return false;if (other == this) return true;if (CPtr.class != other.getClass()) return false;return peer == ((CPtr)other).peer; } /* Pointer value of the real C pointer. Use long to be 64-bit safe. *///这里其实是保存lua_State * L = lua_open(); L指针的地址 private long peer; /** * Gets the value of the C pointer abstraction * @return long */ protected long getPeer() { return peer; } /* No-args constructor. */ CPtr() {} }
至此,LuaState 虚拟机创建完成,LuaState在C语言中的指针L的地址,由对象CPtr 中Peer 保存Long 类型的值。
在LuaState 中有 luaopen_java()方法:
/**
* Initializes lua State to be used by luajava
* @param cptr
* @param stateId
*/
private synchronized native void luajava_open(CPtr cptr, int stateId);
因为CPtr保存了LuaState 的指针,所以C要获取到Lua VM必须通过CPtr传递参数。
/** * Creates a reference to an object in the variable globalName * @param globalName * @return LuaObject */public LuaObject getLuaObject(String globalName){return new LuaObject(this, globalName);}
在LuaState.getLuaObject(String globalName) 来获取全局变量时,LuaState 首先创建一个LuaObject 对象来代理Lua 里面的数据类型,
public class LuaObject{protected Integer ref;protected LuaState L;}
LuaObject 中持有LuaVM虚拟机和Lua对象的引用。
LuaObject 持有Lua对象的引用时通过Lua的引用机制。
JNIEXPORT jint JNICALL Java_org_keplerproject_luajava_LuaState__1Lref (JNIEnv * env , jobject jobj , jobject cptr , jint t){ lua_State * L = getStateFromCPtr( env , cptr ); return ( jint ) luaL_ref( L , ( int ) t );}
Java 测试代码案例1如下:
hello.lua 代码:
sys = luajava.bindClass("java.lang.System")local t1=sys:currentTimeMillis()for i=1,10000 do local obj = luajava.newInstance("org.keplerproject.luajava.JavaObject")endlocal t2=sys:currentTimeMillis()local t =t2-t1print("lua时间:"..t)
main.java代码:
Object obj =null;long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { obj =new Object();} long t2 = System.currentTimeMillis(); System.out.println("java时间:"+(t2-t1));LuaState L = LuaStateFactory.newLuaState(); L.openLibs(); L.LdoFile("hello.lua"); L.close();打印结果:
java时间:0
lua时间:156
通过Lua脚本创建java 对象实例明显性能上有差距,来让我们看看具体原因。
luajava.newInstance("org.keplerproject.luajava.JavaObject") 直接调用luajava Table中注册的函数 。
/***************************************************************************** Function: javaNewInstance* ****/int javaNewInstance( lua_State * L ){ jint ret; jmethodID method; const char * className; jstring javaClassName; jthrowable exp; lua_Number stateIndex; JNIEnv * javaEnv; /* Gets the luaState index */ lua_pushstring( L , LUAJAVASTATEINDEX ); lua_rawget( L , LUA_REGISTRYINDEX ); if ( !lua_isnumber( L , -1 ) ) { lua_pushstring( L , "Impossible to identify luaState id." ); lua_error( L ); } stateIndex = lua_tonumber( L , -1 ); lua_pop( L , 1 ); /* get the string parameter */ if ( !lua_isstring( L , 1 ) ) { lua_pushstring( L , "Invalid parameter type. String expected as first parameter." ); lua_error( L ); } className = lua_tostring( L , 1 ); /* Gets the JNI Environment */ javaEnv = getEnvFromState( L ); if ( javaEnv == NULL ) { lua_pushstring( L , "Invalid JNI Environment." ); lua_error( L ); } //以上都是对java的检查 //获取LuaJavaAPI 类的静态函数javaNewInstance 的方法Id method = ( *javaEnv )->GetStaticMethodID( javaEnv , luajava_api_class , "javaNewInstance" , "(ILjava/lang/String;)I" ); //创建一个java string对象 javaClassName = ( *javaEnv )->NewStringUTF( javaEnv , className ); //调用LuaJavaAPI 的javaNewInstance 静态方法,同时传递参数。剩下事情交由java来处理实际创建java对象的功能。 //调用LuaJavaAPI的静态函数,才是该函数最重要的地方,也是通过Lua语言创建java对象的关键。 ret = ( *javaEnv )->CallStaticIntMethod( javaEnv , luajava_api_class , method, (jint)stateIndex , javaClassName ); //判断是否发生异常 exp = ( *javaEnv )->ExceptionOccurred( javaEnv ); /* Handles exception */ if ( exp != NULL ) { jobject jstr; const char * str; ( *javaEnv )->ExceptionClear( javaEnv ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , get_message_method ); ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); if ( jstr == NULL ) { jmethodID methodId; methodId = ( *javaEnv )->GetMethodID( javaEnv , throwable_class , "toString" , "()Ljava/lang/String;" ); jstr = ( *javaEnv )->CallObjectMethod( javaEnv , exp , methodId ); } str = ( *javaEnv )->GetStringUTFChars( javaEnv , jstr , NULL ); lua_pushstring( L , str ); ( *javaEnv )->ReleaseStringUTFChars( javaEnv , jstr, str ); lua_error( L ); } //对局部引用进行释放 ( *javaEnv )->DeleteLocalRef( javaEnv , javaClassName ); return ret;}
LuaJavaAPI 中静态javaNewInstance 函数源代码:
/** * Pushes a new instance of a java Object of the type className * * @param luaState int that represents the state to be used * @param className name of the class * @return number of returned objects * @throws LuaException */ public static int javaNewInstance(int luaState, String className) throws LuaException {//根据LuaVM索引来获取虚拟机引用 LuaState L = LuaStateFactory.getExistingState(luaState); synchronized (L) { Class clazz; try {//根据类名称利用反射技术获取CLass对象 clazz = Class.forName(className); } catch (ClassNotFoundException e) { throw new LuaException(e); } //创建对象 Object ret = getObjInstance(L, clazz); L.pushJavaObject(ret); return 1; } }很明显在Native Code中对于实际功能的处理非常少,还是利用java语言本身提供的特性来实现功能的。仅仅这样测试,虽然有性能问题,但是不知道问题到底有多大,是否能够接受,看样子只能用LuaInterface与LuaJava相对对比才能知道差距。
- LuaJava:跟着LuaJava一步一步学习JNI -1
- LuaJava: 一步一步调试LuaJava
- LuaJava
- LuaJava:
- LuaJava学习笔记[1]初探Lua
- LuaJava:LuaJava 初探
- LuaJava:一点一点写Example 1
- luajava升级
- AndroLua, Luajava初步探究
- LuaJava学习笔记[2]使用Lua控制Java对象
- luajava中使用luajit提升性能
- Lua and LuaJava ported to Android
- [LUA]几个简单的luajava使用例子
- [LUA]在eclipse中使用luajava
- LuaJava在Java、Android中的使用
- luajava数值和对象传递的一个例子
- 图形绘制布局开发_如何绘制几何图形(LuaJava)
- 一步一步学习JNI(一)
- UFT
- Hibernate-检索策略
- 网上下载一个开源项目,但是缺失jar包怎么办
- Xcode7中CocosPods 编译报错
- [LeetCode] Move Zeroes
- LuaJava:跟着LuaJava一步一步学习JNI -1
- lightoj 1100 - Again Array Queries 【思维题】
- win7安装ubuntu双系统,建议使用u盘安装
- MFC获取系统时间
- JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
- 相对布局的layout_alignLeft属性
- 飞机订票系统客户端-分段截断异常处理
- OnTouchListener的用法
- html复选框选中事件