精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Java運(yùn)行包精簡(jiǎn)探索

jf_ro2CN3Fa ? 來(lái)源:jianshu ? 2023-01-31 16:42 ? 次閱讀

背景如下:

> 最近由于某些原因,需要做一個(gè)自帶運(yùn)行環(huán)境的程序。由于各種原因,選定了 JavaPython 作為備選語(yǔ)言。但是 Java 由于 JRE 的臃腫(100M+)以及 Spring Boot 的日漸臃腫(helloworld 15M),需要在這兩方面進(jìn)行 size 的縮減。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

環(huán)境

系統(tǒng) :Ubuntu 16.04

GraalVM :GraalVM Community 21.3.0 (Based on OpenJDK 11.0.13)

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

環(huán)境準(zhǔn)備

關(guān)鍵配置

環(huán)境變量設(shè)置

exportJAVA_HOME=/path/to/
exportPATH=/path/to//bin:$PATH

安裝 native-image

guinstallnative-image

安裝 native-image 需要的組件

apt-getinstallbuild-essentiallibz-devzlib1g-dev

注意 :這里有個(gè)其他文章都沒有提到的坑。ld 需要更新到 2.26+,不然在構(gòu)建過(guò)程中會(huì)報(bào)告莫名其妙的異常(這里我耗了大半天)。

apt-getinstallbinutils-2.26

另一個(gè)坑

最開始我是在一臺(tái) aliyun 的機(jī)器上實(shí)驗(yàn)的,沒有注意到內(nèi)存問(wèn)題,在實(shí)驗(yàn)過(guò)程中遇到異常中斷。排查 syslog 發(fā)現(xiàn)是 OOMKiller。排查發(fā)現(xiàn)我的可用內(nèi)存只有 4G

后改為在本機(jī)機(jī)器 VMware 里的 Ubuntu 操作,內(nèi)存分配到 8G。經(jīng)觀察,native-image 打包過(guò)程中會(huì)用到 5.2G 左右的內(nèi)存,所以這里要注意一下。

至此,環(huán)境準(zhǔn)備完成。

打包

helloworld 的嘗試就跳過(guò)了,網(wǎng)上一搜一堆。先了解一下打包命令。

2fc54412-8bee-11ed-bfe3-dac502259ad0.png

項(xiàng)目依賴

3003537e-8bee-11ed-bfe3-dac502259ad0.png

主要用到了 solon、solon-api、h2、weed3、logback、slf4j、jlhttp 等包。

首先,通過(guò) Maven 把我的項(xiàng)目 solondemo 打包為可以運(yùn)行的 jar,確保通過(guò)。

java-jarsolondemo.jar

可以正常運(yùn)行并訪問(wèn)。然后把 solondemo.jar 上傳到前面準(zhǔn)備好的 GraalVM 環(huán)境。

首先,需要使用 GraalVM 提供的配置工具,對(duì)想要打包的程序的一些靜態(tài)分析無(wú)法分析到的信息進(jìn)行采集。

如果你確認(rèn)項(xiàng)目沒有使用任何反射、代理等特性,可以省略這一步。執(zhí)行

java-agentlib:native-image-agent=config-output-dir=./config/-jarsolondemo.jar

執(zhí)行后,最好能跑一跑 testcase,盡量保證代碼覆蓋率 100%,避免打包后遇到 classnotfound。

執(zhí)行完成后,終止執(zhí)行。

如果需要多次運(yùn)行采集信息 可以使用如下命令再次執(zhí)行,工具會(huì)自動(dòng)合并采集結(jié)果而不是覆蓋。

java-agentlib:native-image-agent=config-merge-dir=./config/-jarsolondemo.jar

執(zhí)行結(jié)束,config 下生成如下 5 個(gè)文件:

jni-config.json
predefined-classes-config.json
proxy-config.json
reflect-config.json
resource-config.json
serialization-config.json

坑又來(lái)了

