首頁

2013年5月20日 星期一

**~原碼分享( 3 ).各式原碼**整列強陣^絕密分享**~


    **~原碼分享( 3 ).各式原碼**整列強陣^絕密分享*
*~


A.定制java虚拟机 *  (())* java,,*

  最近有网友问:如何让一个JAR文件随JVM启动时运行?java.exe是不能够做成这样的,不过可以自己定制java.exe,定制java.exe在如下情况有用:
1.不想程序的进程名显示为java.exe
2.希望程序双击就可以运行。
下面是一段示例代码:
[cpp] ))view plain **))copy +print=
  1. // JVM_CPP.cpp : Defines the entry point for the console application.   
  2. //   

  • #include "stdafx.h"   
  • #include "windows.h"   
  • #include <jni.h>   
  • typedef jint (JNICALL *JNICREATEPROC)(JavaVM**, void**, void*);  
  • bool setStream(JNIEnv* env, const char* pszFileName, const char* pszMethod);  
  • //启动java虚拟机方法   
  • bool startJvm()  
  • {  
  •     //jvm动态库的路径   
  •     const TCHAR szJvmPath[] = _T("E://java//jdk//jdk1.6.0//jre//bin//server//jvm.dll");  
  •     //java 虚拟机的启动参数,每个参数写一项,不能合在一起写   
  •     int nOptionCount = 2;  
  •     JavaVMOption options[2];  
  •     options[1].optionString = "-Xmx256M";  
  •     //设置classpath   
  •     options[0].optionString = "-Djava.class.path=./Test.jar;";  
  •     JavaVMInitArgs vm_args;  
  •     vm_args.version = JNI_VERSION_1_4;  
  •     vm_args.options = options;  
  •     vm_args.nOptions = nOptionCount;  
  •     vm_args.ignoreUnrecognized = JNI_TRUE;  
  •     //启动类,注意分割符是/,例如启动类test.JTest应该写成 test/JTest   
  •     const char szStartClass[] = "com/kortide/JVM/Test";  
  •     //启动方法,通常是main函数,你也可以设定成其他函数   
  •     const char szStartMethod[] = "main";  
  •     //重导向文件   
  •     const char* szStdoutFileName = "stdout.txt";  
  •     const char* szStderrFileName = "stderr.txt";  
  •     //java程序的命令行参数   
  •     int nParamCount = 2;  
  •     const char* szParams[2] =  
  •     {  
  •         "arg1""arg2"  
  •     };  
  •     //加载JVM。   
  •     HINSTANCE jvmDll = LoadLibrary(szJvmPath);  
  •     if (jvmDll == NULL)  
  •     {  
  •         printf("加载JVM动态库错误。%l", ::GetLastError());  
  •         return false;  
  •     }  
  •     //查找JNI_CreateJavaVM过程。   
  •     JNICREATEPROC jvmCreateProc = (JNICREATEPROC) GetProcAddress(jvmDll,  
  •                                                     "JNI_CreateJavaVM");  
  •     if (jvmCreateProc == NULL)  
  •     {  
  •         FreeLibrary(jvmDll);  
  •         printf("查找JNI_CreateJavaVM过程错误。%l", ::GetLastError());  
  •         return false;  
  •     }  
  •     //创建JVM。   
  •     JNIEnv* env;  
  •     JavaVM* jvm;  
  •     jint r = (jvmCreateProc) (&jvm, (void**) &env, & vm_args);  
  •     if (r < 0 || jvm == NULL || env == NULL)  
  •     {  
  •         FreeLibrary(jvmDll);  
  •         printf("创建JVM发生错误。");  
  •         return false;  
  •     }  
  •     //重导向stdout, stderr到输出文件   
  •     if (!setStream(env, szStdoutFileName, "setOut"))  
  •     {  
  •         printf("设置stdout输出文件失败");  
  •         return false;  
  •     }  
  •     if (!setStream(env, szStderrFileName, "setErr"))  
  •     {  
  •         printf("设置stderr输出文件失败");  
  •         return false;  
  •     }  
  •     //加载启动类。   
  •     jclass serviceClass = env->FindClass(szStartClass);  
  •     if (env->ExceptionCheck() == JNI_TRUE || serviceClass == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         FreeLibrary(jvmDll);  
  •         printf("加载启动类失败。");  
  •         return false;  
  •     }  
  •     //启动方法   
  •     jmethodID mid = env->GetStaticMethodID(serviceClass, szStartMethod,  
  •                             "([Ljava/lang/String;)V");  
  •     if (env->ExceptionCheck() == JNI_TRUE || mid == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         FreeLibrary(jvmDll);  
  •         printf("查找启动方法失败。");  
  •         return false;  
  •     }  
  •     //查找String类。   
  •     jclass stringClass = env->FindClass("java/lang/String");  
  •     if (env->ExceptionCheck() == JNI_TRUE || stringClass == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         FreeLibrary(jvmDll);  
  •         printf("查找String类失败。");  
  •         return false;  
  •     }  
  •     jstring jstr;  
  •     jobjectArray args = 0;  
  •     args = env->NewObjectArray(2, stringClass, 0);  
  •     for (int i = 0; i < nParamCount; i++)  
  •     {  
  •         jstr = env->NewStringUTF(szParams[i]);  
  •         if (jstr == 0)  
  •         {  
  •             printf("分配String失败/n");  
  •             if (env->ExceptionOccurred())  
  •             {  
  •                 env->ExceptionDescribe();  
  •                 env->ExceptionClear();  
  •             }  
  •             return false;  
  •         }  
  •         env->SetObjectArrayElement(args, i, jstr);  
  •         if (env->ExceptionCheck() == JNI_TRUE)  
  •         {  
  •             printf("设置参数失败/n");  
  •             if (env->ExceptionOccurred())  
  •             {  
  •                 env->ExceptionDescribe();  
  •                 env->ExceptionClear();  
  •             }  
  •             return false;  
  •         }  
  •     }  
  •     //调用启动类的启动方法启动Java程序   
  •     //env->CallStaticVoidMethod(serviceClass, mid, parameterArray);   
  •     env->CallStaticVoidMethod(serviceClass, mid, args);  
  •     if (env->ExceptionCheck() == JNI_TRUE)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         FreeLibrary(jvmDll);  
  •         return false;  
  •     }  
  •     return true;  
  • }  
  • //设置输出流的方法   
  • bool setStream(JNIEnv* env, const char* pszFileName, const char* pszMethod)  
  • {  
  •     int pBufferSize = 1024;  
  •     char* pBuffer = new char[pBufferSize];  
  •     //创建字符串对象。   
  •     jstring pathString = env->NewStringUTF(pszFileName);  
  •     if (env->ExceptionCheck() == JNI_TRUE || pathString == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("创建字符串失败。");  
  •         return false;  
  •     }  
  •     //查找FileOutputStream类。   
  •     jclass fileOutputStreamClass = env->FindClass("java/io/FileOutputStream");  
  •     if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamClass == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找FileOutputStream类失败。");  
  •         return false;  
  •     }  
  •     //查找FileOutputStream类构造方法。   
  •     jmethodID fileOutputStreamConstructor = env->GetMethodID(fileOutputStreamClass,  
  •                                                     "<init>",  
  •                                                     "(Ljava/lang/String;)V");  
  •     if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamConstructor == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找FileOutputStream类构造方法失败。");  
  •         return false;  
  •     }  
  •     //创建FileOutputStream类的对象。   
  •     jobject fileOutputStream = env->NewObject(fileOutputStreamClass,  
  •                                         fileOutputStreamConstructor, pathString);  
  •     if (env->ExceptionCheck() == JNI_TRUE || fileOutputStream == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("创建FileOutputStream类的对象失败。");  
  •         return false;  
  •     }  
  •     //查找PrintStream类。   
  •     jclass printStreamClass = env->FindClass("java/io/PrintStream");  
  •     if (env->ExceptionCheck() == JNI_TRUE || printStreamClass == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找PrintStream类失败。");  
  •         return false;  
  •     }  
  •     //查找PrintStream类构造方法。   
  •     jmethodID printStreamConstructor = env->GetMethodID(printStreamClass,  
  •                                                 "<init>",  
  •                                                 "(Ljava/io/OutputStream;)V");  
  •     if (env->ExceptionCheck() == JNI_TRUE || printStreamConstructor == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找PrintStream类构造方法失败。");  
  •         return false;  
  •     }  
  •     //创建PrintStream类的对象。   
  •     jobject printStream = env->NewObject(printStreamClass,  
  •                                 printStreamConstructor, fileOutputStream);  
  •     if (env->ExceptionCheck() == JNI_TRUE || printStream == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("创建PrintStream类的对象失败。");  
  •         return false;  
  •     }  
  •     //查找System类。   
  •     jclass systemClass = env->FindClass("java/lang/System");  
  •     if (env->ExceptionCheck() == JNI_TRUE || systemClass == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找System类失败。");  
  •         return false;  
  •     }  
  •     //查找System类设置方法。   
  •     jmethodID setStreamMethod = env->GetStaticMethodID(systemClass, pszMethod,  
  •                                         "(Ljava/io/PrintStream;)V");  
  •     if (env->ExceptionCheck() == JNI_TRUE || setStreamMethod == NULL)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("查找System类设置方法失败。");  
  •         return false;  
  •     }  
  •     //设置System类的流。   
  •     env->CallStaticVoidMethod(systemClass, setStreamMethod, printStream);  
  •     if (env->ExceptionCheck() == JNI_TRUE)  
  •     {  
  •         env->ExceptionDescribe();  
  •         env->ExceptionClear();  
  •         printf("设置System类的流失败。");  
  •         return false;  
  •     }  
  •     return true;  
  • }  
  • int _tmain(int argc, _TCHAR* argv[])  
  • {  
  •     startJvm();  
  •     return 0;  
  • }  

  •      ))上面的代码参考了《如何用C++自行加载Java虚拟机》 ****
    ****************************************

        B ).  如何用C++**)) 自行加载Java虚拟机 
     
        如何用C++自行加载Java虚拟机为什么要自己写C++程序加载Java虚拟机 
      通常情况下,我们完成了Java类的开发后,都是通过脚本调用Java的java.exe
    或者javaw.exe来启动Java虚拟机的,但在某些情况下,我们需要用C++程序来
    自行加载Java虚拟机运行我们的java程序,例如:
      1、 在windows上面运行时,你不想让那个恼人的DOS窗口出现,DOS窗口
    除了难看以外,对于服务器程序,有时这个DOS窗口是危险的,比如某个管理员
    不小心用鼠标点了一下DOS窗口的那个叉,或者为了拷贝什么东西按了
    一下Ctrl-C,都会把整个Java程序给终止掉。
      2、 你想把DOS窗口里面显示的内容记录到文件里面,以便你以后分析。
    这是个很有用的功能。通常很多异常堆栈,和系统发生的异常消息都是在DOS
    窗口中输出的,有时输出内容太多时,DOS窗口以前显示的内容就看不见了,
    DOS窗口关掉后,你也没法再看到以前显示的内容了。
      3、 在windows下面,你想把java程序做成一个后台服务,就像tomcat那样,
    这样就可以让windows操作系统帮你管理java程序的启动和停止了。
      4、 你在开发象IE这样的程序,在必要的时候才启动虚拟机运行一段Java程序 
       ** C++加载虚拟机的两种方法比较   ***
      
      加载虚拟机可以采用以下两种方法:
      1、 用创建子进程的方法调用java.exe来启动,在windows下面可以用  
    CreateProcess方法,在Linux下面可以用execvp方法,调用的方式和用脚本
    调用差不多,这种方法比较简单我就不详细介绍了,详细的方式可以参考
    开源项目 Java Service Wrapper。用创建子进程的方式用以下优点:
      1) 开发简单,兼容性好,对于java虚拟机的不同版本调用方式都是一样的
      2) 创建出来的java进程和C++程序的进程分离,不会相互影响,你不会因为
    C程序出现什么内存错误崩溃导致java进程也一起完蛋(当然分离进程也带来了
    其他问题,详见我后面的分析)。
      但是我不太喜欢这种方法,因为有以下缺点:
      1) 生成分离的java进程后,在系统里会看到另外一个java.exe的进程,
    当启动了很多这样的进程时,你会看到很多名称为java的进程,你无法区分
    哪个是哪个。
      2) 生成了分离的Java 进程后,你就不好对它进行控制,比如说要关
    闭它,如果直接kill掉java进程,可能java进程里面一些关闭时需要做的清理工作
    还来不及做。如果想让java程序执行清理工作再退出,你就需要建立和java程序
    之间的通讯机制,以向java程序发出退出的消息,这通常还需要在java程序里面
    加载专门的类,以及需要java程序的开发人员进行相关的接口开发工作。
      
      2、 加载java虚拟机的另外一种方法是加载jvm的动态库,并通过动态库的 
    接口来在本进程内启动java虚拟机。我更加喜欢这种方法,因为这种方法可以
    带来很多好处:
      1) 你可以更好地对java虚拟机进行有效地控制,java程序不需要加载 
    专门的类库,你只需要调用不同的java类方法就可以控制java程序的启动、 
    停止等操作 
      2) 不会产生额外的java进程,在系统进程中进程名称是你C++主程序的名字, 
    你可以在系统进程列表中很清楚地区分每个进程  
      当然这种方法也有缺点,但我认为不是大问题:
      1) 由于java虚拟机在进程内部加载,如果主程序写得不好而崩溃 
    会导致java程序也一起终止 
      2) 动态库接口得开发要稍微难一点,需要你了解jvm动态库的接口, 
    不过待会儿你就会看到,这也不是很困难的事情 
      3) jdk不同版本的接口稍微有一点区别,以后可能也会发生变化, 
    你可能得对不同的jdk版本修改一下C程序,但相对来说jvm的兼容性应该     
    是可以信任的  
      
      加载jvm动态库的方法介绍下面就详细介绍一下用C++程序加载动态库  
    的方法,我将分别针对windows平台和linux/unix平台分别进行介绍:
      windows平台的加载方法windows平台下jdk的java虚拟机动态库  
    为jvm.dll,位于:
      %JAVA_HOME%/jre/bin/client/jvm.dll  
      %JAVA_HOME%/jre/bin/server/jvm.dll  
      Jvm动态库有client和server两个版本,分别针对桌面应用和服务器应用做  
    了相应的优化,client版本加载速度较快,server版本加载速度较慢  
    但运行起来较快。
      虚拟机加载可按照以下步骤进行:
      1) 装载jvm动态库  
      2) 查找JNI_CreateJavaVM接口  
      3) 设置JVM启动参数,调用JNI_CreateJavaVM接口启动虚拟机  
      4) 查找启动类,设置命令行参数,设置窗口输出重导向文件  
      5) 调用启动类的启动方法启动java程序 
           6) 要停止Java程序运行时,调用java类的停止方法即可  

       下面的示例代码就说明了一个简单的加载过程
      typedef jint (JNICALL *JNICREATEPROC)(JavaVM **, void **, void *);
      bool setStream(JNIEnv *env, const char* pszFileName, const char* pszMethod);
      //启动java虚拟机方法
      bool startJvm()
      {
       //jvm动态库的路径
       const char szJvmPath[] = "c:\\jdk1.5.0_01\\jre\\bin\\server\\jvm.dll";
      
       //java 虚拟机的启动参数,每个参数写一项,不能合在一起写
       int nOptionCount = 2;
       JavaVMOption options[2];
       options[1].optionString = "-Xmx256M";
      //设置classpath
       options[0].optionString = "-Djava.class.path=./Test.jar;./Test1.jar";
      
       JavaVMInitArgs vm_args;
       vm_args.version = JNI_VERSION_1_4;
       vm_args.options = options;
       vm_args.nOptions = nOptionCount;
       vm_args.ignoreUnrecognized = JNI_TRUE;
      
       //启动类,注意分割符是/,例如启动类test.JTest应该写成 test/JTest
       const char szStartClass[] = "test/JTest";
       //启动方法,通常是main函数,你也可以设定成其他函数
       const char szStartMethod[] = "main";
      
       //重导向文件
       const char szStdoutFileName = "stdout.txt";
       const char szStderrFileName = "stderr.txt";
      
       //java程序的命令行参数
       int nParamCount = 2;
       const char *szParams[2] = {"arg1","arg2"};
      
       //加载JVM。
       HINSTANCE jvmDll = LoadLibrary(szJvmPath);
       if (jvmDll == NULL)
       {
       printf("加载JVM动态库错误。%l", ::GetLastError());
       return false;
       }
      
       //查找JNI_CreateJavaVM过程。
       JNICREATEPROC jvmCreateProc = (JNICREATEPROC)GetProcAddress(jvmDll, "JNI_CreateJavaVM");
       if (jvmCreateProc == NULL)
       {
       FreeLibrary(jvmDll);
       printf("查找JNI_CreateJavaVM过程错误。%l", ::GetLastError());
       return false;
       }
      
       //创建JVM。
       JNIEnv *env;
       jint r = (jvmCreateProc)(&jvm, (void **)&env, &vm_args);
       if (r < 0 || jvm == NULL || env == NULL)
       {
       FreeLibrary(jvmDll);
       printf( "创建JVM发生错误。");
       return false;
       }
      
       //重导向stdout, stderr到输出文件
      
       if (!setStream(env, szStdoutFileName, "setOut"))
       {
       printf("设置stdout输出文件失败");
       return false;
       }
      
       if (!setStream(env, szStderrFileName, "setErr"))
       {
       printf("设置stderr输出文件失败");
       return false;
       }
      
       //加载启动类。
       jclass serviceClass = env->FindClass(szStartClass);
       if (env->ExceptionCheck() == JNI_TRUE || serviceClass == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       FreeLibrary(jvmDll);
       printf("加载启动类失败。");
       return false;
       }
      
       //启动方法
       jmethodID mid = env->GetStaticMethodID(serviceClass, szStartMethod , "([Ljava/lang/String;)V");
       if (env->ExceptionCheck() == JNI_TRUE || mid == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       FreeLibrary(jvmDll);
       printf("查找启动方法失败。");
       return false;
       }
      
       //查找String类。
       jclass stringClass = env->FindClass("java/lang/String");
       if (env->ExceptionCheck() == JNI_TRUE || stringClass == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       FreeLibrary(jvmDll);
       printf("查找String类失败。");
       return false;
       }
      
       jstring jstr;
       for (int i=0; i<nParamCount; i++)
       {
       jstr = env->NewStringUTF(szParams[i]);
       if (jstr == 0) {
       printf("分配String失败\n");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       env->ExceptionClear();
       }
       return false;
       }
       env->SetObjectArrayElement(args, i, jstr);
       if (env->ExceptionCheck() == JNI_TRUE)
       {
       printf("设置参数失败\n");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       env->ExceptionClear();
       }
       return false;
       }
       }
      
       //调用启动类的启动方法启动Java程序
       env->CallStaticVoidMethod(serviceClass, mid, parameterArray);
       if (env->ExceptionCheck() == JNI_TRUE)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       FreeLibrary(jvmDll);
       return false;
       }
       return true;
      }
       //设置输出流的方法
      bool setStream(JNIEnv *env, const char* pszFileName, const char* pszMethod)
      {
       int pBufferSize = 1024;
       char* pBuffer = new char[pBufferSize];
       //创建字符串对象。
       jstring pathString = env->NewStringUTF(pszFileName);
       if (env->ExceptionCheck() == JNI_TRUE || pathString == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("创建字符串失败。");
       return false;
       }
       //查找FileOutputStream类。
       jclass fileOutputStreamClass = env->FindClass("java/io/FileOutputStream");
       if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamClass == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("查找FileOutputStream类失败。");
       return false;
       }
       //查找FileOutputStream类构造方法。
       jmethodID fileOutputStreamConstructor = env->GetMethodID(fileOutputStreamClass, "<init>", "(Ljava/lang/String;)V");
       if (env->ExceptionCheck() == JNI_TRUE || fileOutputStreamConstructor == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("查找FileOutputStream类构造方法失败。");
       return false;
       }
       //创建FileOutputStream类的对象。
       jobject fileOutputStream = env->NewObject(fileOutputStreamClass, fileOutputStreamConstructor, pathString);
       if (env->ExceptionCheck() == JNI_TRUE || fileOutputStream == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("创建FileOutputStream类的对象失败。");
       return false;
       }
       //查找PrintStream类。
       jclass printStreamClass = env->FindClass("java/io/PrintStream");
       if (env->ExceptionCheck() == JNI_TRUE || printStreamClass == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("查找PrintStream类失败。");
       return false;
       }
       //查找PrintStream类构造方法。
       jmethodID printStreamConstructor = env->GetMethodID(printStreamClass, "<init>", "(Ljava/io/OutputStream;)V");
       if (env->ExceptionCheck() == JNI_TRUE || printStreamConstructor == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("查找PrintStream类构造方法失败。");
       return false;
       }
       //创建PrintStream类的对象。
       jobject printStream = env->NewObject(printStreamClass, printStreamConstructor, fileOutputStream);
       if (env->ExceptionCheck() == JNI_TRUE || printStream == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("创建PrintStream类的对象失败。");
       return false;
       }
       //查找System类。
       jclass systemClass = env->FindClass("java/lang/System");
       if (env->ExceptionCheck() == JNI_TRUE || systemClass == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf( "查找System类失败。");
       return false;
       }
       //查找System类设置方法。
       jmethodID setStreamMethod = env->GetStaticMethodID(systemClass, pszMethod, "(Ljava/io/PrintStream;)V");
       if (env->ExceptionCheck() == JNI_TRUE || setStreamMethod == NULL)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("查找System类设置方法失败。");
       return false;
       }
       //设置System类的流。
       env->CallStaticVoidMethod(systemClass, setStreamMethod, printStream);
       if (env->ExceptionCheck() == JNI_TRUE)
       {
       env->ExceptionDescribe();
       env->ExceptionClear();
       printf("设置System类的流失败。");
       return false;
       }
      }
      Linux平台的加载方法Linux平台下的虚拟机的加载方法跟windows平台基本一致,不同的地方仅在于加载动态库的方法不同,在linux平台的JDK中,jvm动态库所在的路径为$JAVA_HOME/jre/lib/i386/client/libjvm.so
      
      $JAVA_HOME/jre/lib/i386/server/libjvm.so
      
      
      在Linux下装载动态库的示例代码如下:
      #include <jni.h>
      #include <stdlib.h>
      #include <dlfcn.h>
      typedef void* (*JNICREATEPROC)(JavaVM **, JNIEnv **, void *);
      bool startJVM() {
       JNIEnv *env;
       JavaVM *jvm;
       jclass cls;
       jmethodID mid;
       jobjectArray args;
       //jvm动态库的路径
       const char szJvmPath[] = "/usr/jdk1.5.0_01/jre/lib/i386/server/libjvm.so";
       //启动类
       const char szStartClass[] = "test/JTest";
       //启动方法
       const char szStartMethod[] = "main";
      
       //Java启动参数
       int nOptionCount = 2;
       JavaVMOption options[2];
       options[1].optionString = "-Xmx256M";
       options[0].optionString = "-Djava.class.path=./Test.jar;./Test1.jar";
       JavaVMInitArgs vm_args;
       vm_args.version = JNI_VERSION_1_4;
       vm_args.options = options;
       vm_args.nOptions = nOptionCount;
       vm_args.ignoreUnrecognized = JNI_TRUE;
       //命令行参数
       int nParamCount = 2;
       const char *szParams[2] = {"arg1","arg2"};
       //装载动态库
       void* lib_handle = 0;
       lib_handle = dlopen(szJvmPath, RTLD_NOW);
       if (!lib_handle)
       {
       fprintf(stderr, "dlopen failed\n");
       return false;
       }
      
       JNICREATEPROC lib_func = 0;
       //查找JNI_CreateJavaVM过程
       lib_func = (JNICREATEPROC)dlsym(lib_handle, "JNI_CreateJavaVM");
       lib_func(&jvm,&env,&vm_args);
       //后面与windows平台处理流程完全一样
       cls = env->FindClass(szStartClass);
       if (cls == 0) {
       fprintf(stderr, "Can't find class:%s\n",szStartClass);
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       return false;
       }
       mid = env->GetStaticMethodID(cls, szStartMethod,"([Ljava/lang/String;)V");
       if (mid == 0) {
       fprintf(stderr, "Can't find Method:%s\n",szStartMethod);
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       return false;
       }
       jclass stringClass = env->FindClass("java/lang/String");
       if (env->ExceptionCheck() == JNI_TRUE || stringClass == NULL)
       {
       fprintf(stderr, "find String class error");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       return false;
       }
       args = env->NewObjectArray(nParamCount, stringClass, NULL);
       if (args == 0) {
       fprintf(stderr, "Out of memory\n");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       return false;
       }
      
       jstring jstr;
       for (int i=0; i<nParamCount; i++)
       {
       jstr = env->NewStringUTF(szParams[i]);
       if (jstr == 0) {
       fprintf(stderr, "Out of memory\n");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       jvm->DestroyJavaVM();
       return false;
       }
       env->SetObjectArrayElement(args, i, jstr);
       if (env->ExceptionCheck() == JNI_TRUE)
       {
       fprintf(stderr, "set param error\n");
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       }
       jvm->DestroyJavaVM();
       return -1;
       }
       }
      
       env->CallStaticVoidMethod(cls, mid, args);
       if (env->ExceptionOccurred()) {
       env->ExceptionDescribe();
       return false;
       }
       return true;
      }
      参考资料1、 用创建子进程方式启动Java虚拟机的具体方法,可参考开源项目 Java Service Wrapper,http://wrapper.tanukisoftware.org
      2、 关于jvm动态库JNI方法的具体说明,参加SUN网站关于JNI的说明http://java.sun.com/j2se/1.4.2/docs/guide/jni/
      

    版权声明
      本文个人原创,未经本人允许不得转载、用於非法,只供參考交流之用^^~~謝謝~!*
     


      C ).  ). 

    在VS 2008下成功编译Chrome

     Chrome源码剖析    
    **** ))

       适合老版本的chrome编译,新版本的编译请看后面的文章
       源码之前了无秘密 - 侯捷的《STL源码分析》, 基于这个定义,
    个人将这句话稍作修改:“源码 + 调试”之前了无秘密。
    抱着研究的态度,今天用VC++ 2008编译了Chrome的源码 

    (现在机器上的VC++版本只剩2008了),现将编译流程描述如下:
    1. 用TortoiseSVN下载最新的Chrome源码,假设下载到了目录 
    “G:/Chrome/src/”下,以后的目录布局都基于这个假设 
    2. 准备Chrome依赖的源码
    a) 无需下载的
    编译时,Chrome依赖的第三方代码都应该在“G:/Chrome/src/src/third_party”
    ,但是很奇怪,Chrome将六个项目放在了“G:/Chrome/src/deps/third_party”下 
    。网上有同仁也提出了这个问题,他们的解决方法是将这六个项目copy一份  到“G:/Chrome/src/src/third_party”,相当管用。但本人本着节约型社会,
    硬盘虽大,仍需节省利用的原则,使用了微软的官方工具junction通过创建 
    软链接解决了这个问题,所使用命令如下
    (注意:命令是在目录G:/Chrome/src/下执行):
       junction src/third_party/icu38 G:/Chrome/src/deps/third_party/icu38
       junction src/third_party/cygwin G:/Chrome/src/deps/third_party/cygwin
       junction src/third_party/cygwin_src G:/Chrome/src/deps/third_party/cygwin_src
       junction src/third_party/python_24 G:/Chrome/src/deps/third_party/python_24
       junction src/third_party/WebKit G:/Chrome/src/deps/third_party/WebKit
       junction src/third_party/svn G:/Chrome/src/deps/third_party/svn
       junction的下载地址是
    http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx
    b) 需要重新下载的
    还有五个项目需要重新下载,分别是
    open-vcdiff,gtest,googleurl,v8,breakpad。
    利用TortoiseSVN下载open-vcdiff的地址是http://src.chromium.org/svn/branches/official/build_154.9/src/sdch
    下载到本地目录G:/Chrome/branches/build_154.9/src/sdch
    利用TortoiseSVN下载gtest的地址是http://googletest.googlecode.com/svn/trunk
    下载到本地目录G:/Chrome/gtest/trunk
    利用TortoiseSVN下载googleurl的地址是http://google-url.googlecode.com/svn/trunk
    下载到本地目录G:/Chrome/google-url/src
    利用TortoiseSVN下载v8的地址是http://v8.googlecode.com/svn/trunk
    下载到本地目录G:/Chrome/v8/trunk
    利用TortoiseSVN下载breakpad的地址是
    http://google-breakpad.googlecode.com/svn/trunk
    下载到本地目录G:/Chrome/google-breakpad/trunk
    创建软链接所使用命令如下:
          junction src/sdch/open-vcdiff ../branches/build_154.9/src/sdch/open_vcdiff/depot/opensource/open-vcdiff
          junction src/testing/gtest ../gtest/trunk
          junction src/googleurl ../google-url/src
          junction src/v8 ../v8/trunk
          junction src/breakpad/src ../google-breakpad/trunk/src
    c) 编译v8项目
    用VS 2008打开和编译G:/Chrome/v8/trunk/tools/visual_studio/v8.sln,
    打开时会提示你转换项目,直接转换,没有问题,编译后顺利的话应该在目录G:/Chrome/v8/trunk/tools/visual_studio/Debug/lib下生成v8.lib
    3. 修改Chrome项目
    a) 修改G:/Chrome/src/src/build/debug.vsprops,将
            
      Name="VCLinkerTool"
      LinkIncremental="2"
       />
    修改成
            
      Name="VCLinkerTool"
      LinkIncremental="2"
      AdditionalDependencies="$(SolutionDir)../v8/tools/visual_studio/Debug/lib/v8.lib"
        />
    b) 打开G:/Chrome/src/src/chrome/chrome.sln,
    将文件G:/Chrome/src/src/testing/gtest/src/gtest-test-part.cc文件添加到项目test/gtest中
    4. 开始编译吧 :),喝杯开水,看看paper,静候成功
    5. 运行G:/Chrome/src/src/chrome/Debug/chrome.exe看看编译的成果吧 :)

       Chrome源码剖析   
     **【序】 && 【一】
    开源是口好东西,它让这个充斥着大量工业垃圾代码和教材玩具代码的行业,
    多了一些艺术气息和美的潜质。它使得每个人,无论你来自米国纽约还是中国
    铁岭,都有机会站在巨人的肩膀上,如果不能,至少也可以抱一把大腿。。。
    现在我就是来抱大腿的,这条粗腿隶属于Chrome(开源项目名称其实是 
    Chromium,本来Chrome这个名字就够晦涩了,没想到它的本名还更上一层楼...)
    ,Google那充满狼子野心的浏览器。每一个含着金勺子出生的人都免不了
    被仰慕并被唾骂,Chrome也不例外。关于Chrome的优劣好坏讨论的太多了,
    基本已经被嚼成甘蔗渣了,没有人愿意再多张一口了。俗话说,内行看门道 
    外行看热闹,大部分所谓的外行,是通过使用的真实感受来评定优劣的,
    这无疑是最好的方式。但偏偏还是有自诩的内行,喜欢说内行话办外行事,
    一看到Chrome用到多进程就说垃圾废物肯定低能。拜托,大家都是搞技术的,
    你知道多进程的缺点,Google也知道,他们不是政客,除了搞个噱头扯个蛋就   
    一无所知了,人家也是有脸有皮的,写一坨屎一样的开源代码放出来遭 
    世人耻笑难道会很开心?所谓技术的优劣,是不能一概而论的,同样的技术 
    在不同场合不同环境不同代码实现下,效果是有所不同的。既然Chrome用了 
    很多看上去不是很美的技术,我们是不是也需要了解一下它为什么要用,
    怎么用的,然后再开口说话?(恕不邀请,请自行对号入座...)。。。
        
    关于Chrome的源码下载和环境配置,大家看这里(windows版本),
    只想强调一点,一定要严格按照说明来配置环境,特别是vs2005的补丁 
    和windows SDK的安装,否则肯定是编译不过的。。。
    最后,写这部分唯一不是废话的内容,请记住以下这幅图,这是Chrome    
    最精华的一个缩影,如果你还有空,一定要去这里进行阅读,
    其中重中之重是这一篇。。。
       原来Windows SDK Configuration tool 工具有一个Bug,具体请看:
    http://blogs.msdn.com/windowssdk/archive/2008/06/30/winsdk-bug-notification-sdk-config-tool-appears-to-work-but-fails.aspx
    二:开发环境准备完毕,接下来下载Chrome的源代码:
       1. 下载depot_tools_win.zip,下完解压到一个目录,假设解压后的目录是:C:/depot_tools。
       2. 把depot_tools的路径加入PATH环境变量:我的电脑|属性|高级|环境变量。
       3. 创建一个存放代码的文件夹,假设是:c:/trunk;运行cmd并将当前路径定位到该文件夹: cd c:/trunk。
       4. 在cmd里执行:gclient config http://src.chromium.org/svn/trunk/src
       5. 执行完后,再执行:gclient sync,此时就开始检出Chrome的代码,需要很长的时间。 经过很长的时间(我下载了3个小时左右),代码终于取下来了,现在开始构建:
       1. 打开c:/trunk/src/chrome/chrome.sln。
       2. 会看到app目录下有一个chrome_exe工程,构建它就行了。
    耐心地等待构建(我构建了1个半小时,看来我的本本性能还是不错的),幸运的话,目标文件会生成在:c:/trunk/src/chrome/debug
    详细编译访问见:http://sites.google.com/a/chromium.org/dev/developers/how-tos/build-instructions-windows
    三:关于chrome的内核引擎
        google chrome用的是WebKit内核引擎,看来firefox日子要开始不好过了。
    WebKit Open Source Project 内核引擎的前世今生
    WebKit 的前身是 KDE 小组的 KHTML。Apple将 KHTML 发扬光大,推出了装备 KHTML 改进型的 WebKit 引擎的浏览器 Safari,获得了非常好的反响。
    WebKit 引擎比 Gecko 引擎更受程序员欢迎的原因,除了其引擎的高效稳定,兼容性好外,其源码结构清晰,易于维护,是一个重要的原因。而 Gecko 的可维护性就差多了。我在 2008年6月时候,曾编译 Gecko 引擎,准备做一个基于 Gecko 的 Embed 应用程序,但文档缺乏、结构欠清晰,折腾了一星期之后,最终不得不承认自己水平有限,放弃了事。
    现在浏览器的内核引擎,基本上是三分天下:
    • Trident: IE 以Trident 作为内核引擎。
    • Gecko: Firefox 是基于 Gecko 开发。
    • WebKit: Safari, Google Chrome 基于 Webkit 开发。
    WebKit 内核在手机上的应用十分广泛,例如 Google 的手机 Gphone、 Apple 的 iPhone, Nokia’s Series 60 browser 等所使用的 Browser 内核引擎,都是基于 WebKit。
    下面是 WebKit 首页关于 WebKit 的介绍:http://www.xiaohui.com/dev/server/20080903-webkit-opensource-project.htm
    四:chrome涉及开源项目
      Google Chrome是一个优秀的开源的浏览器,其开发过程大量地使用了网上现在成熟稳定的开源代码,目前Chrome所涉及25个开源代码:
    1、Google Breakpad
    /src/breakpad
        开源的跨开台程序崩溃报告系统。
    2、Google URL
        /src/googleurl
         Google小巧的URL解析整理库。
    3、Skia
    /src/skia
        矢量图引擎。
    4、Google v8
        /src/v8
        Google开源的JavaScript引擎。V8实现了ECMA-262第三版的ECMAScript规范,可运行于Windows XP 和 Vista, Mac OS X 10.5 (Leopard), 及 Linux等基于IA-32 或 ARM 的系统之上。V8可单独运行也可嵌入到任何C++程序中。
    5、Webkit
    /src/webki
        开源的浏览器引擎
    6、Netscape Portable Runtime (NSPR)
    /src/base/third_party/nspr
        Netscape Portable Runtime (NSPR) 提供了系统级平台无关的API及类似libc的函数。
    7、Network Security Services (NSS)
    /src/base/third_party/nss
        Network Security Services (NSS) 一套用于支持服务器端与客户端安全开发的跨平台函数库。程序通过NSS可支持SSL v2 and v3, TLS, PKCS #5, PKCS #7, PKCS #11, PKCS #12, S/MIME, X.509 v3 认证及其它一些安全标准。
    8、Hunspell
    /src/chrome/third_party/hunspell
        Spell checker and morphological analyzer library and program designed for languages with rich morphology and complex word compounding or character encoding.
    9、Windows Template Library
    /src/chrome/third_party/wtl
        用于开发Windows程序与UI组件的C++ library。WTL扩展了ATL (Active Template Library) 并提供一套用于controls, dialogs, frame windows, GDI objects等开发的类。
    10、Google C++ Testing Framework
        /src/testing/gtest
        Google用于编写C++测试的基于xUnit架构的框架,可用于多种平台上:Linux, Mac OS X, Windows, Windows CE, and Symbian。支持自动测试发现,有一套丰富的Assertions断言,用于可自定义断言,death tests, fatal and non-fatal failures, various options for running the tests, and XML test report generation.
    11、bsdiff 与 bspatch
    /src/third_party/bsdiff /src/third_party/bspatch
        bsdiff 与 bspatch 用于为二进制文件生成补丁。
    12、bzip2
    /src/third_party/bzip2
        bzip2使用Burrows-Wheeler block sorting text compression 算法与Huffman编码压缩文件。
    13、International Components for Unicode (ICU)
        /src/third_party/icu38
        ICU是一套成熟并被广泛使用的C/C++ 及 Java 库,可为软件提供Unicode与全球化支持。
    14、libjpeg
    /src/third_party/libjpeg
        用于处理JPEG (JFIF)图像格式的库。
    15、libpng
    /src/third_party/libpng
        PNG图像格式库。支持绝大部分的PNG特性,可扩展。已经被广泛地使用了13年以上了。
    16、libxml
    /src/third_party/libxml
        C语言的XML解析库。
    17、libxslt
    /src/third_party/libxslt
        C语言的XSLT库。
    18、LZMA
    /src/third_party/lzma_sdk
        LZMA为7-Zip软件中7z格式压缩所使用的压缩算法,有很好的压缩效果。
    19、stringencoders
    /src/third_party/modp_b64
        一系列高性能的c-string转换函数,比如:base 64 encoding/decoding。通常比其标准实现快两倍以上。
    20、Netscape Plugin Application Programming Interface (NPAPI)
    /src/third_party/npapi
        多种浏览器使用的跨平台插件架构。
    21、Pthreads-w32
    /src/third_party/pthread
        用于编写多线程程序的API
    22、SCons - a software construction tool
    /src/third_party/scons
        开源的软件构建工具——下一代的编译工具。可以认为SCons是改进过的跨平台配上autoconf/automake与ccache的Make工具的子系统。
    23、sqlite
    /src/third_party/sqlite
        大名鼎鼎的嵌入式数据库引擎。自管理、零配置、无需服务器、支持事务。
    24、TLS Lite
    /src/third_party/tlslite
         SSL 3.0, TLS 1.0, and TLS 1.1的Python免费实现库。TLS Lite支持这些安全验证方式:SRP, shared keys, and cryptoIDs in addition to X.509 certificates。注:Chrome并不包涵Python。TLS Lite用于Chrome开发过程中的代码覆盖、依赖检查、网页加载时间测试及生成html结果比较等。
    25、zlib
    /src/third_party/zlib
        zlib为一套用于任意平台与机器的无损数据压缩的库,它免费、自由、无任何法律专利问题。
    五:文章链接
  • Chrome源码剖析
  • Google Chrome 的内核引擎 WebKit 介绍
  • WinSDK bug notification: SDK Config Tool appears to work but fails
  • Build Instructions (Windows)
  • cxjnet的专栏
    六:hrome相关链接
  • chromebbs
  • Chromium Blog
  • 谷歌Chrome中文站
  • 谷歌浏览器中文论坛
  •     Junction相当于linux下的ln命令,下面是Microsoft对其的介绍:
    Introduction   
       Windows 2000 and higher supports directory symbolic links, where a
    directory serves as a symbolic link to another directory on the computer.
    For example, if the directory D:/SYMLINK specified C:/WINNT/SYSTEM32
    as its target, then an application accessing D:/SYMLINK/DRIVERS would in
    reality be accessing C:/WINNT/SYSTEM32/DRIVERS. Directory symbolic
    links are known as NTFS junctions in Windows. Unfortunately, Windows
    comes with no tools for creating junctions—you have to purchase the Win2K
     Resource Kit, which comes with the linkd program for creating junctions.
    I therefore decided to write my own junction-creating tool: Junction. Junction
    not only allows you to create NTFS junctions, it allows you to see if files or
    directories are actually reparse points. Reparse points are the mechanism on which
    NTFS junctions are based, and they are used by Windows' Remote Storage
    Service (RSS), as well as volume mount points.
    Please read this Microsoft KB article for tips on using junctions.
    Note that Windows does not support junctions to directories on remote shares.
    If you want to view reparse information, the usage for Junction is the following:

    Using Junction  Use junction to list junctions:

    Usage: [-s] <directory or file name>
    -s    Recurse subdirectories
    Examples:
    To determine if a file is a junction, specify the file name:
    junction c:/test
    To list junctions beneath a directory, include the –s switch:
    junction -s c:/
    To create a junction c:/Program-Files for "c:/Program Files":
    C:/>md Program-Files
    C:/>junction c:/Program-Files "c:/Program Files"
    To delete a junction, use the –d switch:
    junction -d c:/Program-Files

    Download Junction
    (41 KB)

     
    ****待續.......**^ hehe..

    ))
    ))

    QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&



    沒有留言:

    張貼留言


    if you like make fds, wellcome you here~~anytime***

    my free place for everyones who want the good software,

    come & download them~ wellcome!!