LuaJava:跟着LuaJava一步一步学习JNI -1
2015-10-25 22:45
513 查看
Java 测试代码案例1如下:
使用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代码 实现代码为:
在JNI.H头文件中:
class _jobject {};
typedef _jobject *jobject;
在__open()返回值为 jobject obj; 其实就是指针的地址。
至此,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传递参数。
在LuaState.getLuaObject(String globalName) 来获取全局变量时,LuaState 首先创建一个LuaObject 对象来代理Lua 里面的数据类型,
LuaObject 中持有LuaVM虚拟机和Lua对象的引用。
LuaObject 持有Lua对象的引用时通过Lua的引用机制。
Java 测试代码案例1如下:
hello.lua 代码:
main.java代码:
java时间:0
lua时间:156
通过Lua脚本创建java 对象实例明显性能上有差距,来让我们看看具体原因。
luajava.newInstance("org.keplerproject.luajava.JavaObject") 直接调用luajava Table中注册的函数 。
LuaJavaAPI 中静态javaNewInstance 函数源代码:
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") end local t2=sys:currentTimeMillis() local t =t2-t1 print("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相对对比才能知道差距。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Native 绘图方法
- 详解Lua中的表的概念及其相关操作方法
- Lua编程示例(二):面向对象、metatable对表进行扩展
- 把Lua编译进nginx步骤方法
- Lua脚本自动生成APK包
- Lua中的元表(metatable)、元方法(metamethod)详解
- Lua中的metatable介绍
- Lua中ipair和pair的区别
- Lua中的函数精讲笔记
- 浅谈Lua的面向对象特性
- 详解Lua中的变量相关知识点
- Lua脚本语言入门笔记
- Lua脚本调用外部脚本
- 详解Lua中的if语句的使用方法
- Lua中调用函数使用点号和冒号的区别
- Lua中的闭合函数、非全局函数与函数的尾调用详解
- Lua中强大的元方法__index详解
- Lua中调用C++函数示例