Object.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package avt.lang;

import platform.dependent.*;

/** Класс <code>Object</code> является корнем всей иерархии типов программы.
  * Каждый класс имеет <code>Object</code> в качестве суперкласса.
  * Все объекты, включая массивы и структуры, реализуют методы этого класса.
  *
  * С каждым объектом связан монитор — объект синхронизации в многопоточном приложении.
  * Этот монитор уникален для каждого объекта.
  * @see Class
  * @see Thread
  */
public class Object
{
    private long fldRefCountFromOthers;
    private long fldRefCountFromObjects;
    private long fldClassOffset;
    private Monitor fldMonitor;

    /** Создаёт новый объект.
      * Этот конструктор явно или неявно вызывается из всех других конструкторов.
      * Исключением являются массивы: для них не вызывается какой-либо конструктор, поскольку массивы в ПВТ-ОО имеют иной механизм инициализации.
      * @see #afterConstruction()
      * @see #beforeDestruction()
      */
    public () {  }

    /** Показывает, когда некоторый другой объект «равен» этому.
      * Этот метод реализует отношение равенства:
      * <ul><li>
      * Оно <em>рефлексивно</em>: для любой ссылки <code>x</code> <code>x.equals(x)</code> должно возвращать <code>true</code>.
      * </li><li>
      * Оно <em>симметрично</em>: для любых ссылок <code>x</code> и <code>y</code> <code>x.equals(y) == y.equals(x)</code>.
      * </li><li>
      * Оно <em>транзитивно</em>: для любых ссылок <code>x</code>, <code>y</code> и <code>z</code> если <code>x.equals(y)</code>
      * и <code>y.equals(z)</code> возвращают <code>true</code>, то и <code>x.equals(z)</code> так же должно возвращать <code>true</code>.
      * </li><li>
      * Оно <em>консистентно</em>: если содержимое ссылок <code>x</code> и <code>y</code> не изменяется, то и возвращаемое значение <code>x.equals(y)</code>
      * не изменяется даже при повторяющихся вызовах.
      * </li><li>
      * Для любой ссылки <code>x</code> <code>x.equals(null)</code> должно возвращать <code>false</code>.
      * </li></ul>
      * Использование этого метода может заменить собой операцию сравнения двух объектных ссылок, поскольку если <code>(x == y)</code>, то и <code>(x.equals(y) == true)</code>.
      *
      * Этот метод нужно так же переопределять, если переопределён метод <code>{@link #hashCodeAsLong() hashCodeAsLong()}</code>.
      *
      * Реализация данного метода в классе <code>Object</code> возвращает результат сравнения двух ссылок: <code>anot == this</code>.
      * @param anot объект, с которым производится «сравнение» этого объекта.
      * @return <code>true</code>, если объекты «равны», <code>false</code> — во всех остальных случаях.
      * @see #hashCodeAsLong()
      */
    public boolean equals(Object anot) { return anot == this; }

    /** Возвращает контрольную сумму в виде значения типа <code>int</code> для этого объекта.
      * Подклассы могут переопределить этот метод в одном из следующих случаев:
      * <ul><li>
      * если используется свой алгоритм вычисления контрольной суммы объекта;
      * </li><li>
      * если есть возможность более быстрого вычисления контрольной суммы объекта.
      * </li></ul>
      * Этот метод можно переопределить только в том случае, если переопределены методы <code>{@link #hashCodeAsLong() hashCodeAsLong()}</code> и <code>{@link #equals(Object) equals(Object)}</code>.
      * При переопределении и реализации этого метода следует руководствоваться тем же, что и при реализации метода <code>hashCodeAsLong()</code>.
      *
      * Реализация данного метода в классе <code>Object</code> такова:
      * <pre>
      * <b>long</b> hash = hashCodeAsLong();
      * <b>return</b> (<b>int</b>) (hash ^ (hash >> 32));
      * </pre>
      * @return контрольную сумму типа <code>int</code>.
      * @see #equals(Object)
      * @see #hashCodeAsLong()
      */
    public int hashCode() {
        long hash = hashCodeAsLong();
        return (int) (hash ^ (hash >> 32));
    }