根據(jù)網(wǎng)上的 說(shuō)法,可以通過(guò)指定 -H:ConfigurationFileDirectories=./config 的方式來(lái)使用前面生成的配置文件。

但是,最后老是會(huì)把 -H:ConfigurationFileDirectories= 認(rèn)為是指定的生成文件名,然而根據(jù)文檔,-H:Name=xxx 才是指定輸出文件名的參數(shù)

注意 :這個(gè)問(wèn)題是開始在 CentOS 上操作遇到的,最后我在 Ubuntu 上又嘗試用這種方式指定配置文件的時(shí)候,它生效了,原因未知。

我采用了另外一種配置方式。把這些文件打包到 jar 包的 META-INF/native-image 目錄下。

3016a712-8bee-11ed-bfe3-dac502259ad0.png

打包命令:

native-image-jarsolondemo.jar--allow-incomplete-classpath-H:+ReportExceptionStackTraces--enable-http

這個(gè)命令也是經(jīng)過(guò)反復(fù)多次嘗試最終得出的可用命令,嘗試的過(guò)程就略去3W字了。

注意 :如果你的應(yīng)用需要對(duì)外提供 HTTP 服務(wù),必須加上配置 --enable-http。如果提供 HTTPS 服務(wù),則必須加 --enable-https。否則哪怕運(yùn)行起來(lái)了訪問(wèn)也永遠(yuǎn)是 500。打包成功,目錄下生成 solondem 文件。

執(zhí)行運(yùn)行:運(yùn)行成功了,但是插件沒加載。翻閱 solon 源碼,發(fā)現(xiàn)插件加載的流程大致如下:

30311aa2-8bee-11ed-bfe3-dac502259ad0.png

通過(guò)反復(fù)添加日志排查,發(fā)現(xiàn):

在 graalvm native-image 下運(yùn)行,這里掃描到 META-INF/solon 這個(gè)目錄的 type,不是 file/jar,而是 resource。

304f28bc-8bee-11ed-bfe3-dac502259ad0.jpg

所以到了這里自然就無(wú)法遍歷目錄下的文件了。于是我嘗試讓 resource 類型也走 file 的方式去掃描。

3060731a-8bee-11ed-bfe3-dac502259ad0.png

調(diào)研搜索后發(fā)現(xiàn),GraalVM 內(nèi)部資源管理自己實(shí)現(xiàn)了一套 FileSystem,URL 描述符定義為 resource,有一套自定義的 API(由于時(shí)間有限,暫未深入研究)。

對(duì)本來(lái)是目錄類型的 resource 使用 File 方式去處理,得到的結(jié)果是 file not exists!但是對(duì)于確定的文件,是可以正常讀取的。

于是我考慮預(yù)處理,在 GraalVM 外面就先把能掃描到的文件清單提取出來(lái),通過(guò)配置的方式,插件掃描的時(shí)候直接返回預(yù)置的文件清單。

因?yàn)楸镜貓?zhí)行是可以正常掃描的,所以我在掃描結(jié)束的時(shí)候,增加一個(gè)輸出:

3077a008-8bee-11ed-bfe3-dac502259ad0.png

然后在配置中添加:

309a4e96-8bee-11ed-bfe3-dac502259ad0.jpg

scan 流程做如下修改

30a9125a-8bee-11ed-bfe3-dac502259ad0.png

插件掃描成功并運(yùn)行。

30bdc75e-8bee-11ed-bfe3-dac502259ad0.png

掃描注解也有同樣的問(wèn)題,排查過(guò)程與配置文件掃描類似,解決方案已與配置文件掃描的解決方案合并,略去 3萬(wàn)字。

至此,主框架已經(jīng)可以 run 起來(lái)了,但是嵌入式數(shù)據(jù)庫(kù) h2 還在作妖。

但是我嘗試按照他們說(shuō)的 使用 1.4.199 版本,卻仍然各種異常。沒辦法,下載 h2 源碼 加 log 排查吧。

