Это ничего не значит, в частности, в отношении java.
Инвариант класса - это просто свойство, которое сохраняется для всех экземпляров класса всегда, независимо от того, что делает другой код.
Например,
class X {
final Y y = new Y();
}
X имеет инвариант класса, что есть свойство y
, оно никогда не является null
и имеет значение типа Y
.
class Counter {
private int x;
public int count() { return x++; }
}
не поддерживает два важных инварианта
- То, что
count
никогда не возвращает отрицательное значение из-за возможного недостаточного значения. - То, что вызовы
count
строго монотонно возрастают.
Модифицированный класс сохраняет эти два инварианта.
class Counter {
private int x;
public synchronized int count() {
if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
return x++;
}
}
, но не в состоянии сохранить инвариант, который вызывает count
, всегда успешно выполняется (при отсутствии нарушений TCB † ), поскольку count
может выдать исключение или блокировать, если заблокированный поток владеет монитором счетчика.
Каждый язык с классами позволяет легко поддерживать некоторые инварианты классов, но не otее.Java не является исключением:
- Классы Java постоянно имеют или не имеют свойств и методов, поэтому интерфейсные инварианты просты в обслуживании.
- Классы Java могут защищать свои
private
поля,поэтому инварианты, которые полагаются на личные данные, просты в обслуживании. - Классы Java могут быть конечными, поэтому можно поддерживать инварианты, которые полагаются на отсутствие кода, который нарушает инвариант путем создания вредоносного подкласса.
- Java позволяет
null
значениям проникать разными способами, поэтому трудно поддерживать инварианты «имеет реальное значение». - В Java есть потоки, что означает, что классы, которые не синхронизируются, испытывают проблемы с поддержанием инвариантов.которые полагаются на последовательные операции в потоке, происходящем вместе.
- В Java есть исключения, которые позволяют легко поддерживать инварианты типа «возвращает результат со свойством p или не возвращает результата», но сложнее поддерживать инварианты типа «всегда возвращаетрезультат ".
† - внешность или TCB нарушение - это событие, которое, как оптимистично полагает разработчик системы, не произойдет.
Как правило, мы просто верим, что базовое оборудование работает так, как рекламируется, когда речь идет освойства высокоуровневых языков, построенных на них, и наши аргументы, которые содержат инварианты, не учитывают возможность:
- Программист, использующий отладочные хуки для изменения локальных переменных при выполнении программы разными способамиэтот код не может.
- Ваши коллеги не используют отражение с
setAccessible
для изменения private
справочных таблиц. - Локи изменяют физику, заставляя ваш процессор неправильно сравнивать два числа.
Для некоторых систем наш TCB может включать только части системы, поэтому мы не можем предполагать, что
- Администратор или привилегированный демон не будет уничтожать наш процесс JVM,
, но мы можем предположить, что
- Мы можем проверить надежную транзакционную файловую систему.
ПриветЧем выше уровень системы, тем больше ее TCB, как правило, но чем больше ненадежных вещей вы сможете извлечь из TCB, тем выше вероятность того, что ваши инварианты будут храниться, и тем более надежной будет ваша система в долгосрочной перспективе.