    /** Возвращает контрольную сумму в виде значения типа <code>long</code> для этого объекта.
      * Такие классы как <code>{@link avt.util.Hashtable Hashtable}</code> и <code>{@link avt.util.Vector Vector}</code> из пакета <code>{@link avt.util avt.util}</code> используют этот метод.
      *
      * При переопределении и реализации этого метода следует руководствоваться следующим:
      * <ul><li>
      * При каждом вызове этого метода должно возвращаться одно и то же значение, даже если данные объекта были модифицированы.
      * Соответственно, при реализации объектов, поддерживающих модифицирование своих данных, данный метод не должен пользоваться данными, которые использует метод <code>equals</code>.
      * </li><li>
      * Если два объекта «равны» согласно реализации метода <code>equals</code>, то и контрольные суммы этих объектов так же должны быть равны.
      * Данное требование не распространяется на объекты, данные которых были модифицированы.
      * </li><li>
      * Если два объекта «не равны» согласно реализации метода <code>equals</code>, то их контрольные суммы не обязаны быть неравными.
      * </li></ul>
      * Этот метод нужно так же переопределять, если переопределён метод <code>{@link #equals(Object) equals(Object)}</code>.
      *
      * Реализация данного метода в классе <code>Object</code> возвращает уникальное ненулевое значение, связанное с этим объектом.
      * @return контрольную сумму типа <code>long</code>.
      * @see #equals(Object)
      */
    public long hashCodeAsLong() { return System.identityHashCode(this); }

    /** Возвращает контрольную сумму в виде значения типа <code>long2</code> для этого объекта.
      * Подклассы могут переопределить этот метод в одном из следующих случаев:
      * <ul><li>
      * если используется свой алгоритм вычисления контрольной суммы объекта;
      * </li><li>
      * если есть возможность получения контрольной суммы типа <code>long2</code>;
      * </li><li>
      * если есть возможность более быстрого вычисления контрольной суммы объекта.
      * </li></ul>
      * Этот метод можно переопределить только в том случае, если переопределены методы
      * <code>{@link #hashCodeAsLong() hashCodeAsLong()}</code> и
      * <code>{@link #equals(Object) equals(Object)}</code>.
      * При переопределении и реализации этого метода следует руководствоваться тем же, что и при реализации метода <code>hashCodeAsLong()</code>.
      *
      * Реализация данного метода в классе <code>Object</code> вызывает метод <code>hashCodeAsLong()</code> и приводит его результат к типу <code>long2</code>.
      * @return контрольную сумму типа <code>long2</code>.
      * @see #equals(Object)
      * @see #hashCodeAsLong()
      */
    public long2 hashCodeAsLong2() { return (long2) hashCodeAsLong(); }

    /** Возвращает контрольную сумму в виде значения типа <code>long4</code> для этого объекта.
      * Подклассы могут переопределить этот метод в одном из следующих случаев:
      * <ul><li>
      * если используется свой алгоритм вычисления контрольной суммы объекта;
      * </li><li>
      * если есть возможность получения контрольной суммы типа <code>long4</code>;
      * </li><li>
      * если есть возможность более быстрого вычисления контрольной суммы объекта.
      * </li></ul>
      * Этот метод можно переопределить только в том случае, если переопределены методы
      * <code>{@link #hashCodeAsLong() hashCodeAsLong()}</code>,
      * <code>{@link #hashCodeAsLong2() hashCodeAsLong2()}</code> и
      * <code>{@link #equals(Object) equals(Object)}</code>.
      * При переопределении и реализации этого метода следует руководствоваться тем же, что и при реализации метода <code>hashCodeAsLong()</code>.
      *
      * Реализация данного метода в классе <code>Object</code> вызывает метод <code>hashCodeAsLong2()</code> и приводит его результат к типу <code>long4</code>.
      * @return контрольную сумму типа <code>long4</code>.
      * @see #equals(Object)
      * @see #hashCodeAsLong()
      * @see #hashCodeAsLong2()
      */
    public long4 hashCodeAsLong4() { return (long4) hashCodeAsLong2(); }

