node-java的使用及源码分析

上篇文章简单提了下node调用java的方法但也只属于基本提了下怎么输出helloworld的层度,这次将提供一些案例和源码分析让我们更好地了解如何使用node-java库。

前置知识:

1.桥接模式 http://c.biancheng.net/view/1364.html
2.nodejs和c++交互 http://nodejs.cn/api/addons.html
3.java和c++交互 https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html
4.大概了解classloader机制

node-java原理:

&#x901A;&#x8FC7;c++&#x6865;&#x63A5; [js <-> c++(v8&#x3001;jvm) <-> java(jar)] &#x7684;&#x65B9;&#x5F0F;&#x8C03;&#x7528;jar
</-></->

案例地址:

https://gitee.com/lablelan/nodejs_demo.git
&#x6E90;&#x7801;&#x5728;nodeJava&#x76EE;&#x5F55;

案例演示:

demo0
&#x901A;&#x8FC7;&#x521B;&#x5EFA;&#x5B50;&#x8FDB;&#x7A0B;&#x65B9;&#x5F0F;&#x8C03;&#x7528;jar
demo1
&#x8C03;&#x7528;jar&#x8F93;&#x51FA;hello world
demo2
node&#x8FDB;&#x7A0B;&#x7F16;&#x7801;&#x4E3A;base64&#x7531;jvm&#x89E3;&#x7801;&#x8FD4;&#x56DE;&#x7ED3;&#x679C;
demo3
&#x8C03;&#x7528;jar&#x91CC;&#x7684;&#x6D4B;&#x8BD5;&#x63A5;&#x53E3;&#x5BFC;&#x51FA;&#x6570;&#x636E;
demo4
&#x6A21;&#x62DF;jar&#x91CC;&#x7684;&#x6D4B;&#x8BD5;&#x63A5;&#x53E3;&#x5BFC;&#x51FA;&#x6570;&#x636E;
demo5
&#x4F7F;&#x7528;jar&#x5305;&#x5BFC;&#x51FA;100&#x4E07;&#x884C;&#x6570;&#x636E;&#x5230;&#x672C;&#x5730;
demo6
&#x4F7F;&#x7528;express&#x548C;excel-export&#x5305;&#x5BFC;&#x51FA;&#x6570;&#x636E;
demo7
&#x4F7F;&#x7528;easyexcel&#x7684;jar&#x5305;&#x5BFC;&#x51FA;&#x6570;&#x636E;
demo8
&#x4F7F;&#x7528;promise&#x65B9;&#x5F0F;&#x5BFC;&#x51FA;&#x6570;&#x636E;
demo9
&#x8C03;&#x7528;sm4(&#x56FD;&#x5BC6;)&#x7684;jar&#x52A0;&#x89E3;&#x5BC6; https://www.javajike.com/book/hutool/chapter8/eb920b20c199717f34f28a89fcf6d620.html
demo10
&#x5C06;&#x4E1A;&#x52A1;&#x8DD1;&#x5728;worker&#x7EBF;&#x7A0B;&#x4E0A;

用到的jar包源码:

easyexcel: https://github.com/alibaba/easyexcel
utils: ./java/Util
myutils: ./java/myutils

node-java源码:

https://github.com/joeferner/node-java

核心源码目录:

.
&#x251C;&#x2500;&#x2500; index.js
&#x251C;&#x2500;&#x2500; lib
&#x2502;   &#x2514;&#x2500;&#x2500; nodeJavaBridge.js # index.js&#x5165;&#x53E3;&#x8FD9;&#x91CC;&#x5F00;&#x59CB;&#x521D;&#x59CB;&#x5316;java&#x5BF9;&#x8C61;
&#x2514;&#x2500;&#x2500; src
    &#x251C;&#x2500;&#x2500; java.cpp
    &#x251C;&#x2500;&#x2500; java.h # java&#x7C7B; &#x521D;&#x59CB;&#x5316;jvm&#x3001;&#x63D0;&#x4F9B;&#x4E00;&#x4E9B;&#x57FA;&#x7840;&#x7C7B;&#x578B;&#x5B9E;&#x4F8B;&#x5316;&#x63A5;&#x53E3;&#x548C;&#x8C03;&#x7528;&#x4EE3;&#x7406;
    &#x251C;&#x2500;&#x2500; javaObject.cpp
    &#x251C;&#x2500;&#x2500; javaObject.h # java&#x5BF9;&#x8C61;&#x4EE3;&#x7406; &#x6211;&#x4EEC;&#x7684;Sync&#x540E;&#x7F00;&#x7B49;&#x65B9;&#x6CD5;&#x5C31;&#x662F;&#x4ECE;&#x8FD9;&#x91CC;&#x88AB;&#x52A0;&#x8FDB;&#x5BF9;&#x8C61;&#x7684;&#x539F;&#x578B;&#x4E2D;
    &#x251C;&#x2500;&#x2500; javaScope.cpp
    &#x251C;&#x2500;&#x2500; javaScope.h # &#x7BA1;&#x7406;&#x5C40;&#x90E8;&#x5F15;&#x7528;&#x751F;&#x547D;&#x5468;&#x671F;
    &#x251C;&#x2500;&#x2500; methodCallBaton.cpp
    &#x251C;&#x2500;&#x2500; methodCallBaton.h # &#x7BA1;&#x7406;v8&#x548C;jvm&#x5BF9;&#x8C61;&#x5185;&#x5B58;&#xFF0C;&#x63D0;&#x5347;&#x5168;&#x5C40;&#x4F5C;&#x7528;&#x57DF;&#x7B49;
    &#x251C;&#x2500;&#x2500; nodeJavaBridge.cpp # &#x6865;&#x63A5;&#x66B4;&#x9732;&#x7ED9;v8
    &#x251C;&#x2500;&#x2500; node_NodeDynamicProxyClass.h # &#x52A8;&#x6001;&#x4EE3;&#x7406;&#x7C7B; &#x63D0;&#x4F9B;&#x591A;&#x7EBF;&#x7A0B;&#x529F;&#x80FD;
    &#x251C;&#x2500;&#x2500; utils.cpp
    &#x2514;&#x2500;&#x2500; utils.h # v8&#x548C;jvm&#x5BF9;&#x8C61;&#x8F6C;&#x6362;&#x5DE5;&#x5177;

带着问题去看源码:
1.如何查看一个对象的Java类型?

// Nan::SetPrototypeTemplate(funcTemplate, methodNameSync, methodCallSyncTemplate);
const ArrayList = java.import('java.util.ArrayList');
const arrayList = new ArrayList();
// 调用java的getClass方法可以获得类名称,这里的类名称被加工过,但可以大概看得出类路径
console.log(ArrayList, arrayList, arrayList.getClassSync())

2.如何知道对象/类有什么方法?

// 从源码上看可以得出java的方法会注入到原型中并带上后缀
const ArrayList = java.import('java.util.ArrayList');
const arrayList = new ArrayList();
console.log(arrayList.__proto__)

3.他是如何加载jar包的?

// 可以看出最终classpath会通过jni接口创建虚拟机时当做参数传入
Nan::SetAccessor(this->handle(), Nan::New("classpath").ToLocalChecked(), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter);
classPath << *arrayItemStr;
vmOptions[0].optionString = strdup(classPath.str().c_str());
args.options = vmOptions;
JNI_CreateJavaVM(&jvmTemp, (void **)env, &args);

4.对象的生命周期是什么样的?

When you call a Java method through node-java, any arguments (V8/JavaScript objects) will be converted to Java objects on the v8 main thread via a call to v8ToJava (found in utils.cpp). The JavaScript object is not held on to and can be garbage collected by v8. If this is an async call, the reference count on the Java objects will be incremented. The Java method will be invoked in a node.js async thread (see uv_queue_work). When the method returns, the resulting object will be returned to the main v8 thread and converted to JavaScript objects via a call to javaToV8 and the Java object's reference count will then be decremented to allow for garbage collection. The resulting v8 object will then be returned to the callers callback function.

5.java和js对象如何转换?

// utils.cpp上有两个函数进行对象转换
jobjectArray v8ToJava(JNIEnv* env, Nan::NAN_METHOD_ARGS_TYPE args, int start, int end);
jobject v8ToJava(JNIEnv* env, v8::Local arg);

6.为什么对象的方法会自动带上Sync?

// 在javaObject.cpp可以看到javaToV8时会将java类上的方法放到v8对象上,带Sync为运行在v8主线程上,不带Sync则放进workerQueue等待其他线程处理(需要回调)
const char* methodNameSync = methodNameSyncStr.append(java->SyncSuffix()).c_str();

ps:

1.&#x9879;&#x76EE;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; node-gyp rebuild &#x5BF9;c++&#x4EE3;&#x7801;&#x8FDB;&#x884C;&#x91CD;&#x65B0;&#x7F16;&#x8BD1;&#xFF0C;&#x5982;&#x9700;&#x91CD;&#x65B0;&#x7F16;&#x8BD1;&#x53EF;&#x4EE5;&#x6267;&#x884C; npm rebuild
2.&#x9047;&#x5230; java_dll_path.json &#x627E;&#x4E0D;&#x5230;&#x7684;&#x60C5;&#x51B5;&#x53EF;&#x4EE5;&#x5728; /node_modules/java &#x6267;&#x884C; node postInstall.js

