Wednesday, October 17, 2012

JNI learning: Basic


1, Java app code :

package test.sample.jni.run;

public class Sample {

static int staticint = 0;
String strField="default";
int intField=0;
public native int intMethod(int n);
public native boolean booleanMethod(boolean bool);
public native String stringMethod(String text);
public native int intArrayMethod(int[] intArray);
public native boolean callJavaMethod(String text);
public String callmethod(String c,int  a){

String s = "intput value is "+String.valueOf(a)+":"+c;
System.out.println(s);
return s;
}
public void perf()
{
System.out.println(this.intMethod(5));
boolean bool = this.booleanMethod(true);
this.callJavaMethod("abc");
for(int i=0 ; i<10000;i++)
//System.out.println(this.stringMethod("Java"));
this.callJavaMethod("abc");
int sum = this.intArrayMethod(new int[]{1,2,3,4});
System.out.println(this.strField+":"+this.intField);
}
/**
* @param args
*/
public static void main(String[] args) {
System.loadLibrary("sample");
for(int j= 0 ; j < 10; j++){
new Sample().perf();
}
}
}

2. Native library header file

javah test.sample.jni.run.Sample at bin folder. there will be following .h generated:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class test_sample_jni_run_Sample */

#ifndef _Included_test_sample_jni_run_Sample
#define _Included_test_sample_jni_run_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     test_sample_jni_run_Sample
 * Method:    intMethod
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intMethod
  (JNIEnv *, jobject, jint);

/*
 * Class:     test_sample_jni_run_Sample
 * Method:    booleanMethod
 * Signature: (Z)Z
 */
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_booleanMethod
  (JNIEnv *, jobject, jboolean);

/*
 * Class:     test_sample_jni_run_Sample
 * Method:    stringMethod
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_test_sample_jni_run_Sample_stringMethod
  (JNIEnv *, jobject, jstring);

/*
 * Class:     test_sample_jni_run_Sample
 * Method:    intArrayMethod
 * Signature: ([I)I
 */
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intArrayMethod
  (JNIEnv *, jobject, jintArray);