30e7278e-8bee-11ed-bfe3-dac502259ad0.png

首先,這里報(bào)空指針,那么唯一的可能就是 defaultProvider 為空。分析 defaultProvider 初始化過(guò)程:

310c32ae-8bee-11ed-bfe3-dac502259ad0.png

發(fā)現(xiàn)了 Class.forName,以及吃掉了異常:

e.printStackTrace();

打包,再來(lái)運(yùn)行:

Causedby:java.lang.ClassNotFoundException
......
org.h2.store.fs.disk.FilePathDisk

好嘛。native-image 的 agent 居然沒有把這個(gè)掃出來(lái)。手動(dòng)把這些添加到 reflect-config.json 里面,再打包運(yùn)行。又報(bào)了個(gè)別的 class not found。再添加,再打包。

[
........,
{
"name":"org.h2.store.fs.FilePathDisk",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathMem",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathMemLZF",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathNioMem",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathNioMemLZF",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathNioMapped",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathAsync",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathZip",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathRetryOnInterrupt",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathNio",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.store.fs.FilePathSplit",
"methods":[{"name":"","parameterTypes":[]}]
},
{
"name":"org.h2.mvstore.db.MVTableEngine",
"methods":[{"name":"","parameterTypes":[]}],
"allDeclaredFields":true
}
]

成了!

312d7414-8bee-11ed-bfe3-dac502259ad0.png

訪問(wèn)接口、增刪改查、靜態(tài)頁(yè)面 、日志都 OK 了。

3179dd68-8bee-11ed-bfe3-dac502259ad0.png

幸福來(lái)得如此突然。

總結(jié)

最終可用的打包命令

native-image-jarsolondemo.jar--allow-incomplete-classpath-H:+ReportExceptionStackTraces--enable-http

ld 需要升級(jí)到 2.26+

root@ubuntu:/home/hx/graalvm/demo3#ld-version

GNUld(GNUBinutilsforUbuntu)2.26.1

Copyright(C)2015FreeSoftwareFoundation,Inc.
Thisprogramisfreesoftware;youmayredistributeitunderthetermsof
theGNUGeneralPublicLicenseversion3or(atyouroption)alaterversion.
Thisprogramhasabsolutelynowarranty.

其他注意事項(xiàng)

-agentlib:native-image-agent 不一定能檢查出所有的反射;

GraalVM 有自己的文件系統(tǒng)實(shí)現(xiàn),暫未找到遍歷目錄的方法;

第三方包不能運(yùn)行時(shí),大概率是由于反射沒有檢查到導(dǎo)致的 class not found;

排查第三方包問(wèn)題時(shí),一定要注意被吃掉的 Exception;

native-image 打包時(shí)需要 5G+ 內(nèi)存。

補(bǔ)充

1. native-image后序列化失敗問(wèn)題(比如 JSON.toJSONString(JavaBean))

fastjson1.2.68 版本下在程序啟動(dòng)時(shí)增加如下代碼:

ParserConfig.getGlobalInstance().setAsmEnable(false);
SerializeConfig.getGlobalInstance().setAsmEnable(false);

2. 反射方法報(bào)錯(cuò)

需將反射類手動(dòng)配置到 reflect-config.json 文件中,也可在編譯打包成 jar 時(shí)添加配置

-agentlib:native-image-agent=config-output-dir=../META-INF/native-image

后打包,然后 java -jar 或 java -cp 運(yùn)行起來(lái)后,執(zhí)行對(duì)應(yīng)測(cè)試用例后,會(huì)自動(dòng)將反射類信息生成到。

reflect-config.json 文件中(但真的不一定)。配置文件樣例:

[
{
"name":"com.test.A",
"allDeclaredFields":true,
"allPublicFields":true,
"queryAllPublicMethods":true,
"methods":[
{"name":"getA","parameterTypes":[]},
{"name":"getD","parameterTypes":[]},
{"name":"getF","parameterTypes":[]},
{"name":"getI","parameterTypes":[]},
{"name":"getQ","parameterTypes":[]},
{"name":"getR","parameterTypes":[]},
{"name":"getT","parameterTypes":[]},
{"name":"getY","parameterTypes":[]},
{"name":"getU","parameterTypes":[]},
{"name":"getV","parameterTypes":[]}
]
}
]

3. GraalVM 有自己的文件系統(tǒng)實(shí)現(xiàn)

暫未找到遍歷目錄的方法(即上文說(shuō)說(shuō)的).

如果你的程序中有涉及 ClassLoad.getResource("com.org") 這樣的代碼并打算對(duì)齊返回的結(jié)果以 File 或 jar 文件的方式掃描 com.org 下的所有類文件時(shí)會(huì)報(bào)錯(cuò)。

解決方式如上文所說(shuō),手動(dòng)配置需要掃描的類文件,然后讀取該配置(替代 getResource 方式)。

4. 控制 native 化后的二進(jìn)制程序內(nèi)存大小(配置參數(shù)不多說(shuō),一看就明白)

樣例:

./solondemo-Xmx16m-Xms16m-XX:MaxDirectMemorySize=8m






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • URL
    URL
    +關(guān)注

    關(guān)注

    0

    文章

    139

    瀏覽量

    15312
  • JAVA語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    138

    瀏覽量

    20076
  • HTTP協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    61

    瀏覽量

    9705
  • Ubuntu系統(tǒng)
    +關(guān)注

    關(guān)注

    0

    文章

    85

    瀏覽量

    3910
  • openjdk
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    2309