    /** Возвращает контрольную сумму в виде значения типа <code>long8</code> для этого объекта.
      * Подклассы могут переопределить этот метод в одном из следующих случаев:
      * <ul><li>
      * если используется свой алгоритм вычисления контрольной суммы объекта;
      * </li><li>
      * если есть возможность получения контрольной суммы типа <code>long8</code>;
      * </li><li>
      * если есть возможность более быстрого вычисления контрольной суммы объекта.
      * </li></ul>
      * Этот метод можно переопределить только в том случае, если переопределены методы
      * <code>{@link #hashCodeAsLong() hashCodeAsLong()}</code>,
      * <code>{@link #hashCodeAsLong2() hashCodeAsLong2()}</code>,
      * <code>{@link #hashCodeAsLong4() hashCodeAsLong4()}</code> и
      * <code>{@link #equals(Object) equals(Object)}</code>.
      * При переопределении и реализации этого метода следует руководствоваться тем же, что и при реализации метода <code>hashCodeAsLong()</code>.
      *
      * Реализация данного метода в классе <code>Object</code> вызывает метод <code>hashCodeAsLong4()</code> и приводит его результат к типу <code>long8</code>.
      * @return контрольную сумму типа <code>long8</code>.
      * @see #equals(Object)
      * @see #hashCodeAsLong()
      * @see #hashCodeAsLong2()
      * @see #hashCodeAsLong4()
      */
    public long8 hashCodeAsLong8() { return (long8) hashCodeAsLong4(); }

    /** Возвращает текстовое представление объекта.
      * Иными словами, этот метод возвращает строку, которая «текстовым образом представляет» этот объект.
      * Результат не обязательно должен быть подробным, но должен быть информативным для читателя.
      * Этот метод рекомендуется переопределять всем подклассам.
      *
      * Реализация данного метода в классе <code>Object</code> возвращает конкатенацию трёх элементов: канонического имени класса объекта,
      * символа «@» и шестнадцатеричного представления беззнакового значения контрольной суммы типа <code>long</code> для этого объекта.
      * Другими словами, возвращается значение, эквивалентное следующему:
      *
      * <code>getClass().canonicalName + '@' + Long.toHexString(hashCodeAsLong())</code>
      * @return текстовое представление объекта.
      */
    public String toString() { return (new StringBuilder() + getClass().canonicalName + '@' + Long.toHexString(hashCodeAsLong())).toString(); }

    /** Пробуждает один поток исполнения, ожидающий на мониторе этого объекта.
      * Если какие-либо потоки исполнения ожидают на мониторе, то один из них выбирается для пробуждения.
      * Какой из них будет выбран — зависит от реализации.
      * Поток исполнения ожидает на мониторе при вызове одного из методов <code>wait</code>.
      *
      * Пробужденный поток исполнения не сразу получает управление, а лишь после того, как текущий поток исполнения перестанет быть владельцем монитора, связанным с этим объектом.
      * Этот метод может быть вызван только если текущий поток исполнения является владельцем монитора этого объекта.
      * Поток исполнения становится владельцем монитора в одном из следующих случаев:
      * <ul><li>
      * Выполняет тело управляющей конструкции <code>synchronized</code> или <code>synchronized with</code>, которая синхронизирует выполнение кода на мониторе этого объекта;
      * </li><li>
      * Выполняет тело синхронизированного инстанционного метода этого объекта;
      * </li><li>
      * Для объектов типа <code>Class</code>: выполняет тело синхронизированного статичного метода этого класса.
      * </li></ul>
      * Только один поток исполнения одновременно может владеть монитором объекта.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @see #notify(Thread)
      * @see #notifyAll()
      * @see #wait()
      */
    public final void notify() {
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.notify(false, 0L);
    }

