日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

本文介紹了Java:刪除JAR后,類仍被加載的處理方法,對(duì)大家解決問(wèn)題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧!

問(wèn)題描述

我試圖重現(xiàn)一個(gè)錯(cuò)誤,其中JAR被更新(通過(guò)Linux機(jī)器上的rsync),然后拋出NoClassDefFoundError。更新的JAR沒(méi)有變化,但我在考慮這樣一個(gè)事實(shí),即文件在類加載時(shí)正在傳輸…

我現(xiàn)在正在嘗試復(fù)制該錯(cuò)誤。

我的應(yīng)用程序啟動(dòng)時(shí)只有一個(gè)JAR的類路徑(/opt/test/myjar.jar)

其他JAR位于myjar.jar(/opt/test/lib/mylib.jar)相同路徑下的目錄中。

該庫(kù)已注冊(cè)到myjar.jarMETA-INF/MANIFEST.MF,文本為

Manifest-Version: 1.0
Built-By: FB
Class-Path: lib/mylib.jar

現(xiàn)在我編寫(xiě)了一些等待幾秒鐘的代碼,然后使用Class.forName("mylib.MyClass")加載一些類。

然后我將設(shè)置文件夾,啟動(dòng)Java運(yùn)行時(shí),然后刪除lib/mylib.jar文件,并等待Class.forName失敗。

并且代碼運(yùn)行正常。我期待的是NoClassDefFoundError。然后我重新運(yùn)行代碼,拋出了一個(gè)NoClassDefFoundError

然后我將mylib.jar讀取到lib目錄,重新運(yùn)行,一切正常。

然后我使用-verbose:class重新運(yùn)行代碼,刪除lib/mylib.jar,然后出現(xiàn)此日志。