原文標(biāo)題:Java 運(yùn)行包精簡(jiǎn)探索(GraalVM)

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    java框架學(xué)習(xí)-Webwork2開發(fā)

    的wwexample中4:在WEB-INF中新建lib,把所有的jar包拷貝一份過(guò)去5:在Webwork-2.2.4發(fā)行包中找到taglib.tld,在/src/java/META-INF下面,拷貝到WEB-INF
    發(fā)表于 09-29 14:15

    [原創(chuàng)]java從代碼到運(yùn)行的過(guò)程

    java從代碼到運(yùn)行的過(guò)程 用一個(gè)圖來(lái)描述這個(gè)過(guò)程會(huì)比較容易理解:(鏈接地址:http://hiphotos.baidu.com/javass/pic/item
    發(fā)表于 10-31 11:44

    linux上的Java項(xiàng)目運(yùn)行

    有一次我發(fā)現(xiàn),沒有服務(wù)器的root 和數(shù)據(jù)庫(kù)的root,用sqlplus查詢的亂碼問(wèn)題實(shí)在是太難解決了,所以就采用了java的jdbc 的方法進(jìn)行查詢,但是我發(fā)現(xiàn)在linux上面運(yùn)行java 項(xiàng)目帶 jar包的那種真的有點(diǎn)麻煩,
    發(fā)表于 07-24 06:58

    nodejs與java的互調(diào)用方法

    nodejs 與java的互調(diào)用方法很多,我們可選的是使用oracle 新的vm 引擎(graalvm很不錯(cuò)) 還有就是基于browserify進(jìn)行包裝,同時(shí)給java 提供一套require
    發(fā)表于 11-04 07:31

    如何在嵌入式設(shè)備上運(yùn)行高性能Java

    如何在嵌入式設(shè)備上運(yùn)行高性能Java
    發(fā)表于 03-28 09:43 ?16次下載

    Java 運(yùn)行環(huán)境的安裝、配置與運(yùn)行

    Java 運(yùn)行環(huán)境的安裝、配置與運(yùn)行 一、實(shí)驗(yàn)?zāi)康?    1. 掌握下載 Java SDK 軟件包。    2. 掌握設(shè)
    發(fā)表于 09-23 18:56 ?1.1w次閱讀

    java參考大全

    對(duì)Java語(yǔ)言、庫(kù)及應(yīng)用程序進(jìn)行包括語(yǔ)法在內(nèi)的詳細(xì)介紹。我們將介紹Java語(yǔ)言產(chǎn)生的背景、發(fā)展過(guò)程,以及使它變得如此重要的原因。
    發(fā)表于 12-15 17:27 ?0次下載
    <b class='flag-5'>java</b>參考大全

    Java程序編譯和運(yùn)行的過(guò)程

    Java 虛擬機(jī)(JVM)是可運(yùn)行Java 代碼的假想計(jì)算機(jī)。只要根據(jù)JVM規(guī)格描述將解釋器移植到特定的計(jì)算機(jī)上,就能保證經(jīng)過(guò)編譯的任何Java代碼能夠在該系統(tǒng)上
    發(fā)表于 03-09 15:32 ?8858次閱讀

    Java程序是如何運(yùn)行

    ? JVM是Java運(yùn)行時(shí)虛擬機(jī),所有的Java程序都是在JVM沙箱中運(yùn)行,每個(gè)Java程序就是一個(gè)獨(dú)立的JVM進(jìn)程。 談到
    的頭像 發(fā)表于 12-27 09:31 ?1803次閱讀

    初學(xué)者:講解Java程序的開發(fā)與運(yùn)行原理

    可能剛剛接觸編程的初學(xué)者會(huì)發(fā)現(xiàn),編寫一個(gè)Java程序其實(shí)很簡(jiǎn)單,但是Java程序的運(yùn)行過(guò)程卻是非常復(fù)雜的。關(guān)于Java程序工作原理這部分知識(shí),雖然不要求編程學(xué)習(xí)者完全掌握,你但是至少需
    的頭像 發(fā)表于 08-13 15:01 ?3360次閱讀
    初學(xué)者:講解<b class='flag-5'>Java</b>程序的開發(fā)與<b class='flag-5'>運(yùn)行</b>原理

    CA850 Ver.3.20 C編譯器運(yùn)行包

    CA850 Ver.3.20 C編譯器運(yùn)行包
    發(fā)表于 05-04 19:03 ?0次下載
    CA850 Ver.3.20 C編譯器<b class='flag-5'>運(yùn)行包</b>

    eclipse怎么運(yùn)行java項(xiàng)目

    在Eclipse中運(yùn)行Java項(xiàng)目是非常簡(jiǎn)單的。下面了解一下如何在Eclipse中運(yùn)行Java項(xiàng)目。 首先,確保您已經(jīng)在Eclipse中創(chuàng)建了Jav
    的頭像 發(fā)表于 12-06 11:25 ?1953次閱讀

    eclipse設(shè)置java運(yùn)行環(huán)境

    在Eclipse中設(shè)置Java運(yùn)行環(huán)境是非常重要的,它能夠確保你的代碼能夠正確地編譯和運(yùn)行。下面介紹如何設(shè)置Java運(yùn)行環(huán)境。 下載和安裝J
    的頭像 發(fā)表于 12-06 11:29 ?1482次閱讀

    idea的java運(yùn)行配置怎么弄

    Java是一種跨平臺(tái)的編程語(yǔ)言,可以通過(guò)Java虛擬機(jī)(JVM)在不同的操作系統(tǒng)和硬件上運(yùn)行。在運(yùn)行Java程序之前,需要進(jìn)行一些配置。本文
    的頭像 發(fā)表于 12-06 14:04 ?2057次閱讀

    java環(huán)境配置成功后怎么運(yùn)行

    Java環(huán)境配置成功后,我們可以使用幾種方式來(lái)運(yùn)行Java程序。下面將詳細(xì)介紹這幾種方式以及其使用方法。 命令行運(yùn)行方式 在成功配置Java
    的頭像 發(fā)表于 12-06 15:57 ?2067次閱讀