尽管IRIS和HealthConnect拥有全面的互操作特性,但在实际工作中,还是有可能遇到需要使用遗留类库,dll SDK等方式与外部应用通信的情况。例如IRIS中并没有内嵌国密算法SM2、SM3和SM4,而开源社区中不乏通过Java、Python和C++等语言完成的具体实现。本文就将以调用SM4的Java实现为例展示ObjectScript程序与第三方语言通信的过程。
Github地址:https://github.com/LinZhuISC/javademo.SM4
跨编程环境调用设计要点
在开始实际操作之前,希望读者先针对整个调用过程中的主调方和被调方思考两个现象:
- ObjectScript作为主调方,Java程序对它来说是个黑盒,它既不能直接访问Java虚拟机堆栈中的变量,也不能直接操纵被调代码的行为,例如限制内存使用、控制日志输出等。
- Java程序作为被调方,其设计目的是通过Java容器运行或被其他Java程序调用,开发过程中通常并不会考虑其自身如何与另一个语言环境交互,因此不能确保异常信息能被主调方捕获与跟踪。
针对这两个现象,开发者需要思考,在哪一侧需要做什么样的一些工作以便调用过程能够顺畅进行。
在这个背景下,当我们需要让ObjectScript与Java相互通信和调用时,就不得不解决几个技术问题:
- 两种体系结构间的数据类型如何相互转换: 例如Java的int类型在ObjectScript中能顺利转为int吗?正如32位系统的Java int等同于64位系统的Java int吗?或者Java中的String与ObjectScript中的String等价吗?
这是所有跨系统跨平台通信都会遇到的问题。比如32位的Java支持的int类型最大值比64位的Java要小得多,因此在大整型数的处理上,两者就会有不同。同理, ObjectScript中String的字符长度与Java中能支持的的String的最大长度也不同。因此,在构建跨技术平台调用时,需要有意识地进行类型转换和匹配。 - 两种语言通信,传输的到底是什么?
类型转换固然是一件繁琐而不怎么有趣的事,我们也可以从另一个方向思考。计算机通信的底层都是二进制数据流,并没有字符串和整型的区别。那么,在ObjectScript与Java进程通信的过程中,我们是否也可以直接进行二进制数据的传输,从而避免在一个运行时中去适配另一个运行时的数据类型? - 书写Java或.NET程序时不可避免地会引入大量的依赖(dependencies),如果不希望在ObjectScript这一侧来调试和验证classpath下包含所有依赖,那么在我们将Java程序打包时就需要处理这个问题——或把所有的依赖打在一个jar包里,或把所有依赖统一放在一个路径下供第三方调用。
- Java程序有bug怎么办?
事实上bug是不可避免的,那么当Java程序中的bug被触发的时候,开发者有没有办法从ObjectScript中来观察、定位和处理Java中的bug?参考上文主调方与被调方的特征,这显然不现实。因此,在Java程序中提供充足的异常捕获手段,在错误发生时记录日志以便在Java一侧还原、定位和解决问题,才能避免问题出现时被卡在两种语言之间不知从哪边着手的尴尬。
如上所述,大家在ObjectScript中应用Java程序时,通常不能期待对现存的Java程序不做任何改动即可顺