logo
25
3
WeChat Login

feature: Implement a new SM3MessageDigest with JIN and OpenSSL 3.5.0#12

Merged
created 2025-07-11
RhinoBird2025
maple-bird2025/TencentKona-17:250710
Edit
OverviewCommits
23
Files changed
11
Attachments

Project summary report

Project Goals

Use JNI and OpenSSL 3.5.0 to implement the new SM3MessageDigest, and improve the SM3 hash calculation performance while maintaining API compatibility

fixes #7

Work Completed

Renovate based on the original SM3MessageDigest.java. If OpenSSL can be used, OpenSSL is preferred. Otherwise, it falls back to the original pure Java implementation to achieve the effect of automatically switching between OpenSSL and pure Java implementation
Renovation details: Successfully use JNI to call OpenSSL 3.5.0, correctly implement the SM3 hash of the GB/T 32905-2016 standard, maintain the compatibility of the original MessageDigest API, and the OpenSSL implementation significantly improves performance

  • SM3MessageDigest.java --> Modified SM3 algorithm implementation, supports OpenSSL/pure Java dual backend
  • opensslsm3.c --> JNI implementation, calling OpenSSL EVP API
  • Lib.gmk --> Add corresponding build configuration
  • SM3ComparisonBenchmark.java -> 相应的JMH测试

7.17目前的优化完成工作

  • 资源管理: 长期持有native context + Cleaner → "create-use-destroy" 一次性模式
  • 数据处理: 分阶段native调用 → Java层累积 + 一次性native处理
  • 性能优化: 小数据/大数据分别优化 → 统一简化的处理流程
  • GC压力: 重量级Cleaner机制 → 轻量级Java对象管理

重构后,目前主要是减少了很多冗余代码,基于应用场景主要为每次都会创建新的MessageDigest实例,并不会复用实例。
所以基于用时创建,用完销毁的思想 -> 每次生成哈希时都要新创建ctx,哈希生成之后就立即释放它.

同时这种处理方式还有其他好处,每次调用都是完整的create→use→destroy,代表着是零native资源泄漏的。同时避免了繁杂的底层Context清除方法。
也减少了JNI的调用开销(多次->一次),进一步降低了gc压力,移除了复杂的状态管理和资源追踪。
在内存效率方面,使用ByteArrayOutputStream高效累积数据
有更清晰的异常信息和边界检查。

7.19的优化工作

  • 优化目前的架构,通过抽象接口,然后由纯Java实现和OpenSSL实现作为实现类。大大减少了原SM3MessageDigest的更改,采用策略模式,可以减少很多if-else。
  • 通过接入OpenSSLUtil类,可以运行时指定指定libcrypto的路径进行加载对应版本(但是要注意OpenSSL版本ABI兼容,就能正常工作)

7.22的优化工作

  • 再次优化架构,删除sm3包,规范类的可见范围
  • 优化SM2Engine和SM2KeyAgreement,不要直接实例化纯Java实现,直接实例化MessageDigest
  • 根据导师的其他修改意见进行了修改

7.25的优化工作

  • 再次优化架构,更改SM3Engine接口的访问级别为public,这样SM2Engine和SM2KeyAgreement就可以访问,且可以去除之前所捕获的异常
  • 为.c文件封装一个异常捕获函数,减少重复代码量
  • Lib.gmk文件优化成只有--with-openssl,如果不指定则无法使用openssl
  • 优化各个文件缺失的文件声明
  • 添加一个jtreg测试

以上更改均已通过测试

Code verification results

  • Independent compilation verification: JNI library compilation is successful
  • Functional verification: OpenSSL SM3 calculation is correct
  • Performance verification: significant performance improvement compared to pure Java implementation
  • Compatibility verification: keep the original API fully compatible

Performance improvement

根据附录的优化结果分析:
1.gc.time大大降低。(重点结果)

2.在吞吐量方面,优化后的吞吐量在某些场景要么略微下降(比如singleHash大数据块(1048576B)场景下),在其他场景则有显著上升(比如smallChunks)。

OpenSSL 实现总体上具有更高的吞吐量,并且在大多数情况下,GC分配速率、GC次数和GC时间都优于或接近纯Java 实现。具体来说:

吞吐量:OpenSSL 实现普遍表现出更高的吞吐量,尤其在处理大数据块时优势更为明显。
GC性能:虽然OpenSSL 实现的GC分配速率有时较高,但由于其较高的吞吐量和较短的GC时间,整体性能仍然优于纯Java 实现。
内存管理:OpenSSL 实现通常需要更多的内存分配,但通过减少GC停顿时间,使得其整体效率更高

Instructions

1.How to use

./configure autogen \
  --with-debug-level=release \
  --with-native-debug-symbols=internal \
  --with-jvm-variants=server \
  --enable-unlimited-crypto \
  --disable-warnings-as-errors \
  --with-toolchain-type=gcc \
  --with-boot-jdk=/usr/lib/jvm/java-17-openjdk-amd64 \
  --with-openssl=/usr \
  --with-jmh=/home/maple/kona-build/tencentkona-17/lib \
  --with-jtreg=/usr/share/jtreg
  1. Verify the build
# 构建微基准测试 JAR
make build-microbenchmark
# 使用 RunTests.gmk 运行微基准测试
make test TEST="micro:org.openjdk.bench.java.security.SM3ComparisonBenchmark" \
    MICRO="OPTIONS=-jvmArgs=-Djdk.openssl.cryptoLibPath=/usr/lib/x86_64-linux-gnu/libcrypto.so.3 -prof gc"
# 运行jtreg测试
make test TEST="jtreg:test/jdk/sm/sm3/NativeSM3Test.java"

这是7月17号的JMH测试附件
56e0b0a0-184b-45da-8230-2592da6db986.xlsx

openssl实现的gc.time可能有点异常,可能的原因有JMH测试每个方法都创建相关实例,没有复用,增加了gc压力。

7.17最新优化后的附件对比
极大优化了gc表现!

1ff43a0c-d4f7-4056-9591-d6d453bad827.xlsx

这里展示部分数据
纯Java实现数据:
20b22d63-c47a-407b-aa4b-126ad6d49d66.png

OpenSSL实现数据:
5c0a0746-9dfe-4aa1-ad7c-1304008bfae7.png

7.19最新优化表现
纯Java实现数据
8006d5ed-70ea-4816-b74e-25e6cb33c285.png

OpenSSL实现数据
e863eb26-8b25-45d5-8fde-c667cc59f270.png

实现附件如下
sheet2是OpenSSL实现
sheet3是纯Java实现的

f1c2db21-3337-4876-99aa-1866658aebb7.xlsx

administrator

需要JMH性能测试程序,并展示优化前后的性能对比。

administrator
bash configure \
--with-boot-jdk=/path/to/jdk17  \
--with-openssl-dir=/path/to/openssl \
--disable-warnings-as-errors

报错:

configure: error: unrecognized options: --with-openssl-dir
configure exiting with result code 1
reviewed
make/modules/java.base/Lib.gmk
jiangsha

以支持Linux(x86_64和aarch64)为主,不必支持Windows。

reviewed
test/micro/org/openjdk/bench/java/security/SM3ComparisonBenchmark.java
jiangsha

JMH会持续调用Benchmark方法,所以应该不需要在该方法内再多次调用digest了。

May

我想问这类测试应该放在test/micro/org/openjdk/bench/javax目录下还是test/micro/org/openjdk/bench/java目录下呢

jiangsha

也许直接修改test/micro/org/openjdk/bench/java/security/MessageDigests.java,让它支持SM3

reviewed
src/java.base/share/classes/sun/security/provider/SM3MessageDigest.java
jiangsha

如何考虑清除底层EVP_MD_CTX?

reviewed
src/java.base/share/native/libopensslsm3/opensslsm3.h
jiangsha

参考其它的JNI实现,是否有必要为JNI函数提供.h文件?

May

您的观点是什么呢

jiangsha

应该可以不提供header文件。OpenJDK在构建时会自动处理。

createor

抱歉误导了您,您应该使用以下命令来配置
./configure
--with-debug-level=release
--with-native-debug-symbols=internal
--with-jvm-variants=server
--enable-unlimited-crypto
--disable-warnings-as-errors
--with-toolchain-type=gcc
--with-boot-jdk=/usr/lib/jvm/java-17-openjdk-amd64

我新提交了commit:
1.使Lib.gmk支持Linux,去除多余的配置
2.修改了SM3ComparisonBenchmark
3.清除底层EVP_MD_CTX,防止内存泄漏

至于opensslsm3.h,如果您成功构建了JDK运行了JMH测试,我将移除它

关于Lib.gmk文件,我所做的issue里也要用到同样的OpenSSL3.5.0,如果您的版本可以成功支持Linux(x86_64和aarch64)的话,我想或许可以复用。

reviewed
make/modules/java.base/Lib.gmk
jiangsha

--with-openssl-dir还需要吗?
似乎没看到在哪里加入了这个配置?

maple

不好意思,您可以忽略它,这是我在之前的方案,忘记删去了,在最后的commit中我会将其删去

administrator

抱歉误导了您,您应该使用以下命令来配置
./configure
--with-debug-level=release
--with-native-debug-symbols=internal
--with-jvm-variants=server
--enable-unlimited-crypto
--disable-warnings-as-errors
--with-toolchain-type=gcc
--with-boot-jdk=/usr/lib/jvm/java-17-openjdk-amd64

我新提交了commit:
1.使Lib.gmk支持Linux,去除多余的配置
2.修改了SM3ComparisonBenchmark
3.清除底层EVP_MD_CTX,防止内存泄漏

至于opensslsm3.h,如果您成功构建了JDK运行了JMH测试,我将移除它

上面的命令没有引入OpenSSL,它是会使用系统默认安装的OpenSSL吗?
但我希望能够指定使用一个openssl的安装目录。

createor

上面的命令没有引入OpenSSL,它是会使用系统默认安装的OpenSSL吗?
但我希望能够指定使用一个openssl的安装目录。

@johnjiang 是的,使用的是系统的默认的openssl,但是我更新为了openssl 3.5.0了

createor

关于Lib.gmk文件,我所做的issue里也要用到同样的OpenSSL3.5.0,如果您的版本可以成功支持Linux(x86_64和aarch64)的话,我想或许可以复用。

@StephenSu 我没有看您的issue,您最好根据您自己的情况进行更改

administrator

@johnjiang 是的,使用的是系统的默认的openssl,但是我更新为了openssl 3.5.0了

从你修改的Lib.gmk来看,可以使用环境变量OPENSSL_HOME来设置。
不过,一般来看,还是希望支持参数--with-openssl

createor

从你修改的Lib.gmk来看,可以使用环境变量OPENSSL_HOME来设置。
不过,一般来看,还是希望支持参数--with-openssl

@johnjiang 如果要支持的话,是不是在make目录下新创建相关文件进行配置呢?然后更改Lib.gmk呢?

createor

@johnjiang 如果要支持的话,是不是在make目录下新创建相关文件进行配置呢?然后更改Lib.gmk呢?

我觉得我们可以一步步来进行改进,直到我们都乐于看见的结果。您可以先尝试用原命令来进行构建,然后进行JMH测试,如果符合相关指标,我们再进行下一步优化

administrator

@johnjiang 如果要支持的话,是不是在make目录下新创建相关文件进行配置呢?然后更改Lib.gmk呢?

这应该是需要的。
或者,目前先简单一些,先使用一个特别的环境变量,比如KONA_OPENSSL_HOME
因为系统(如我自己的系统)中可能已经设置了OPENSSL_HOME,使用KONA_OPENSSL_HOME可以与之区分开。

reviewed
test/micro/org/openjdk/bench/java/security/SM3ComparisonBenchmark.java
jiangsha

不太必要直接测试SM3Engine,尤其是还要使用反射这种形式,

maple

您觉得应该如何测试SM3Engine呢?是直接去掉吗?那应该如何进行纯Java的实现的SM3MessageDigest测试呢

jiangsha

目前的实现并没有同时支持纯Java实现与Native实现。
那么,可以在修改之前测试一次,修改后之后再测试一次。
然后比较两次测试的结果。

maple

您觉得先构造纯Java版本的实现的JDK(即./configure不带相应的--with-openssl-dir参数,也不要有相应的openssl环境),然后进行相应的JMH测试。再进行构造openssl版本的测试,然后再进行相同的JMH测试。这样就可以比较出两种结果,这种思路您觉得怎么样,要是符合我现在着手去办

jiangsha

我就是这个意思。

顺便问一下,支持OpenSSL的版本会包含OpenSSL的libcrypto.so吗?如果不包含的话,如何在运行时加载这个库?

maple

支持OpenSSL的JDK版本不会包含OpenSSL的libcrypto.so,而是在运行时动态加载系统已安装的OpenSSL库。
从Lib.gmk可以看出,OPENSSL_LIBS := -L/usr/lib -lssl -lcrypto,这表明JDK构建的libopensslsm3.so是动态链接到系统的OpenSSL库,而不是静态包含。

在SM3MessageDigest.java中,会加载我们构建的JNI库System.loadLibrary("opensslsm3");然后验证OpenSSL是否可用available = nativeSupportsSM3();

jiangsha

那么在构建JDK时并不会指定OpenSSL的本地安装目录?
也就是说,你既不会使用make选项--with-openssl-dir,也不会使用环境变量KONA_OPENSSL_HOME
但我不希望使用系统中的OpenSSL,因为其版本不可控。
而且也不灵活。比如,我可能会使用不同的OpenSSL 3.0+版本进行构建与测试。

