JNI学习

JVM提供Java运行环境 (context.....)

JNIEnv提供Java与本地代码交互框架(JNIEnv是通过JVM创建的)

通过保存JVM,我们可以把新创建的本地游戏线程attach到JVM里面运行,

然后通过JNIEnv我们可以注册本地方法到JVM里面,也可以去查询Java里面的代码来实现真正的本地代码与Java代码交互


示例代码:

MainActivity.java

package com.example.jnistudy;

import android.support.v7.app.ActionBarActivity;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

	private Button mButton = null; 
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		runOnUiThread(new Runnable(){
			@Override
			public void run()
			{
				int i = 0;
				i++;
				System.out.println("UIThread i = " + i);
			}
		});
		
		Thread thread = new Thread(new Runnable(){
			@Override
			public void run()
			{
				int i = 0;
				i++;
				System.out.println("thread i = " + i);
			}
		});
		
		thread.start();
		
		 mButton = (Button)this.findViewById(R.id.button);
		 //按钮监听
		 mButton.setOnClickListener(new View.OnClickListener() 
		 {
			 @Override
			 public void onClick(View v) 
			 {
			 // TODO Auto-generated method stub
			 //调用JNI中的函数来启动JNI中的线程
				 mainThread();
			 }
		 });
		 //初始化JNI环境
		 setJNIEnv();
	}

	//由JNI中的线程回调
	private static void fromJNI(int i)
	{
		System.out.println("Java------>" + i);
	}
	//本地方法
	private native void mainThread();
	private native void setJNIEnv(); 

	static
	{
		//加载动态库
		System.loadLibrary("JNIThreads");
	}
}

JNI_Thread.cpp

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

#include<jni.h>
#include<android/log.h>

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))

//线程数
#define NUMTHREADS 5

//全局变量
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;

void *thread_fun(void* arg)
{
	 JNIEnv *env;
	 jclass cls;
	 jmethodID mid;

	 //Attach主线程
	 if(g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK)
	 {
		 LOGE("%s: AttachCurrentThread() failed", __FUNCTION__);
		 return NULL;
	 }
	 //找到对应的类
	 cls = env->GetObjectClass(g_obj);

	 if(cls == NULL)
	 {
		 LOGE("FindClass() Error.....");
		 goto error;
	 }
	 //再获得类中的方法
	 mid = env->GetStaticMethodID(cls, "fromJNI", "(I)V");
	 if (mid == NULL)
	 {
		 LOGE("GetMethodID() Error.....");
		 goto error;
	 }
	 //最后调用java中的静态方法
	 env->CallStaticVoidMethod(cls, mid ,(int)arg);

	 error:
	 //Detach主线程
	 if(g_jvm->DetachCurrentThread() != JNI_OK)
	 {
		 LOGE("%s: DetachCurrentThread() failed", __FUNCTION__);
	 }


	 pthread_exit(0);
}

extern "C" {
	//由java调用以创建子线程
	JNIEXPORT void Java_com_example_jnistudy_MainActivity_mainThread( JNIEnv* env, jobject obj)
	{
		 int i;
		 pthread_t pt[NUMTHREADS];

			__android_log_print(ANDROID_LOG_DEBUG, "JNIStudy",  "Java_com_example_jnistudy_MainActivity_mainThread called");

		 for (i = 0; i < NUMTHREADS; i++)
			 //创建子线程
			 pthread_create(&pt[i], NULL, &thread_fun, (void *)i);
	}
}

extern "C" {
	//由java调用来建立JNI环境
	JNIEXPORT void Java_com_example_jnistudy_MainActivity_setJNIEnv( JNIEnv* env, jobject obj)
	{
		 //保存全局JVM以便在子线程中使用
		 env->GetJavaVM(&g_jvm);
		 //不能直接赋值(g_obj = obj)
		 //get the reference of main class
		 g_obj = env->NewGlobalRef(obj);
	}
}


//当动态库被加载时这个函数被系统调用
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
{
	 JNIEnv* env = NULL;
	 jint result = -1;

	 //获取JNI版本
	 if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
	 {
		 LOGE("GetEnv failed!");
			 return result;
	 }

	 return JNI_VERSION_1_4;
}

Android.mk

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE    := JNIThreads
LOCAL_SRC_FILES := JNI_Thread.cpp
 
LOCAL_LDLIBS    := -llog
 
include $(BUILD_SHARED_LIBRARY)

运行结果:

Java_com_example_jnistudy_MainActivity_mainThread called
Java------>1
Java------>0
Java------>2
Java------>4
 Java------>3

从上面可以看出,新创建的子线程attach到主线程上在JVM里面运行就好比Java里面的多线程运行是竞争关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值