    /** Пробуждает заданный поток исполнения, ожидающий на мониторе этого объекта.
      * Если какие-либо потоки исполнения ожидают на мониторе, то один из них выбирается для пробуждения,
      * однако предпочтение отдаётся тому потоку, который был передан в качестве аргумента этому методу.
      * Другими словами, если заданный в качестве аргумента поток исполнения ожидает на мониторе, то будет пробужден именно он.
      * Иначе — любой другой ожидающий поток исполнения.
      * Поток исполнения ожидает на мониторе при вызове одного из методов <code>wait</code>.
      *
      * Пробужденный поток исполнения не сразу получает управление, а лишь после того, как текущий поток исполнения перестанет быть владельцем монитора, связанным с этим объектом.
      * Этот метод может быть вызван только если текущий поток исполнения является владельцем монитора этого объекта.
      * О том, как поток исполнения становится владельцем монитора, можно узнать в описании метода <code>notify()</code>.
      * @param notifying поток исполнения, который следует пробудить в первую очередь.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @see #notify()
      * @see #notifyAll()
      * @see #wait()
      */
    public final void notify(Thread notifying) {
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.notify(false, notifying == null ? 0L : notifying.threadId);
    }

    /** Пробуждает все потоки исполнения, ожидающие на мониторе этого объекта.
      * Поток исполнения ожидает на мониторе при вызове одного из методов <code>wait</code>.
      *
      * Пробужденные потоки исполнения не сразу получают управление, а лишь после того, как текущий поток исполнения перестанет быть владельцем монитора, связанным с этим объектом,
      * причём управление получит только один из этих потоков до тех пор, пока он не перестанет быть владельцем монитора,
      * после чего управление получит другой поток до тех пор, пока он не перестанет быть владельцем монитора и т. д.
      * Этот метод может быть вызван только если текущий поток исполнения является владельцем монитора этого объекта.
      * О том, как поток исполнения становится владельцем монитора, можно узнать в описании метода <code>notify()</code>.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @see #notify()
      * @see #notify(Thread)
      * @see #wait()
      */
    public final void notifyAll() {
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.notify(true, 0L);
    }

    /** Заставляет текущий поток исполнения ждать на мониторе этого объекта до тех пор, пока другой поток не вызовет метод <code>notify()</code> или <code>notifyAll()</code> для этого объекта.
      * Другими словами, этот метод ведёт себя подобно вызову <code>wait(0L)</code> или <code>wait(0L, 0)</code>.
      *
      * Текущий поток исполнения должен владеть монитором этого объекта.
      * Поток перестаёт быть владельцем монитора, уходит в спячку, а после пробуждения — снова становится владельцем этого монитора, после чего метод <code>wait</code> возвращает управление.
      * О том, как поток исполнения становится владельцем монитора, можно узнать в описании метода <code>notify()</code>.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @throws InterruptedException если текущий поток исполнения был прерван. <em>Статус прерывания</em> сбрасывается после того,
      * как текущий поток исполнения станет владельцем монитора этого объекта, и перед тем, как это исключение будет возбуждено.
      * @see #notify()
      * @see #wait(long)
      * @see #wait(long, int)
      */
    public final void wait() throws InterruptedException {
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.wait(0i, Thread.current().interruptioHandler);
    }

