Xinspace


  • 首页

  • 归档

  • 搜索

JNI技术解析第八章 JNI的其他特性

发表于 2015-05-27 | 分类于 Android

本章篇幅较长,需要多天完成。下面部分是05/27/15完成的。

 

本章主要讨论JNI的其他特性。

8.1 JNI和线程

Java虚拟机支持在同一个地址空间中控制多个线程并发执行。多线程比单线程有多大的复杂度,比如多个线程可能会同时访问一个对象,需要进行多线程的同步与互斥。在继续下面的讨论之前,你必须要懂Java多线程编程,懂得同步与互斥。

8.1.1 多线程的约束

阅读全文 »

JNI技术解析第七章 Java虚拟机的调用接口

发表于 2015-05-27 | 分类于 Android

本章篇幅较长,因此分为几天完成,下面是05/27/15完成的。

 

这一章介绍如何在原生应用中嵌入Java虚拟机。一个Java虚拟机的实现通常是一个原生库,原生应用就可以链接这个库,并且使用Java虚拟机的调用接口加载Java虚拟机。事实上,Java程序的启动命令”java”就是使用一个简单的C语言程序,链接了Java虚拟机实现库。这个命令分析命令行参数,使用虚拟机的调用接口加载Java虚拟机,运行Java程序。

7.1 创建Java虚拟机

阅读全文 »

Android Studio NDK开发第一章:安装与配置

发表于 2015-05-26 | 分类于 Android

1.安装

安装的教程网上一大片,不再敖述。安装步骤就是下载安装JDK、下载和安装Android Studio和SDK、下载安装NDK。

2.调整Android Studio的参数

打开Android Studio,在菜单栏File->Project Structure->SDK Location,填写正确的SDK安装目录和JDK的安装目录。如果已经填写好了,确认正确后保存即可。

3.安装SDK platforms

打开SDK Manager,在菜单栏Tools->Android->SDK Manager,自动从Google的网站上搜寻SDK Platfrom相关的下载包(需要翻墙)。建议只下载最新版本的SDK Platform与4.2的SDK Platform相关文件,其他的Platform按需下载。

阅读全文 »

JNI技术解析第六章 异常

发表于 2015-05-26 | 分类于 Android

前面几章也提到过在原生代码中对JNI函数调用后总会检查错误,如果有异常,则直接中断执行,直接返回。本章介绍在原生代码中检测错误并从异常中恢复。本章关注的异常处理是调用JNI函数之后产生的异常,而不是其他的异常。比如,在原生代码中使用了系统调用,那么对错误的处理就要遵循系统调用的规则;如果使用了Java API,那么就应该遵循Java的规则。本章值关注JNI函数对异常处理的规则。

6.1 概述

通过几个例子来介绍JNI提供的异常处理函数。

6.1.1 在原生代码中缓存并抛出异常

阅读全文 »

JNI技术解析第五章 局部引用和全局引用

发表于 2015-05-24 | 分类于 Android

由于本章篇幅太长,需要花费几天的时间才能介绍完。下面部分是05/18/15完成的。

JNI使用不透明引用来使用对象、数组(jobject、jclass、jstring、jarray等)。不透明引用屏蔽了JNI内部数据结构的实现细节,让程序员无需了解Java虚拟机中JNI的实现细节。原生代码不能直接通过不透明引用访问引用指向的内容,必须通过JNI函数来访问。

在JNI中,有三种不同的不透明引用:

1.局部引用、全局引用和弱全局引用。

2.局部引用在原生代码离开其作用于后被自动释放(很像C/C++中的局部变量,离开其作用域后自动销毁),全局引用和弱全局引用必须由程序员手动显式释放(很像C中的malloc与free,C++中的new与delete)。

3.局部引用和全局引用在其有效期间,其指向的对象可以不被垃圾回收机制回收。而弱全局引用在其有效期间则允许垃圾回收机制回收其指向的对象。

4.并不是所有的引用都能在任何上下文中被使用。比如当创建一个局部引用的原生代码返回值后,该局部引用就不能继续被使用了,否则不合法。

本章对这三种引用着重介绍。

阅读全文 »

JNI技术解析第四章 访问类成员变量和成员方法

发表于 2015-05-17 | 分类于 Android

由于篇幅较长,因此可能要花好几天才能写完这一章。下面这一部分是05/14/2015完成的。

这一章介绍访问任意对象的成员变量和方法(调用Java中的方法就是从原生代码回调Java方法)。在后面的章节中也会介绍如何有效快速的进行访问。

4.1 访问类成员变量

Java的类含有两种成员变量:静态成员变量和非静态成员变量。

我们首先介绍如何读取/修改非静态成员变量。

4.1.1 访问非静态成员变量

下面看一个简单的访问类成员变量的例子。

阅读全文 »

Android Studio无法启动AVD

发表于 2015-05-13 | 分类于 Android

在Android Studio中启动AVD的时候,出现了错误。

提示说在$ANDROID_AVD_HOME与$ANDROID_SDK_HOME/.android/avd路径中找不到创建的AVD。

然后,按照下图这样,选中创建好了的某个AVD,点击右边第三个按钮,选择View Details。android_studio_avd在弹出的详细信息框中,从上往下看,找到Path(应该是在第三行),这个Path说明了这个AVD存放在本地的哪个目录下。比如我的是/home/xxx/.android/avd/Nexus_5_API_17.avd。xxx是我的用户名,把它修改为自己的用户名就可以了。

阅读全文 »

在Android Studio中使用javah生成头文件

发表于 2015-05-12 | 分类于 Android

在开发NDK程序时,javah工具分析编译完成的使用了声明了原生代码的Java类文件(*.class),自动生成符合JNI规定的原生函数声明。如:


private native int func(int i);
经过javah命令分析后,自动生成的头文件包含其对应的声明为:
JNIEXPORT jint JNICALL Java_com_example_func_MainActivity_func(JNIEnv *, jobject, jint);
在Eclipse下,可以使用宏和系统环境变量等构件自动的工具,只需要点击这个自制的工具就能完成javah的命令。但是在Android Studio中,我目前还没有找到这种方法,只能打开Android Studio自带的Terminal,手动输入命令。假定我们创建的项目为Func, 在Android Studio的工作目录下,该项目的Java类的目录路径为Func/app/src/main/java/com/example/func/MainActivity.java,JNI代码的目录路径为Func/app/src/main/jni/func.cpp,Java类生成的类文件(*.class)路径为Func/app/build/intermediates/classes/debug/com/example/func/,Android SDK的支持jar包的路径在我的Mac上为/Users/my_name/Library/Android/sdk/platforms/android-21/android.jar,所以,进入Func/app/目录,执行javah命令:
javah -classpath ./build/intermediates/classes/debug/com/example/func:/Users/my_name/Library/Android/sdk/platforms/android-21/android.jar -jni -d ./src/main/jni -force com.example.func.MainActivity
命令中的参数都是上面假定的,根据个人的情况做相应的调整。其中 -classpath参数说明后面的字符串指定了本项目Java类文件(*.class)以及Java中使用到的如Activity等Android定义的组建的类文件的路径。
./build/intermediates/classes/debug/com/example/func:/Users/my_name/Library/Android/sdk/platforms/android-21/android.jar
阅读全文 »

JNI技术解析第三章 Java与C的基本类型、字符串和数组

发表于 2015-05-12 | 分类于 Android

第二章以一个非常简单的HelloWorld示例演示了使用JNI技术Java调用C,Java程序只是单纯的调用了C程序,C程序不接受任何参数(除了必须的JNIEnv和jobject外),也不提供返回值。但是,真实项目中很少有机会碰到这么简单的使用JNI的情况,大部分情况是C代码接受参数,也有返回值。这样就涉及到了两种语言之间不同类型的转换。如Java中int与C的int可能定义不同,String与char不同,数组也不同,因此,下面仍然结合示例程序,讲一下两种语言如何类型转换。在下面的讲解中,不会重复出现第二章中已经讲过的命令使用方法和配置环境变量等,如果需要请看第二章内容。本章只会贴出Java和C的源代码,并讲解其中的知识点,javac,javah,gcc等命令的用法不再出现。

本章使用到的函数可以在JNI函数列表页面详细了解函数原型、参数解释、返回值及注意事项等。本章只对函数的使用方法和重要的地方做介绍。

一、调用带参数和返回值的原生方法

这个示例程序中,原生方法的原型为:String getLine(String prompt);。Java提供一个字符串,调用getLine函数,该函数打印这个字符串,并从终端获取用户输入,返回给Java程序。结合这个例子,可以讲解Java与C转换字符串类型和基本类型。

阅读全文 »

JNI技术解析第二章 初探JNI

发表于 2015-04-23 | 分类于 Android

本文讲解一个简单的示例程序:在Java程序中调用原生方法,打印Hello World。让读者大概了解JNI编程的步骤。

对于本系列所有的示例程序,作者均在终端(Terminal)下编写、编译、调试和配置完成的。大家根据个人习惯进行编程。不过我还是说一下本人的编程环境:

1.Mac系统(之前用的Linux,不久前换了Mac,两个系统差不多),Windows系统没有实践过。

2.在执行命令之前,必须确定系统中已经安装了JDK最新版本,gcc和g++等工具。

3.编辑器是终端vim,大家根据习惯可以使用IDE或记事本等。

4.编译器在终端下用命令javac、javah、gcc/g++。

5.所有的配置(基本上是环境变量的设置)均在终端下完成,图形界面没有实践过。

下面提到的内容是用于达成共识:

1.执行命令时,我会这么写:$javac HelloWorld.java。其中’$’是终端命令提示符,不用用户输入,”javac HelloWorld.java”是需要用户输入的命令。

阅读全文 »
1…789…17

Xinspace

Personal blog from xin.

170 日志
6 分类
1 标签
© 2019 Xinspace
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4