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)

大家都在看

  • Shell脚本监控线上端口服务是否正常开启

    前言: 线上服务正常可用是至关重要的,当正在运行的某个端口服务异常停止,我们期望定时脚本可以自动启动,而无需遇到问题再人为的启动。 例如:监听Mysql服务是否正常,我们通常的思路…

    Linux 2023年5月28日
    0107
  • html2canvas中toDataURL方法返回值为:data,解决方案

    | 0.35分钟 | 572字符 | 1、引言&背景 2、解决方案 3、声明与参考资料 | SCscHero | 2022/6/1 PM11:13 | 系列 | 已完成 每…

    Linux 2023年6月13日
    089
  • 我为儿子开发的第一款Android App,用于九九乘法练习

    用一天时间在macbook上安装好了Android Studio For Mac,注意dl.google.com只支持电信网络下载,家里宽带如果是移动或者联通的,使用AS下载And…

    Linux 2023年6月14日
    0101
  • docker:alpine使用logrotate切割日志

    最近在交付项目的时候使用了docker,大家都知道日志是项目定位问题的重要依据,但如果一开始项目本身没有对日志进行合理切割那就会导致长时间运行的项目日志文件大得编辑器打不开的情况。…

    Linux 2023年6月13日
    0100
  • Jq 手机端输入框防止底部菜单被小键盘弹起

    var winHeight = $(window).height(); //获取当前页面高度 $(window).resize(function () { var thisHeig…

    Linux 2023年6月7日
    091
  • Linux pssh安装与使用

    说明:我这是没有在密钥认证的情况下操作 1、安装pssh [root@libin ansible]# yum install -y pssh [root@libin ansible…

    Linux 2023年6月13日
    093
  • Linux下使用压力测试工具stress

    首先解压安装包到/usr/local/src/下 mv stress-1.0.4.tar.gz /usr/local/src​tar -zxf stress-1.0.4.tar.g…

    Linux 2023年6月13日
    093
  • Redis基础

    1.简介 Redis (远程字典服务器)是一 个开源的、使用C语言编写的NoSQL数据库。Redis基于内存运行并支持持久化,采用 key-value (键值对)的存储形式,是目前…

    Linux 2023年6月13日
    091
  • redis分享PPT材料

    上次在公司类做了一个redis分享,特别想把ppt上传上来,好像博客园不支持,那就截图把 1.简介 redis是什么: redis是一个nosql(not only sql不仅仅只…

    Linux 2023年5月28日
    080
  • 【Leetcode】64. 最小路径和

    给定一个包含非负整数的 m&#xA0;x&#xA0;n网格 grid,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动…

    Linux 2023年6月6日
    0105
  • 类成员变量的初始化

    1-1 类成员变量初始化的分类 类成员变量的初始化可简单分为两类:非静态成员变量的初始化(以下简称”普通初始化”)和静态成员变量的初始化(”静态…

    Linux 2023年6月8日
    0119
  • KVM 虚机镜像操作, 扩容和压缩

    qemu-img命令 创建镜像 qemu-img create 创建一个设备空间大小为10G的镜像 qemu-img create -f qcow2 centos7-guest.q…

    Linux 2023年5月27日
    088
  • 一文搞懂 Netty 发送数据全流程 | 你想知道的细节全在这里

    欢迎关注公众号:bin的技术小屋,如果大家在看文章的时候发现图片加载不了,可以到公众号查看原文 本系列Netty源码解析文章基于 4.1.56.Final版本 在《Netty如何高…

    Linux 2023年6月6日
    092
  • ulimit: open files: cannot modify limit: Operation not permitted

    统管理员刚给授权了一台Linux 服务器访问权限,我在JumpServer 登录的时候,遇到下面错误: Last login: Wed Nov 10 13:29:30 2021 f…

    Linux 2023年5月27日
    0126
  • python数据结构与算法(1)—时间复杂度

    一.数据结构基础 1.数据结构概念 就是一组数据在内存中的存储形式,也是对基本数据类型的一次封装 也是数据对象中数据元素之间的关系。 算法与数据结构的区别: 数据结构只是静态的描述…

    Linux 2023年6月6日
    080
  • Springboot整合redis

    原文链接:https://blog.csdn.net/SDDDLLL/article/details/103703627 去年学习的Redis,刚刚学习完就迫不及待的在实战中用了一…

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