maple

我稍后的commit会提供--with-openssl-dir这个选项,请等我更改完这个JMH测试类一并提交,抱歉

reviewed
test/micro/org/openjdk/bench/java/security/SM3ComparisonBenchmark.java
jiangsha

调用digest方法之后,是不是就应该自动reset了?
也就是说,可以直接进行下一次哈希生成。

maple

是的,我会进行修改

reviewed
test/micro/org/openjdk/bench/java/security/SM3ComparisonBenchmark.java
jiangsha

我觉得需要考虑测试一个完成的过程,包括创建MessageDigest实例。
也就是说,不复用MessageDigest实例,每次都在Benchmark方法内创建新的MessageDigest实例。
而且还要打开JMH的gc profiler,以观察GC时长。

maple

好的,我会按照这个思路进行改进

createor

在最新的commit中,提供了--with-openssl-dir支持和重构了JMH测试类

现在您可以通过这样来配置工具类来指定特定版本的openssl

在项目根目录执行

./configure autogen
--with-debug-level=release
--with-native-debug-symbols=internal
--with-jvm-variants=server
--enable-unlimited-crypto
--disable-warnings-as-errors
--with-toolchain-type=gcc
--with-boot-jdk=/usr/lib/jvm/java-17-openjdk-amd64
--with-openssl-dir=/usr

administrator

我刚才提交了如下的commit,
johnshajiang@3682ce31

它支持了在构建JDK时使用--with-openssl指定一个本地的OpenSSL目录。
并且提供了OpenSSLUtil用于帮助加载libcrypto.so。在运行时,需要使用系统属性jdk.openssl.cryptoLibPath去指定该文件的位置。
这样,你的PR只需要关注JNI部分,而不需要关注OpenSSL的加载了。

请先同步代码,然后再更新你的PR。

createor

或许JMH测试不用创建新的,直接在test/micro/org/openjdk/bench/java/security/MessageDigests.java的基础上,添加SM3即可进行测试,如果您接受的话我可以删去原来的JMH测试

administrator

或许JMH测试不用创建新的,直接在test/micro/org/openjdk/bench/java/security/MessageDigests.java的基础上,添加SM3即可进行测试,如果您接受的话我可以删去原来的JMH测试

还是需要一个新的JMH测试,需要把MessageDigest md = MesssgeDigest("SM3")也纳入测试中。

@Benchmark
public byte[] digest() throws Exception {
    MessageDigest md = MessageDigest.getInstance("SM3");
    return md.digest(MESSAGE);
}

在执行JMH测试时,需要观察一下GC状态。

administrator

我刚才提交了如下的commit,
johnshajiang@3682ce31

它支持了在构建JDK时使用--with-openssl指定一个本地的OpenSSL目录。
并且提供了OpenSSLUtil用于帮助加载libcrypto.so。在运行时,需要使用系统属性jdk.openssl.cryptoLibPath去指定该文件的位置。
这样,你的PR只需要关注JNI部分,而不需要关注OpenSSL的加载了。

请先同步代码,然后再更新你的PR。

之前忘记合并我的commit,刚才合并进去了。
9d01dbc6

createor

还是需要一个新的JMH测试,需要把MessageDigest md = MesssgeDigest("SM3")也纳入测试中。

@Benchmark
public byte[] digest() throws Exception {
    MessageDigest md = MessageDigest.getInstance("SM3");
    return md.digest(MESSAGE);
}

在执行JMH测试时,需要观察一下GC状态。

@johnjiang 我待会会把完整的JMH测试执行情况更新在上面的pr描述中

reviewed
src/java.base/share/classes/sun/security/provider/SM3MessageDigest.java
jiangsha

建议抽象出一个SM3Engine接口,然后会有一个纯Java实现的SM3EngineImpl,还有一个使用OpenSSL的NativeSM3Engine。
dataBuffer可以放到NativeSM3Engine中。
这样的话,SM3MessageDigest类的修改就会很小。

maple

好的

reviewed
src/java.base/share/classes/sun/security/provider/SM3MessageDigest.java
jiangsha

如何加载的OpenSSL libcrypto?
没看到使用我提供的OpenSSLUtil。

maple

由于前期开发的时候您还没有给出OpenSSLUtil,我采用了编译时动态链接的方法(Lib.gmk),这样JVM就可以自动加载对应的库依赖关系了。

# 从Lib.gmk可以看到完整的OpenSSL检测和链接过程
ifneq ($(KONA_OPENSSL_HOME),)
  OPENSSL_CFLAGS := -I$(KONA_OPENSSL_HOME)/include
  OPENSSL_LIBS := -L$(KONA_OPENSSL_HOME)/lib -lssl -lcrypto
else
  # 使用pkg-config检测系统OpenSSL
  OPENSSL_CFLAGS := $(shell pkg-config --cflags openssl)
  OPENSSL_LIBS := $(shell pkg-config --libs openssl)
endif

# 构建libopensslsm3.so,链接OpenSSL
$(eval $(call SetupJdkLibrary, BUILD_LIBOPENSSLSM3, \
    NAME := opensslsm3, \
    CFLAGS := $(CFLAGS_JDKLIB) $(OPENSSL_CFLAGS), \
    LIBS := $(OPENSSL_LIBS) $(LIBDL), \  # 这里链接了-lssl -lcrypto
))

我待会会同步成OpenSSLUtil的方式

jiangsha

由于JDK中没有OpenSSL的库文件,那么运行时,如何确保能够加载到OpenSSL的库?
是加载系统中标准路径下的OpenSSL库吗?
如果系统中没有安装OpenSSL,或者版本不合适呢?

maple

是加载系统中标准路径下的OpenSSL库吗?
如果系统中没有安装OpenSSL,或者版本不合适呢?

对的,所以有局限性。我会改成用OpenSSLUtil的方式,这样就可以指定相应的路径和版本了。

jiangsha

我目前的想法比较简单,就是不要依赖系统中的OpenSSL。
从现实来看,很多Linux系统并没有安装3.0+版本。
OpenSSLUtil中提供了一个系统属性jdk.openssl.cryptoLibPath,用于在运行时指定libcrypto的路径。

administrator

684c2011
上面的commit在test目录下增加了OpenSSL的crypto lib,可用于测试。

reviewed
src/java.base/share/classes/sun/security/provider/sm3/SM3Engine.java
jiangsha

不要增加包sm3,相关文件依然放在sun.security.provider中。

maple

好的,请您一并指出其他需要修改的地方,方便我一并修改

maple

相关文件依然放在sun.security.provider中

那么SM3EngineImpl,NativeSM3EngineImpl这两个类是不是应该要去掉public关键字

jiangsha

是的。
这也是为什么要把它们都放到一个包内,以避免声明为public,尽量减小可见的范围。

reviewed
src/java.base/share/classes/sun/security/provider/sm3/SM3Engine.java
jiangsha

该接口应该需要继承Cloneable,因为它也定义了clone方法。

reviewed
src/java.base/share/classes/sun/security/provider/sm3/impl/NativeSM3EngineImpl.java
jiangsha

一般地,使用super.clone()来创建被克隆的对象。

reviewed
src/java.base/share/classes/sun/security/provider/sm3/impl/SM3EngineImpl.java
jiangsha

sun.security.provider.SM3Engine应该被用于接口,而它原来的代码需要转到sun.security.provider.SM3EngineImpl中。

maple

意思是原来的sun.security.provider.SM3Engine应该修改为接口吗?

jiangsha

是的

reviewed
src/java.base/share/classes/sun/security/provider/sm3/impl/SM3EngineImpl.java
jiangsha

直接声明该方法会抛出CloneNotSupportedException会有影响吗?

maple

应该没影响,但是捕获并抛出有意义的信息可能会好一点(当然我也可以直接声明方法抛出对应异常)

jiangsha

这个异常本身应该就比较清晰了。

createor

意思是原来的sun.security.provider.SM3Engine应该修改为接口吗

现在有一个问题

// SM2Engine.java 和 SM2KeyAgreement.java
import sun.security.provider.SM3Engine;
private SM3Engine sm3 = new SM3Engine(); // 接口不能实例化

按这样的修改后,新的SM3EngineImplNativeSM3EngineImpl按道理也是无法工作的,需要修改SM2EngineSM2KeyAgreement等,使它们直接实例化OpenSSL实现或者纯Java实现,而且我们新修改的SM3EngineImplNativeSM3EngineImpl也需要改为public外部包的类才可访问

我觉得可以把相关的类,比如SM2EngineSM2KeyAgreement的实例化改为OpenSSL实现或者纯Java实现比较好

希望得到您的意见@johnjiang(jiangsha)

createor

或者可以回退到之前SM3MessageDigest两种实现并存的版本

administrator

现在有一个问题

// SM2Engine.java 和 SM2KeyAgreement.java
import sun.security.provider.SM3Engine;
private SM3Engine sm3 = new SM3Engine(); // 接口不能实例化

