簡體   English   中英

Java中靜態類變量的范圍

[英]Scope of Static Class Variables in Java

我在我的日志記錄類中定義了一個靜態對象,其行如下:

   class myLoggingClass {
     static java.util.Properties properties;
     ...
     ...
   }

根據我的參考書,這意味着屬性對象由我的類的所有實例共享。

我覺得這個定義不夠。 我正在編寫一個在我們項目的每個應用程序中多次調用的類。

此外,我們的項目使用在同一個tomcat容器中運行的多個Web服務。 每個Web服務可能有多個線程。

在主機上運行的Java虛擬機還可以運行一個或多個Web服務客戶端應用程序,這些應用程序在tomcat外部運行。

因此,通過這個定義,我可能讓tomcat運行帶有線程的多個Web服務,每個線程都有幾個對象,這些對象可能包含我的類的實例。

也可能有一個或兩個Web客戶端在tomcat之外運行,但在同一個JVM中。 我班級的所有這些實例都會共享相同的屬性對象嗎? 這將使其成為JVM范圍的。

如果靜態對象不是 JVM范圍的,那么有人知道每個對象存在的級別嗎? 每個tomcat容器一個? 每個Web服務一個,每個獨立Web服務客戶端應用程序一個?

原因是:當我更新我的屬性時,我從java.util.Properties獲得了java.lang.ConcurrentUpdateException。

我正在使用靜態布爾變量來在我的類更新時“鎖定”屬性對象,但這並不能防止異常發生。

這讓我相信我的類中使用的靜態對象可能與java.util.Properties中使用的靜態對象沒有相同的范圍級別......但這只是猜測。

謝謝你的幫助。

靜態不是“所有類的實例共享” - 它們實例無關 ; 它們屬於該類型本身 特別是,靜態變量在沒有創建任何實例的情況下完全可用。

這給出了關於靜態范圍的線索:它們由表示包含類的Class對象確定范圍,包含類又由加載它的ClassLoader限定范圍。

根據庫的放置位置,靜態變量可能是JVM范圍的或Web應用程序范圍的 - 或者可能是介於兩者之間的東西,如果Tomcat支持多個托管(我不記得隨便)。

查看Tomcat文檔,了解庫的布局方式以及它們與類加載器的關系。 例如,這里是Tomcat 6.0 ClassLoader的操作指南 ,以及5.5的等價物

您的布爾“鎖定”如何工作? 您應該使用正確的鎖( synchronized )來確保每次使用屬性對象(包括讀取和寫入,包括在整個迭代期間鎖定)都被適當地鎖定。

您是否考慮將其視為不可變的,而不是更改“實時” Properties對象 - 所以當您想要更新屬性時,您需要復制,更改它,然后將副本復制為“實時”版本? 你仍然需要阻止兩個不同的線程同時進行更改(或者你會丟失一些),但它可能會使閱讀方面更容易,更有效。

您可能會發現這樣的static變量的范圍僅限於已加載類的ClassLoader。 我不確定Tomcat如何安排其ClassLoader,因此很難說該范圍在該環境中的范圍。

ConcurrentModificationException的可能原因是您在一個線程中通過Properties對象的值/條目進行迭代,而另一個線程同時修改它。 你不能做這個。

你能詳細說明你在這里提到的鎖定機制:

我正在使用靜態布爾變量來在我的類更新時“鎖定”屬性對象,但這並不能防止異常發生。

因為它聽起來不像是在Java中使用內置鎖定和同步方法。

這樣的事情應該阻止線程讀取Properties對象,而另一個線程更新它:

static Object lockObject = new Object();

...

synchronized(lockObject) {
     // access the Properties object
}

請注意, 每次訪問Properties對象時都需要執行此操作,以讀取或修改它。

此外,我永遠不會建議靜態對象在所有實例或靜態lockObjects之間共享數據 - 全局數據是邪惡的 - 但聽起來好像你出於某種原因需要它。

這可能是一個類加載器問題,其中包含您的類的jar在您的不同應用程序的每個WEB-INF / lib中都是重復的嗎? 如果是這樣,我會嘗試將此jar添加到Tomcat庫而不是應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM