Область действия переменных статического класса в Java

StackOverflow https://stackoverflow.com/questions/1402034

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть статический объект, определенный в моем классе ведения журнала, например:

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

Согласно моему справочнику, это означает, что объект свойств является общим для всех экземпляров моего класса.

Я считаю это определение недостаточным.Я пишу класс, который вызывается более одного раза в каждом приложении нашего проекта.

Кроме того, наш проект использует несколько веб-сервисов, работающих в одном контейнере Tomcat.Каждый веб-сервис может иметь несколько потоков.

Виртуальная машина Java, работающая на хосте, также может запускать одно или несколько клиентских приложений веб-службы, которые выполняются вне Tomcat.

Таким образом, согласно этому определению, у меня может быть Tomcat, запускающий несколько веб-сервисов с потоками, каждый из которых имеет несколько объектов, которые могут содержать экземпляр моего класса.

Также может быть один или два веб-клиента, работающих за пределами Tomcat, но внутри одной JVM.Бы все из этих экземпляров моего класса имеют один и тот же объект свойств?Это сделало бы его общедоступным для JVM.

Если статический объект нет В рамках JVM, кто-нибудь знает, на каком уровне будет существовать каждый из них?По одному на контейнер Tomcat?По одному на каждую веб-службу и по одному на отдельное клиентское приложение веб-службы?

Причина:Когда я обновляю свои свойства, я получаю исключение java.lang.ConcurrentUpdateException из java.util.Properties.

Я использую статическую логическую переменную, чтобы «заблокировать» объект свойств, когда мой класс его обновляет, но это не предотвращает возникновение исключения.

Это наводит меня на мысль, что статический объект, используемый в моем классе, может быть не на том же уровне области видимости, что и тот, который используется в java.util.Properties...Но это всего лишь предположение.

Спасибо за любую помощь.

Это было полезно?

Решение

Вероятная причина вашего ConcurrentModificationException заключается в том, что вы перебираете значения/записи Properties объект в одном потоке, в то время как другой одновременно изменяет его.Ты не сможешь это сделать.

Можете ли вы рассказать подробнее о механизме блокировки, который вы здесь упоминаете:

Я использую статическую логическую переменную, чтобы «заблокировать» объект свойств, когда мой класс его обновляет, но это не предотвращает возникновение исключения.

?

Потому что это не похоже на использование встроенных в Java методов блокировки и синхронизации.

Что-то вроде этого должно помешать потокам читать объект Properties, пока другой поток его обновляет:

static Object lockObject = new Object();

...

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

Обратите внимание, что вам нужно будет это сделать каждый время доступа к объекту «Свойства» для его чтения или изменения.

Кроме того, я бы никогда не рекомендовал статическим объектам совместно использовать данные между всеми экземплярами или статическими объектами блокировки — глобальные данные — это зло, но звучит так, как будто вам это нужно по какой-то причине.

Другие советы

Статика не "используется всеми экземплярами класса" - они не связаны с экземплярами; они принадлежат самому типу . В частности, статические переменные идеально подходят без создания каких-либо экземпляров.

Это дает ключ к пониманию области действия статики: они ограничены объектом Class , представляющим содержащий класс, который в свою очередь ограничен ClassLoader , который загрузил его.

В зависимости от того, где находится библиотека, статическая переменная может иметь размер JVM или веб-приложения, или, возможно, что-то среднее между ними, если Tomcat поддерживает множественный хостинг (я не могу вспомнить случайно).

Посмотрите в документации Tomcat, как расположены библиотеки и как они связаны с загрузчиками классов. Например, вот руководство Tomcat 6.0 ClassLoader и эквивалент для 5.5 .

Как ваш Boolean " заблокировать " Работа? Вы должны действительно использовать правильную блокировку ( synchronized ), чтобы убедиться, что каждое использование объекта свойств (как чтение, так и запись, включая блокировку на весь период, в течение которого вы итерируете его), надлежащим образом заблокировано.

Вместо изменения " live " Объект Properties рассматривал ли вы его как неизменный - поэтому, когда вы хотите обновить свойства, вы берете копию, изменяете ее, а затем делаете копию " живой " версия? Вам по-прежнему нужно предотвращать одновременное внесение изменений в двух разных потоках (или вы их потеряете), но это, вероятно, сделает чтение намного проще и эффективнее.

Вы можете обнаружить, что область действия такой переменной static ограничена одной на ClassLoader, который загрузил ваш класс. Я не уверен, как Tomcat упорядочивает свои ClassLoaders, поэтому трудно сказать, какой будет область действия в этой среде.

Может ли быть проблема загрузчика классов, когда jar, содержащий ваш класс, дублируется в каждом WEB-INF / lib ваших разных приложений? Если это так, я бы попытался добавить эту банку в библиотеки Tomcat, а не в приложение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top