按这样的修改后,新的SM3EngineImplNativeSM3EngineImpl按道理也是无法工作的,需要修改SM2EngineSM2KeyAgreement等,使它们直接实例化OpenSSL实现或者纯Java实现,而且我们新修改的SM3EngineImplNativeSM3EngineImpl也需要改为public外部包的类才可访问

@cnb.acvgNwzIQGA
确实有这个问题。

我觉得可以把相关的类,比如SM2EngineSM2KeyAgreement的实例化改为OpenSSL实现或者纯Java实现比较好

让两个类不要直接使用Engine实现,而是使用MessageDigest实例,这样它们应该就被解耦了。

createor

最新的优化已经在pr表述呈现,请您再次review@johnjiang(jiangsha)

现在有一个问题

// SM2Engine.java 和 SM2KeyAgreement.java
import sun.security.provider.SM3Engine;
private SM3Engine sm3 = new SM3Engine(); // 接口不能实例化

按这样的修改后,新的SM3EngineImplNativeSM3EngineImpl按道理也是无法工作的,需要修改SM2EngineSM2KeyAgreement等,使它们直接实例化OpenSSL实现或者纯Java实现,而且我们新修改的SM3EngineImplNativeSM3EngineImpl也需要改为public外部包的类才可访问

我觉得可以把相关的类,比如SM2EngineSM2KeyAgreement的实例化改为OpenSSL实现或者纯Java实现比较好

希望得到您的意见@johnjiang(jiangsha)

@cnb.acvgNwzIQGA(maple) 但是这个是其他的issue的任务,我们应该用其他issue的同学做好的?

createor

但是这个是其他的issue的任务,我们应该用其他issue的同学做好的

我觉得这个更改是有必要的,改动SM3之后,应该要修复它涉及的问题。如果这个pr率先合并,其他issue的同学应该需要同步代码,解决代码冲突

我觉得这个更改是有必要的,改动SM3之后,应该要修复它涉及的问题。如果这个pr率先合并,其他issue的同学应该需要同步代码,解决代码冲突

@cnb.acvgNwzIQGA(maple) 所以还得先确定pr合并顺序再说🙏

createor

所以还得先确定pr合并顺序再说

对的,倘若导师先合并其他有相关文件的pr,这边也需要解决代码冲突才可以推进下一步

administrator

@cnb.acvgNwzIQGA(maple) @cnb.awOE5sooQFA(momo)
在现在工作中,文件冲突是不可避免的。
在OpenJDK社区中,经常会出现因为某个commit进入仓库之后,有些PR就显示存在文件冲突,导致该PR无法自动合入。
解决文件冲突本来就是开发的一部分。

👍

createor

还请您在空闲时间帮我review最新的commit@johnjiang(jiangsha)

@cnb.acvgNwzIQGA(maple) @cnb.awOE5sooQFA(momo)
在现在工作中,文件冲突是不可避免的。
在OpenJDK社区中,经常会出现因为某个commit进入仓库之后,有些PR就显示存在文件冲突,导致该PR无法自动合入。
解决文件冲突本来就是开发的一部分。

@johnjiang 好嘞,受教了

administrator
bash configure \
--with-boot-jdk=/data/home/johnsjiang/jdk/konajdk17  \
--with-jmh=build/jmh/jars \
--with-openssl=/path/to/openssl-3.5.0 \
--disable-warnings-as-errors

使用上面的配置构建JDK,make images时会遇到下面的错误,

Building target 'images' in configuration 'linux-x86_64-server-release'
Building OpenSSL SM3 with configured OpenSSL: /path/to/openssl-3.5.0
/usr/bin/ld: cannot find -lssl
/usr/bin/ld: cannot find -lcrypto
collect2: error: ld returned 1 exit status

请直接使用--with-openssl指定的OpenSSL,不要试图使用系统中的OpenSSL库。

createor

请直接使用--with-openssl指定的OpenSSL

您的这个--with-openssl=/path/to/openssl-3.5.0是绝对路径吗

administrator

您的这个--with-openssl=/path/to/openssl-3.5.0是绝对路径吗

是的

withdrew a comment.
withdrew a comment.
withdrew a comment.
createor
  --with-openssl=/usr \
  # ... 其他参数

您或许需要添加autogen。

bash configure autogen \
--with-boot-jdk=/data/home/johnsjiang/jdk/konajdk17 \
--with-jmh=build/jmh/jars \
--with-openssl=/path/to/openssl-3.5.0 \
--disable-warnings-as-errors
createor

在别的pr看到您的OpenSSL库文件目录是lib64,而非lib,我待会会推上一个新commit用来检测包括lib64和lib等其他可能目录

createor

现在您可以使用

bash configure autogen \
--with-boot-jdk=/data/home/johnsjiang/jdk/konajdk17 \
--with-jmh=build/jmh/jars \
--with-openssl=/path/to/openssl-3.5.0 \
--disable-warnings-as-errors

来配置,然后再使用make images构建新JDK了

administrator

在执行SM3ComparisonBenchmark时,有如下错误:

Failed to load OpenSSL libcrypto: java.lang.UnsatisfiedLinkError: no opensslcrypto in system library path: ...

能否让它用上test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so
请见类sun.security.util.OpenSSLUtil,可以通过系统属性jdk.openssl.cryptoLibPath指定OpenSSL libcrypto的路径。

createor

在执行SM3ComparisonBenchmark时,有如下错误:

Failed to load OpenSSL libcrypto: java.lang.UnsatisfiedLinkError: no opensslcrypto in system library path: ...

能否让它用上test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so
请见类sun.security.util.OpenSSLUtil,可以通过系统属性jdk.openssl.cryptoLibPath指定OpenSSL libcrypto的路径。

@johnjiang(jiangsha) 您目前使用

make build-microbenchmark

make test TEST="micro:org.openjdk.bench.java.security.SM3ComparisonBenchmark" \
    MICRO="OPTIONS=-jvmArgs=-Djdk.openssl.cryptoLibPath=/usr/lib/x86_64-linux-gnu/libcrypto.so.3 -prof gc"

这里的/usr/lib/x86_64-linux-gnu/libcrypto.so.3改为test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so不能使用吗

createor

注意这里的jdk.openssl.cryptoLibPath要是绝对路径。

make test TEST="micro:org.openjdk.bench.java.security.SM3ComparisonBenchmark" \
    MICRO="OPTIONS=-jvmArgs=-Djdk.openssl.cryptoLibPath=$(pwd)/test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so -prof gc"
administrator

我的意思是,能否自动地使用到那个库文件libopensslcrypto.so

在jtreg测试中,可以通过系统属性test.src获得测试文件所在的绝对路径,test.root可以获得测试根目录。
通过这些路径,可以间接地获取其它文件的路径。

不过,我不确定这些系统属性对于micro benchmark测试同样有效。
也许你可以试试。

createor

您是想实现这样的效果吗?

make test TEST="micro:org.openjdk.bench.java.security.SM3ComparisonBenchmark" \
    MICRO="OPTIONS=-jvmArgs=-prof gc"
createor

我用以下命令是可以成功运行的

make test TEST="micro:org.openjdk.bench.java.security.SM3ComparisonBenchmark" \
    MICRO="OPTIONS=-jvmArgs=-Djdk.openssl.cryptoLibPath=$(pwd)/test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so -prof gc"

您或许可以先尝试运行JMH测试,看看和我之前的测试的结果是否符合。

能否自动地使用到那个库文件libopensslcrypto.so?
在jtreg测试中,可以通过系统属性test.src获得测试文件所在的绝对路径,test.root可以获得测试根目录。
通过这些路径,可以间接地获取其它文件的路径

我觉得可能超出了目前的issue的范围了

createor

我觉得可能超出了目前的issue的范围了

我可能需要解释一下这句话的意思。在其他开源社区中,比如seata社区,每个pr需要专注于它所解决issue,如果验证了解决了该issue即可。如果要解决其他由该pr引出的问题,则需要另外提出一个pr来进行解决。

想得到您的意见❤️

administrator

那先不修改吧

我已经执行了那个JMH测试。

createor

那先不修改吧

我已经执行了那个JMH测试。

@johnjiang(jiangsha) 好的,期待您的其他意见❤️

reviewed
src/jdk.crypto.ec/share/classes/sun/security/ec/SM2Engine.java
jiangsha

由于这些异常处理,使我认为还是使用SM3Engine更好一些。
可以让SM3MessageDigest提供了一个方法,让它创建具体的SM3Engine的实现,SM3EngineImpl或NativeSM3Engine。

SM2KeyAgreement也同理处理。

maple

您的意思是像这样吗:在SM2KeyAgreement和SM2Engine中,通过SM3MessageDigest的新建的公有方法,直接获取SM3EngineImpl(我比较倾向于原来的纯Java实现)

maple

如果是通过SM3MessageDigest的新建的公有方法来创建SM3EngineImpl,是不是这个public方法为static好一些呢

jiangsha

是的,一个static方法。