    /** Заставляет текущий поток исполнения ждать на мониторе этого объекта до тех пор, пока другой поток не вызовет метод <code>notify()</code> или <code>notifyAll()</code> для этого объекта,
      * но не дольше заданного времени.
      * Если заданное время ожидания равно нулю, то ожидание будет длиться до тех пор, пока другой поток не вызовет метод <code>notify()</code> или <code>notifyAll()</code> для этого объекта.
      *
      * Текущий поток исполнения должен владеть монитором этого объекта.
      * Поток перестаёт быть владельцем монитора, уходит в спячку, а после пробуждения — снова становится владельцем этого монитора, после чего метод <code>wait</code> возвращает управление.
      * О том, как поток исполнения становится владельцем монитора, можно узнать в описании метода <code>notify()</code>.
      * @param timeInMillis время ожидания в миллисекундах. Если этот аргумент равен нулю, то он игнорируется.
      * @throws IllegalArgumentException если <code>timeInMillis</code> отрицательный.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @throws InterruptedException если текущий поток исполнения был прерван. <em>Статус прерывания</em> сбрасывается после того,
      * как текущий поток исполнения станет владельцем монитора этого объекта, и перед тем, как это исключение будет возбуждено.
      * @see #notify()
      * @see #wait()
      * @see #wait(long, int)
      */
    public final void wait(long timeInMillis) throws InterruptedException {
        if(timeInMillis < 0)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.negative"), new Object[] { "timeInMillis" }));
        }
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.wait(timeInMillis, Thread.current().interruptioHandler);
    }

    /** Заставляет текущий поток исполнения ждать на мониторе этого объекта до тех пор, пока другой поток не вызовет метод <code>notify()</code> или <code>notifyAll()</code> для этого объекта,
      * но не дольше заданного времени.
      * Если заданное время ожидания равно нулю, то ожидание будет длиться до тех пор, пока другой поток не вызовет метод <code>notify()</code> или <code>notifyAll()</code> для этого объекта.
      *
      * Данный метод позволяет задать время ожидания с точностью до наносекунды.
      * Время ожидания имеет величину (1000000 × <code>timeInMillis</code> + <code>timeInNanos</code>) наносекунд.
      * Однако далеко не все операционные системы и аппаратные возможности позволяют измерять время с точностью до наносекунды.
      * Поэтому реальное время ожидания может быть округлено до миллисекунд.
      *
      * Текущий поток исполнения должен владеть монитором этого объекта.
      * Поток перестаёт быть владельцем монитора, уходит в спячку, а после пробуждения — снова становится владельцем этого монитора, после чего метод <code>wait</code> возвращает управление.
      * О том, как поток исполнения становится владельцем монитора, можно узнать в описании метода <code>notify()</code>.
      * @param timeInMillis время ожидания в миллисекундах.
      * @param timeInNanos дополнительное время ожидания в наносекундах. Если и <code>timeInMillis</code>, и <code>timeInNanos</code> оба равны нулю, то оба этих аргумента игнорируются.
      * @throws IllegalArgumentException если <code>timeInMillis</code> отрицательный.
      * @throws IllegalArgumentException если <code>timeInNanos</code> отрицательный или больше 999999.
      * @throws IllegalMonitorStateException если текущий поток исполнения не владеет монитором этого объекта.
      * @throws InterruptedException если текущий поток исполнения был прерван. <em>Статус прерывания</em> сбрасывается после того,
      * как текущий поток исполнения станет владельцем монитора этого объекта, и перед тем, как это исключение будет возбуждено.
      * @see #notify()
      * @see #wait()
      * @see #wait(long)
      */
    public final void wait(long timeInMillis, int timeInNanos) throws InterruptedException {
        if(timeInMillis < 0)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.negative"), new Object[] { "timeInMillis" }));
        }
        if(timeInNanos < 0 || timeInNanos > 999999)
        {
            throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.out-of-range"), new Object[] { "timeInNanos" }));
        }
        Waitable monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.wait(timeInMillis, timeInNanos, Thread.current().interruptioHandler);
    }

    /** Возвращает настоящий класс этого объекта.
      * Этот объект типа <code>Class</code> используется в качестве монитора в статичных синхронизированных (<code>static synchronized</code>) методах этого класса.
      * @return объект типа <code>Class</code>, представляющий настоящий класс этого объекта.
      */
    public final native Class getClass();

    /** Автоматически вызывается сразу после того, как конструктор вернул управление.
      * Компилятор ПВТ-ОО вставляет инструкцию вызова этого метода после каждой инструкции вызова конструктора в операторах <code>new</code>.
      * Допустим, что написана строка кода:
      *
      * <code>Vector v = <b>new</b> Vector(15);</code>
      *
      * Компилятор ПВТ-ОО сгенерирует для неё следующие инструкции:
      * <ol><li>
      * Создать пустую инстанцию класса <code>Vector</code>.
      * </li><li>
      * Передать <code>int</code> 15 конструктору в качестве аргумента.
      * </li><li>
      * Вызвать конструктор <code>Vector(int)</code> для созданной пустой инстанции. После возврата из конструктора инстанция считается проинициализированной.
      * </li><li>
      * Вызвать метод <code>afterConstruction()</code> для этой инстанции.
      * </li><li>
      * Присвоить ссылку на эту инстанцию переменной <code>v</code>.
      * </li></ol>
      * Таким образом, код внутри переопределённого <code>afterConstruction()</code> выполняется для только что созданного и полностью проинициализированного объекта.
      *
      * Для массивов этот метод не вызывается, поскольку массивы в ПВТ-ОО имеют иной механизм инициализации.
      *
      * Реализация данного метода в классе <code>Object</code> не делет чего-либо и сразу же возвращает управление.
      * @see #beforeDestruction()
      */
    protected void afterConstruction() {  }

    /** Вызывается автоматическим сборщиком мусора перед утилизацией этого объекта.
      * Если автоматический сборщик мусора видит, что этот объект больше не используется программой, то вызовет
      * для него метод <code>beforeDestruction()</code> и отметит выделенную под него память как свободную.
      * Переопределение этого метода необходимо для освобождения ресурсов, созданных системными библиотеками опреационной системы и требующих явного удаления из памяти.
      *
      * При переопределении данного метода следует помнить о том, что этот объект будет утилизирован после возврата управления,
      * поэтому коду внутри переопределённого <code>beforeDestruction()</code> не следует сохранять где-либо ссылку на этот объект, иначе неизбежны ошибки в работе программы.
      * Любые исключения, возбужденные этим методом, игнорируются автоматическим сборщиком мусора.
      *
      * Для массивов этот метод не вызывается, поскольку массивы в ПВТ-ОО имеют иной механизм инициализации.
      *
      * Реализация данного метода в классе <code>Object</code> не делет чего-либо и сразу же возвращает управление.
      * @see #afterConstruction()
      */
    protected void beforeDestruction() {  }

    package final native void defaultConstructor();

    package final void checkObjectArrayAssignable(Object component) {
        Class saving;
        Class required = getClass().componentType;
        if(required == null || (required.attributes & Class.TYPE_MASK) == Class.PRIMITIVE)
        {
            throw new VerifyError(package.getResourceString("!machine-error.verify.array-of-objects"));
        }
        if(component != null && !required.isAssignableFrom(saving = component.getClass()))
        {
            throw new ArrayStoreException(package.getResourceString("array-store")) { saving = saving, required = required };
        }
    }

    package final Monitor monitor { read = fldMonitor }

    private void lock() {
        Mutex monitor = fldMonitor;
        if(monitor == null)
        {
            Runtime runtime = Runtime.getInstance();
            Mutex operation = runtime.systemOperation;
            operation.lock();
            try
            {
                if((monitor = fldMonitor) == null) monitor = fldMonitor = runtime.newMonitor();
            } finally
            {
                operation.unlock();
            }
        }
        monitor.lock();
    }

    private void unlock() {
        Mutex monitor = fldMonitor;
        if(monitor == null)
        {
            throw new IllegalMonitorStateException(package.getResourceString("illegal-state.monitor"));
        }
        monitor.unlock();
    }
}