安卓系统虚拟机原理 -- 初试DVM创建

本文介绍如何通过JNI在C程序中启动Java虚拟机并调用Java类的方法。具体步骤包括创建Java类、编译为class文件、编写C程序并调用Java方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


原文地址:http://dingran.iteye.com/blog/1694476

        在Android的世界中,由名称为app_process的C++本地应用程序(路径为:framework/base/cmds/app_process/app_main.cpp)调用JNI Invocation API 在自身进程中加载dalvikvm虚拟机,这样就开创了java世界.

        现在就简单的Demo一下这个原理,在Ubuntu11.10的终端中操作,已安装了jdk的条件。

 

1.首先创建一个工作目录:mkdir javaVMTest 

2.创建一个java文件,Called.java,内容:

 

 

Java代码 复制代码  收藏代码
  1. public class Called  
  2. {  
  3.     public static void main(String[] args)  
  4.     {  
  5.      // 把参数打印出来  
  6.     System.out.println(args[0]);    
  7.     }   
  8. }  
public class Called
{
    public static void main(String[] args)
    {
     // 把参数打印出来
    System.out.println(args[0]);

    }



}

 3.使用下面的命令将这个java文件编译为class文件,生成的class文件就在当前目录下: javac Called;

4.编写本地的C/C++程序,此处以C为例,名字为:invocationApi.c 

C代码 复制代码  收藏代码
  1. #include <jni.h>       /* where everything is defined */  
  2.   
  3. int main()  
  4. {  
  5.     JavaVM *vm;       /* denotes a Java VM */  
  6.     JNIEnv *env;       /* pointer to native method interface */  
  7.     JavaVMInitArgs vm_args; /* JDK 6 VM initialization arguments */  
  8.     JavaVMOption* options = new JavaVMOption[1];  
  9.     //options[0].optionString = "-Djava.class.path=/usr/lib/java";  
  10.     options[0].optionString = "-Djava.class.path=/home/joy/android4.0.3/external/javaVMTest";  
  11.     vm_args.version = JNI_VERSION_1_6;  
  12.     vm_args.nOptions = 1;  
  13.     vm_args.options = options;  
  14.     vm_args.ignoreUnrecognized = false;  
  15.   
  16.   
  17.   
  18.     /* load and initialize a Java VM, return a JNI interface  
  19.      * pointer in env */  
  20.     JNI_CreateJavaVM(&vm, (void**)&env, &vm_args);  
  21.     //delete options;  
  22.       
  23.     jclass cls = (*env).FindClass("Called");  
  24.     //printf("%p  %d %d\n",cls,size,a);  
  25.     printf("%p \n",cls);  
  26.     jmethodID mid = env->GetStaticMethodID(cls, "main""([Ljava/lang/String;)V");  
  27.   
  28.     jstring jstr = env->NewStringUTF("Hello JNI Invocation API !!!");  
  29.     jclass stringClass = env->FindClass("java/lang/String");  
  30.     jobjectArray args = env->NewObjectArray(1,stringClass,jstr);  
  31.   
  32.     env->CallStaticVoidMethod(cls, mid, args);  
  33.   
  34.   
  35.     /* We are done. */  
  36.     vm->DestroyJavaVM();  
  37.   
  38.     return 0;  
  39. #include <jni.h>       /* where everything is defined */
    
    int main()
    {
        JavaVM *vm;       /* denotes a Java VM */
        JNIEnv *env;       /* pointer to native method interface */
        JavaVMInitArgs vm_args; /* JDK 6 VM initialization arguments */
        JavaVMOption* options = new JavaVMOption[1];
        //options[0].optionString = "-Djava.class.path=/usr/lib/java";
        options[0].optionString = "-Djava.class.path=/home/joy/android4.0.3/external/javaVMTest";
        vm_args.version = JNI_VERSION_1_6;
        vm_args.nOptions = 1;
        vm_args.options = options;
        vm_args.ignoreUnrecognized = false;
    
    
    
        /* load and initialize a Java VM, return a JNI interface 
         * pointer in env */
        JNI_CreateJavaVM(&vm, (void**)&env, &vm_args);
        //delete options;
        
        jclass cls = (*env).FindClass("Called");
        //printf("%p  %d %d\n",cls,size,a);
        printf("%p \n",cls);
        jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
    
        jstring jstr = env->NewStringUTF("Hello JNI Invocation API !!!");
        jclass stringClass = env->FindClass("java/lang/String");
        jobjectArray args = env->NewObjectArray(1,stringClass,jstr);
    
        env->CallStaticVoidMethod(cls, mid, args);
    
    
        /* We are done. */
        vm->DestroyJavaVM();
    
        return 0;
    }

 5.因为在这个c文件中用到了JDK中虚拟机相关的共享库,所以需要先找到JDK中的头文件位置,下面的命令可以对JDK进行快速定位:

   which javac; 

   这样jdk的位置就能找到了,一般都在/usr/lib/jvm下 

   这里就用/usr/lib/jvm/java-6-sun-1.6.0.16/来代替。 


6.在上一步骤中确定了编译时需要用到的头文件的位置,但还要确定链接运行需要的共享库位置:libjvm.so 

  这个文件一般都在jdk路径下面的:/jre/lib/amd64/server或者是什么i386等等的,用find -name "libjvm.so"能很快找到。

 

7.配置编译时连接库,打开一个终端执行下列命令,输出一个链接环境变量:

export LD_LIBRARY_PATH=/usr/lib/jvm/java-6-sun-1.6.0.16 /jre/lib/amd64/server


8.在上述配置好了环境的终端中,执行下列命令进行编译: 

   g++ -I /usr/lib/jvm/java-6-sun-1.6.0.16 /include

      -I /usr/lib/jvm/java-6-sun-1.6.0.16 /include/linux -ljvm

      -L/usr/lib/jvm/java-6-sun-1.6.0.16 /jre/lib/amd64/server invocationApi.c

 

9.执行上述编译产生的目标文件,可以看到运行结果:./a.out 

   如果文件正确执行,可以在终端中看到如下字符串:

Hello JNI Invocation API !!!


总结,在上述步骤中,我们制作了一个class文件和一个C文件,C文件里调用JVM相关的JVM创建函数,创建了一个JVM虚拟机,然后并构造了恰当的参数,再调用JVM相关的class文件执行函数,执行编译好的class文件,最终得到我们想要的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值