[Loaded mylib.MyClass from file:/opt/test/lib/mylib.jar`]

所以類加載是在JAR刪除之后發(fā)生的。我不明白這為什么管用。
并且以前未從lib/mylib.jar加載任何其他類。

使用的JDK為OpenJDK Runtime Environment corretto-8.302.08.1(Build 1.8.0_302-B08)

我不明白JVM如何從我剛剛刪除的文件加載類。我認(rèn)為JVM可能會(huì)在某個(gè)地方緩存這些文件(可能是因?yàn)樗鼈冊(cè)?code>MANIFEST.MF中注冊(cè))。

有人知道這種行為嗎?

P。我用真正的JAR和類測(cè)試了這個(gè)過(guò)程。如果沒(méi)有人知道原因,我可以構(gòu)建一個(gè)測(cè)試項(xiàng)目。

推薦答案

您使用的系統(tǒng)沒(méi)有強(qiáng)制文件鎖定。例如,如果您在Windows下嘗試了相同的操作,則無(wú)法同時(shí)覆蓋或刪除.jar文件。

類路徑上的JAR文件在JVM啟動(dòng)時(shí)打開(kāi),并在運(yùn)行時(shí)保持打開(kāi)狀態(tài)。我們可以使用普通文件操作演示該行為:

Path p = Files.createTempFile(Paths.get(System.getProperty("user.home")),"test",".tmp");
try(FileChannel ch = FileChannel.open(p,
                                 StandardOpenOption.READ, StandardOpenOption.WRITE)) {
  System.out.println("opened " + p);
  int rc = new ProcessBuilder("rm", "-v", p.toString()).inheritIO().start().waitFor();
  System.out.println("rm ran with rc " + rc);
  int w = ch.write(StandardCharsets.US_ASCII.encode("test data"));
  System.out.println("wrote " + w + " bytes into " + p);
  ch.position(0);
  ByteBuffer bb = ByteBuffer.allocate(w);
  do ch.read(bb); while(bb.hasRemaining());
  bb.flip();
  System.out.println("read " + bb.remaining() + " bytes, "
                   + StandardCharsets.US_ASCII.decode(bb));
}
System.out.println("closed, reopening");
try(FileChannel ch = FileChannel.open(p,
                                 StandardOpenOption.READ, StandardOpenOption.WRITE)) {
  System.out.println("opened " + p);
}
catch(IOException ex) {
  System.out.println("Reopening " + p + ": " + ex);
}

打印類似

的內(nèi)容

opened /home/tux/test722563514590118445.tmp
removed '/home/tux/test722563514590118445.tmp'
rm ran with rc 0
wrote 9 bytes into /home/tux/test722563514590118445.tmp
read 9 bytes, test data
closed, reopening
Reopening /home/tux/test722563514590118445.tmp: java.nio.file.NoSuchFileException: /home/tux/test722563514590118445.tmp

演示了在刪除之后,我們?nèi)匀豢梢詮囊呀?jīng)打開(kāi)的文件中寫(xiě)入和讀取數(shù)據(jù),因?yàn)橹挥袟l目已經(jīng)從目錄中刪除。JVM現(xiàn)在正在操作一個(gè)沒(méi)有名稱的文件。但是,一旦此文件句柄關(guān)閉,再次嘗試打開(kāi)它將失敗,因?yàn)楝F(xiàn)在它真的不見(jiàn)了。


然而,覆蓋該文件則是另一回事。打開(kāi)現(xiàn)有文件時(shí),我們?cè)L問(wèn)相同的文件并使更改可被察覺(jué)。

所以

Path p = Files.createTempFile(Paths.get(System.getProperty("user.home")),"test",".tmp");
try(FileChannel ch = FileChannel.open(p,
                                 StandardOpenOption.READ, StandardOpenOption.WRITE)) {
  System.out.println("opened " + p);
  int w = ch.write(StandardCharsets.US_ASCII.encode("test data"));
  System.out.println("wrote " + w + " bytes into " + p);
  int rc = new ProcessBuilder("cp", "/proc/self/cmdline", p.toString())
      .inheritIO().start().waitFor();
  System.out.println("cp ran with rc " + rc);
  ch.position(0);
  ByteBuffer bb = ByteBuffer.allocate(w);
  do ch.read(bb); while(bb.hasRemaining());
  bb.flip();
  System.out.println("read " + bb.remaining() + " bytes, "
                   + StandardCharsets.US_ASCII.decode(bb));
}

產(chǎn)生類似

的結(jié)果

opened /home/tux/test7100435925076742504.tmp
wrote 9 bytes into /home/tux/test7100435925076742504.tmp
cp ran with rc 0
read 9 bytes, cp/proc/

顯示了對(duì)已經(jīng)打開(kāi)的文件的read操作導(dǎo)致了cp寫(xiě)入的內(nèi)容,當(dāng)然,部分原因是緩沖區(qū)的大小預(yù)先調(diào)整到了Java應(yīng)用程序?qū)懭氲膬?nèi)容。這演示了當(dāng)一些數(shù)據(jù)已經(jīng)被讀取并且應(yīng)用程序嘗試根據(jù)它從舊版本中知道的來(lái)解釋新數(shù)據(jù)時(shí),覆蓋打開(kāi)的文件會(huì)如何造成破壞。


這產(chǎn)生了一種解決方案,可以在不使已經(jīng)運(yùn)行的JVM崩潰的情況下更新JAR文件。首先刪除舊的JAR文件,這會(huì)讓JVM在將新版本復(fù)制到相同位置之前,使用已經(jīng)打開(kāi)的、現(xiàn)在是私有的舊文件運(yùn)行。從系統(tǒng)的角度來(lái)看,您有兩個(gè)不同的文件。當(dāng)JVM終止時(shí),舊的將不復(fù)存在。替換后啟動(dòng)的JVM將使用新版本。

這篇關(guān)于Java:刪除JAR后,類仍被加載的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,

分享到:
標(biāo)簽:JAR Java 刪除 加載 類仍被
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定