[英]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.