reviewed
src/jdk.crypto.ec/share/classes/sun/security/ec/SM2Engine.java
jiangsha

如果使用SM3Engine,这里也不需要处理异常了。

reviewed
src/java.base/share/native/libopensslsm3/opensslsm3.c
jiangsha

可以定义一个函数用来抛异常。比如,像下面这样,

#define NULL_POINTER_EXCEPTION "java/lang/NullPointerException"

void throw_ex(JNIEnv *env, const char *exceptionName, const char *message) {
    jclass exceptionClazz = (*env)->FindClass(env, exceptionName);
    if (exceptionClazz != NULL) {
        (*env)->ThrowNew(env, exceptionClazz, message);
    }
}
reviewed
make/modules/java.base/Lib.gmk
jiangsha

目前没有依赖libssl,就不要加它了。

reviewed
make/modules/java.base/Lib.gmk
jiangsha

目前还是先做的简单一些。如果没有指定OpenSSL,也不要去搜索了。

maple

意思是只需要第一种KONA_OPENSSL_HOME的吗,其他全部去掉?

jiangsha

是的

reviewed
src/java.base/share/classes/sun/security/provider/NativeSM3EngineImpl.java
jiangsha

2025

reviewed
src/java.base/share/classes/sun/security/provider/NativeSM3EngineImpl.java
jiangsha

只有Java层源代码中的.java文件需要声明Classpath exception,其它文件是不能有这个声明的。
请参考test目录下的已有这类版本声明。

reviewed
administrator

需要增加一个测试程序,用于确保测试到Native SM3。
也就是说,这个测试需要使用到test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so

createor

需要增加一个测试程序,用于确保测试到Native SM3。
也就是说,这个测试需要使用到test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so

@johnjiang(jiangsha) 可以再详细解释一下是什么意思吗?目前新增的SM3ComparisonBenchmark不是可以使用test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so吗?而且也可以检测OpenSSL的可用性

administrator

我是说,加上jtreg测试,不是JMH的测试。
在目录test/jdk/sm/SM3/中加一个测试程序。要测试到Native SM3的实现。
为了能够测试到Native SM3,测试程序需要设置系统属性jdk.openssl.cryptoLibPath

下面的方法可以帮助这个测试程序获得文件test/jdk/openssl/lib/linux-x86_64/libopensslcrypto.so的路径。

public static String opensslCryptoPath() {
    String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT);
    String os = "unsupported";
    String ext = "unsupported";
    if (osName.contains("linux")) {
        os = "linux";
        ext = ".so";
    } else if (osName.contains("mac")) {
        os = "macos";
        ext = ".dylib";
    }

    String archName = System.getProperty("os.arch").toLowerCase(Locale.ROOT);
    String arch = "unsupported";
    if (archName.contains("x86_64") || archName.contains("amd64")) {
        arch = "x86_64";
    } else if (archName.contains("aarch64") || archName.contains("arm64")) {
        arch = "aarch64";
    }

    String platformName = os + "-" + arch;
    String libName = "libopensslcrypto" + ext;

    Path testRoot = Paths.get(System.getProperty("test.root"));
    Path libPath = testRoot.resolve("openssl").resolve("lib")
            .resolve(platformName).resolve(libName);
    return Files.exists(libPath) ? libPath.toString() : null;
}
createor

由于这些异常处理,使我认为还是使用SM3Engine更好一些。
可以让SM3MessageDigest提供了一个方法,让它创建具体的SM3Engine的实现,SM3EngineImpl或NativeSM3Engine。
SM2KeyAgreement也同理处理

如果按照这样的想法去做,也不能够完全去除捕获异常。原因在于SM3EngineImpl或NativeSM3Engine都是默认级别的访问。

假如在SM3MessageDigest.java 中添加静态方法

public static MessageDigest createPureJavaInstance() {
    SM3Engine engine = new SM3EngineImpl();
    return new SM3MessageDigest(engine);
}

在那两个类中则只能去除NoSuchAlgorithmException这个异常捕获,而不能去除DigestException的异常捕获。
用的还是digest(c3, 0, c3.length)这个方法,而不是纯Java实现的doFinal(),因为无法访问

期待您的建议@johnjiang(jiangsha)

administrator
public static SM3Engine newSM3Engine() {
    return isNativeSM3Supported() ? new NativeSM3Engine() : new SM3EngineImpl();
}

此时,SM3Engine接口需要是public。

withdrew a comment.
withdrew a comment.

Successfully merged and closed

Reviewer
(jiangsha)
Assignee
None yet
Label
None yet
Participant