/*
 * Class:     test_sample_jni_run_Sample
 * Method:    callJavaMethod
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_callJavaMethod
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

3. Native library 

create one dll project and implement the header file with following c++ file:
//#include "stdafx.h"
#include "test_sample_jni_run_Sample.h"
#include <string.h>

JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intMethod
  (JNIEnv *env, jobject ojb, jint num){
 
 jclass cls = env->GetObjectClass(ojb);
 jfieldID intfid = env->GetFieldID(cls,"intField","I");
 if(intfid)
 {
 jint intvalue = (jint)env->GetObjectField(ojb,intfid);
 printf("intfield value is %d \n", intvalue);
 env->SetIntField(ojb,intfid,100);
 }
 return num * num;
  }
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_booleanMethod
  (JNIEnv *env, jobject ojb, jboolean boolean){
    return !boolean;
  }

JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_callJavaMethod
  (JNIEnv *env, jobject ojb, jstring string){

   jclass cls = env->GetObjectClass(ojb);
 
 jfieldID strfid = env->GetFieldID(cls,"strField","Ljava/lang/String;");
 //call java method
 jmethodID mid = env->GetMethodID(cls,"callmethod","(Ljava/lang/String;I)Ljava/lang/String;");
 if (mid)
 {
 jstring inputS = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");  
 jint inputV = 1;
 jstring  strvalue = (jstring )env->CallObjectMethod(ojb,mid,inputS,inputV);
 const char *str;
 str = env->GetStringUTFChars(strvalue, 0);
 printf("call java method return value is %s \n", str);
 env->DeleteLocalRef(inputS);
 }
 return true;
}
JNIEXPORT jstring JNICALL Java_test_sample_jni_run_Sample_stringMethod
  (JNIEnv *env, jobject ojb, jstring string){
 
 jclass cls = env->GetObjectClass(ojb);
 
 jfieldID strfid = env->GetFieldID(cls,"strField","Ljava/lang/String;");
 //call java feild
 if(strfid)
 {
 jstring  strvalue = (jstring )env->GetObjectField(ojb,strfid);
 const char *str;
 str = env->GetStringUTFChars(strvalue, 0);
 printf("strField value is %s \n", str);
 strvalue = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");  
 env->SetObjectField(ojb,strfid,(jobject)strvalue);
 env->DeleteLocalRef(strvalue);
 }

 //call java method
 jmethodID mid = env->GetMethodID(cls,"callmethod","(Ljava/lang/String;I)Ljava/lang/String;");
 if (mid)
 {
 jstring inputS = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");  
 jint inputV = 1;
 jstring  strvalue = (jstring )env->CallObjectMethod(ojb,mid,inputS,inputV);
 const char *str;
 str = env->GetStringUTFChars(strvalue, 0);
 printf("call java method return value is %s \n", str);
 env->DeleteLocalRef(inputS);
 }


 //return str;

 const char *str = env->GetStringUTFChars(string, 0);
 char cap[128];
 strcpy(cap, str);
 env->ReleaseStringUTFChars(string, str);
 return env->NewStringUTF(strupr(cap));
  }
  
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intArrayMethod
  (JNIEnv *env, jobject obj, jintArray array) {
    int i, sum = 0;
    jsize len = env->GetArrayLength(array);
    jint *body = env->GetIntArrayElements(array, 0);
    for (i=0; i<len; i++)
    {
      sum += body[i];
    }
    env->ReleaseIntArrayElements(array, body, 0);;// avoid mem leaks
    return sum;
  }
  void main(){}

4. Java call native lib

place the native lib to the class path at Java application run time. and explicitly call system load like this: System.loadLibrary("sample"); //don't add extension.

5.Native Application call Java class

Project setting:
1. link following lib :
C:\Program Files (x86)\Java\jdk1.6.0_11\lib\jvm.lib
2. include following head file:
C:\Program Files (x86)\Java\jdk1.6.0_11\include;C:\Program Files (x86)\Java\jdk1.6.0_11\include\win32
3. add jvm.dll to dll search path by modify environment path :
C:\Program Files (x86)\Java\jdk1.6.0_11\jre\bin\client\jvm.dll


In the following source code, C++ create jvm and call the specified the java class:

#include <jni.h>
#include <string.h>
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif

static jmethodID gmid;

void checkGloabalMethod()
{
}
int main()
{

JavaVMOption options [1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean not;

options[0].optionString = "-Djava.class.path=.;C:/Users/jiali/Documents/Visual Studio 2010/Projects/sample/Debug";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);

if (status != JNI_ERR)
{
cls = env->FindClass("CalledbyNative");
if (cls)
{
jfieldID a = env->GetStaticFieldID(cls,"a","I");
if(a)
{
jint avalue = env->GetStaticIntField(cls,a);
printf("field a  value is %d \n",avalue);
}
mid = env->GetStaticMethodID(cls,"intMethod","(I)I");
gmid = (jmethodID)env->NewGlobalRef((jobject)mid);
if (mid)
{
square = env->CallStaticIntMethod(cls,mid,5);
printf("square is %d \n",square);
}
mid = env->GetStaticMethodID(cls, "booleanMethod","(Z)Z");
if(mid)
{
not = env->CallStaticBooleanMethod(cls,mid,1);
printf("Result of booleanmethod is %d \n",not);
}
}
status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);
square = env->CallStaticIntMethod(cls,gmid,6);
printf("square is %d \n",square);
jvm->DestroyJavaVM();
return 0;
}
return -1;
}





Tuesday, October 9, 2012

Tips OSGI and Decompile swf


OSGI:
1,install bundle:
install file:c:\net.adamsoftware.drive_4.0.0.jar
start bundleid

There is one tool called 'swfdump' at flex sdk folder.this tool can be used to show the swf info.