Original: https://www.cnblogs.com/lablelan/p/15836882.html
Author: lable
Title: node-java的使用及源码分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/609876/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux虚拟机追加扩展磁盘

    一、使用VMware给虚拟机追加磁盘 使用VMware打开虚拟机设置对话框,选择硬盘,点击右侧的扩展按钮,输入扩展后的磁盘容量。 点击扩展按钮。提示磁盘已成功扩展。 二、对闲置的空…

    Linux 2023年6月6日
    0113
  • 2020年12月-第02阶段-前端基础-CSS Day06

    CSS Day06 定位(position) *理解 能说出为什么要用定位能说出定位的4种分类能说出四种定位的各自特点能说出我们为什么常用子绝父相布局 *应用 能写出淘宝轮播图布局…

    Linux 2023年6月8日
    0117
  • 03-MySQL事务

    数据库事务 1、事务特性 1.1、原子性 即不可分割性,事务要么全部被执行,要么就全部不被执行 1.2、一致性 事务的执行使得数据库从一种正确状态转换成另一种正确状态 1.3、隔离…

    Linux 2023年6月7日
    075
  • shell之磁盘容量检查,配合crontab可以定时清理磁盘

    我的做法: !/bin/bashAvailable=df -k | sed -n 2p | awk ‘{print $4}’if [ $Available -eq 0 ];then…

    Linux 2023年5月28日
    078
  • 函数指针的重要用途——回调函数

    什么是回调函数? 粗暴的说,如果一个函数作为另一个函数的参数传入,这种函数就可以称为回调函数(这句话并不严谨,但为了说明问题可以这么理解)。C语言里面,一般就是一个函数的参数列表中…

    Linux 2023年6月8日
    093
  • Linux 用户密码正确但无法登录和无法su问题故障

    一、 故障 描述 在应用登入操作系统时,用户密码正确但显示Permission denied无法登录,通过管理口控制台用root用户登录,也是同样情况,通过进入单用户查找问题。 一…

    Linux 2023年6月13日
    084
  • 【实测】Python 和 C++ 下字符串查找的速度对比

    最近在备战一场算法竞赛,语言误选了 Python ,无奈只能着手对常见场景进行语言迁移。而字符串查找的场景在算法竞赛中时有出现。本文即对此场景在 Python 和竞赛常用语言 C+…

    Linux 2023年6月13日
    0106
  • 高通平台如何避免误入FFBM模式

    前面两篇博客分别介绍了通过fastboot和QFIL工具退出FFBM模式的方法。虽然售后的同学可以这么指导用户做恢复,但步骤多操作也麻烦,且属于事后处理,如果大面积高概率地出现,会…

    Linux 2023年6月7日
    093
  • Python导入cx_Oracle报错

    系统环境:RHEL5.4 python2.5(手动编译安装,系统带有2.4版本) 在使用python脚本访问数据库时,需要导入cx_Oracle模块 $>>>im…

    Linux 2023年6月14日
    080
  • django基础

    目录 django三板斧 登录功能 静态文件 request对象方法 pycharm链接MySQL django链接MySQL django orm简介 orm基本使用 *orm数…

    Linux 2023年6月7日
    0106
  • Redis是如何实现高性能的?

    Redis到底有多快? redis到底有多快,可以通过 redis-benchmark 脚本进行基准测试。redis官方的性能基准测试报告 Redis为什么这么快? redis之所…

    Linux 2023年6月7日
    094
  • pod(二):创建包含多个容器的pod(sidecar)

    服务器版本 docker软件版本 CPU架构 CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64…

    Linux 2023年6月7日
    098
  • 关于 Promise 的一些简单理解

    一、ES6 中的 Promise 1、JS 如何解决 异步问题? (1)什么是 同步、异步?同步指的是 需要等待 前一个处理 完成,才会进行 下一个处理。异步指的是 不需要等待 前…

    Linux 2023年6月11日
    0105
  • VMware ESXi 7.0 U3 SLIC 2.6 & Unlocker 集成 Intel NUC 网卡、USB 网卡和 NVMe 驱动

    提供标准版和 Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科) 定制版镜像 请访问原文链接:VMware ESXi 7.0…

    Linux 2023年5月27日
    0153
  • powershell download, 兼容低版本 powershell

    powershell (new-object System.Net.WebClient).DownloadFile(‘文件url’,’保存路径’); Original: https…

    Linux 2023年5月28日
    0103
  • windows系统cmd切换盘符路径命令失效

    问题描述:比如当我在C盘想切换到D盘的某个文件夹路径下时 只是输出了那个路径 但是并没有真的切换 这时候需要再多操作一步就会成功了 Original: https://www.cn…

    Linux 2023年6月14日
    084
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球