java jwidnow_Java, JNI and Notepad++ Plugin

最近把之前写的 JsFormatter 用 Java 移植了一下,于是想着能不能用 JNI 作为包装,让 Notepad++ 的插件调用 Java 版的算法,于是有了下面的两个项目:

https://github.com/sunjw/JsToolJava

https://github.com/sunjw/JsFormatterJavaNppPlugin

先说一下怎么跑这个插件,将 JsFormatterJavaNppPlugin 编译得到的 JSMinJava.dll 放到 npp 的插件目录,之后将 JsToolJava.jar 和 commons-lang-2.6.jar 也放入插件目录,最后将 %JAVA_HOME%\bin\client 添加到 PATH 环境变量。这样应该就能运行 JSMinJava 插件,其中 JSFormat 功能就是用 JNI 调用 Java 执行的。这个在 npp 6.3, JRE 1.6 上测试成功,其他配置不一定能正常工作。

具体过程是这样的,首先通过 JNI 启动一个 JVM

JavaVMOption options[1];

JavaVMInitArgs vm_args;

long status;

options[0].optionString = "-Djava.class.path=.\\plugins\\JsToolJava.jar;.\\plugins\\commons-lang-2.6.jar";

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**)&jenv, &vm_args);

之后通过 JNI 找到 org.sunjw.jni.JsfJniWrapper 这个类,并创建实例,调用成员函数,将 c 语言表达的参数传入,之后得到返回的 Java String,并在转换回 c 语言的字符串。

jclass jcls = jenv->FindClass("org/sunjw/jni/JsfJniWrapper");

if(jcls != 0)

{

// We found class!

// Now, try to create an instance.

jobject jinstance = 0;

jmethodID jClsInit = jenv->GetMethodID(jcls, "", "()V");

if(jClsInit != 0)

{

jinstance = jenv->NewObject(jcls, jClsInit); // Create an instance

}

jmethodID jmid = jenv->GetMethodID(jcls,

"formatJs",

"(Ljava/lang/String;CIZZZ)Ljava/lang/String;");

if(jinstance != 0 && jmid != 0)

{

// We have instance and method!

string strJs(pJS);

strJs = utf8conv(strJs);

jstring jJsStr = jenv->NewStringUTF(strJs.c_str());

jchar jChIndent = struOptions.chIndent;

jint jnChPerInd = _nChPerInd;

jboolean jbPutCR = struOptions.bPutCR ? JNI_TRUE : JNI_FALSE;

jboolean jbNLBracket = struOptions.bNLBracket ? JNI_TRUE : JNI_FALSE;

jboolean jbIndentInEmpty = struOptions.bIndentInEmpty ? JNI_TRUE : JNI_FALSE;

jstring jretstr = (jstring)jenv->CallObjectMethod(

jinstance, jmid,

jJsStr, jChIndent, jnChPerInd, jbPutCR, jbNLBracket, jbIndentInEmpty);

const char *nativeString = jenv->GetStringUTFChars(jretstr, 0);

strJSFormat = (const char *)nativeString;

strJSFormat = asciiconv(strJSFormat);

jenv->ReleaseStringUTFChars(jretstr, nativeString);

jenv->DeleteLocalRef(jJsStr);

}

}

测试的时候发现貌似 Java 版的算法还比 Release 编译的 c++ 版算法更快一点,JRE 的 JIT 性能还是相当可以的。

续 ————————————

发现 Java 版的算法在特定的几个测试文件上稳定的快于 c++ 版后,开始着手研究这个问题。通过 Very Sleepy 这个 c++ profiler 发现问题在于,一个方便操作 stack 的函数中,声明的参数没有使用常量引用(const reference),导致 stack 被多次拷贝,将那个参数改成常量引用后,c++ 版的性能终于稳超 Java 版了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值