Занятие 4 Класс Object Определение классов Сборка мусора
Определение классов
Перерыв 
Сборка мусора
291.50K
Category: programmingprogramming

Занятие 4

1. Занятие 4 Класс Object Определение классов Сборка мусора

2.

Класс Object
• getClass()
• hashCode()
• equals()
• wait(), notify(), notifyAll()
• toString()
• clone()
• finalize()

3.

Метод finalize()
Метод finalize() предназначен для очистки ресурсов.
Он вызывается перед удалением объекта сборщиком мусора.
Однако моментом вызова сборщика мусора нельзя управлять программно,
следовательно, момент вызова метода finalize() не определен.
Более того, программа может завершиться до вызова finalize().
Также переопределение метода finalize() не дает сборщику мусора сразу
удалить объект, и такие объекты складываются в специальную очередь на
обработку. Если эта очередь будет заполняться быстрее, чем выполняется
вызов методов finalize(), то можно получить OutOfMemoryError.
Все эти причины привели к тому, что на текущий момент переопределение
метода finalize() является плохим стилем, и не рекомендуется к
использованию.

4.

Метод clone()
Метод clone() предназначен для создания копии объекта.
Реализация метода clone() по умолчанию создает точную бинарную
копию объекта, т.е. все поля нового объекта будут равны полям
исходного объекта.
Это удобно для примитивных типов, но для переменной ссылочного
типа копируется только значение переменной, а объект, на который
она указывает, остается тем же.
Не для всех объектов это будет корректным, поэтому по умолчанию
клонирование отключено, и при вызове clone() летит исключение.
Чтобы включить клонирование нужно реализовать интерфейс
Cloneable, в котором нет ни одного метода.

5.

Метод toString()
Метод toString() преобразует объект в строку.
Например, это автоматически происходит при сложении
объекта со строкой.
Реализация по умолчанию для класса Object выводит имя
класса в специальной форме и хеш объекта. Эта реализация
не особо информативна, поэтому рекомендуется
переопределять этот метод для всех классов с данными,
хотя бы для целей отладки.

6.

Метод equals()
Метод equals() возвращает true, если объекты равны, и false
иначе.
Контракт метода equals():
• x.equals(x) == true
• x.equals(null) == false
• Если x.equals(y), то и y.equals(x)
• Если x.equals(y) и y.equals(z), то и x.equals(z)
• x.equals(y) должен возвращать одно и то же значение,
если состояние объектов x и y не меняется

7.

Метод hashCode()
Метод hashCode() возвращает хеш-код объекта.
Контракт метода hashCode():
• Если x.equals(y), то x.hashCode() == y.hashCode()
• Если x.hashCode() != y.hashCode(),
то x.equals(y) == false
• x.hashCode() возвращает одно и то же значение,
если состояние объекта x не изменяется

8. Определение классов

9.

Интерфейсы
• Интерфейс содержит только public методы и public static final поля
• Интерфейс не содержит реализации методов (кроме default)
• Интерфейс только определяет контракт, тогда как абстрактный
класс предлагает реализацию по умолчанию
• default-методы предназначены для расширения контрактов
уже существующих интерфейсов в новых версиях (как самой Java,
так и библиотек или framework’ов), чтобы не ломать
обратную совместимость для существующих реализаций
интерфейса

10.

Пример внутреннего static-класса
public class Question {
private Type type;
public Type getType() {
return type;
Обращение к внутреннему static-классу
}
public void setType(Question.Type type) {
this.type = type;
Внутренний static-класс
}
public static class Type {
public static final Type SINGLE_CHOICE = new Type();
public static final Type MULTI_CHOICE = new Type();
public static final Type TEXT = new Type();
private Type() {
}
}
}

11.

Пример внутреннего класса
class List {
private Object[] array;
Создание экземпляра
public void print() {
Iterator iter = this.new Iterator();
Object obj;
do {
Внешний объект
obj = iter.getNext();
System.out.println(obj);
} while (obj != null);
Внутренний класс
}
private class Iterator {
private int index = 0;
Обращение к полю
внешнего объекта
public Object getNext() {
return (index < array.length) ? array[index++] : null;
}
}
}

12.

Пример локального класса
class Handler {
public void handle(String requestPath) {
Локальный класс
class Path implements HasSize {
private List<String> parts;
private String path = "/";
Path(String path) {
this.path = path;
this.parts = Arrays.asList(path.split("/"));
}
int size() { return parts.size(); }
String get(int i) { return this.parts.get(i); }
boolean startsWith(String s) { return path.startsWith(s); }
}
Path path = new Path(PATH_PREFIX + requestPath);
Создание экземпляра
if (path.startsWith("/page")) {
String pageId = path.get(1);
Вызов методов
// ...
}
локального класса
if (path.startsWith("/post")) {
String categoryId = path.get(1);
String postId = path.get(2);
// ...
}
// ...
}
}

13.

Анонимные классы
Анонимный класс похож на локальный класс. Он также объявляется
внутри метода, но имеет более простой синтаксис и, ко всему прочему, не
имеет имени. Синтаксис также накладывает ограничения: анонимный
класс всегда является наследником какого-либо класса или интерфейса,
причем только одного. Объявление анонимного класса невозможно без
создания экземпляра этого класса, причем ровно одного.
Анонимный класс
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Cell cell = field.getCell(buttonX, buttonY);
cell.onClick();
}
});

14.

Использование анонимных классов
class Result {
// Поля результата
}
interface Callback {
void execute(Result result);
}
Вызываем сервис,
class Client {
а когда получим
public static void main(String[] args) {
Service service = new Service();
ответ – обработаем
service.executeRemote(new Callback() {
результат
@Override
public void execute(Result result) {
System.out.println(result);
}
});
}
Библиотечный класс
}
class Service {
public void executeRemote(Callback callback) {
Result result = new Result();
// Сделать удаленный вызов, записать результат в Result
callback.execute(result);
}
}

15. Перерыв 

Перерыв

16.

Перечисления
Перечисление – специальный класс, имеющий ограниченное, заранее
заданное число экземпляров, каждый из которых помечен именем.
Дополнительные экземпляры перечисления создать нельзя.
Перечисления могут иметь поля, конструкторы с параметрами, а также
методы.
Все перечисления неявно наследуются от класса Enum, содержащего
методы:
• name() – возвращает им константы.
• ordinal() – возвращает порядковый номер константы в enum’е.
• toString() – возвращает строковое представление объекта.
• valueOf() – позволяет найти объект enum’а по имени константы.
• values()

17.

Примеры перечислений
enum Month {
JANUARY(Season.WINTER),
FEBRUARY(Season.WINTER),
MARCH(Season.SPRING),
APRIL(Season.SPRING),
MAY(Season.SPRING),
JUNE(Season.SUMMER),
JULY(Season.SUMMER),
AUGUST(Season.SUMMER),
SEPTEMBER(Season.AUTUMN),
OCTOBER(Season.AUTUMN),
NOVEMBER(Season.AUTUMN),
DECEMBER(Season.WINTER);
private final Season season;
Month(Season season) {
this.season = season;
}
public Season getSeason() {
return season;
}
}
enum Season {
WINTER,
SPRING,
SUMMER,
AUTUMN
}
Если ниже что-то объявлено –
точка с запятой обязательна

18.

Полиморфизм перечислений
В перечислениях можно создавать абстрактные методы. В этом случае для
каждой константы необходимо описать реализацию этих методов.
enum SaveStrategy {
TO_FILE() {
@Override
public void save(Context object) {
// Сохранение в файл
}
},
TO_DATABASE() {
@Override
public void save(Context object) {
// Сохранение в БД
}
};
public abstract void save(Context object);
}

19.

Аннотации
Аннотации – специальные модификаторы, добавляемые к элементам языка.
Аннотации имеют имя, начинающееся с символа @, и могут добавляться к
пакетам, классам, полям, методам, конструкторам, параметрам метода,
локальным переменным, а также к другим аннотациям.
Аннотации применяются для привязки метаинформации, которая может
использоваться как на этапе компиляции (если подключены процессоры
аннотаций), так и на этапе выполнения программы.
Например, документирующая аннотация @Override на методе говорит о том,
что метод перегружен, и заменяет реализацию родительского класса.
Существуют также метааннотации, которые определяют область
использования аннотации (@Target) и доступность во время компиляции и во
время выполнения (@Retention).

20.

Методы аннотаций
Аннотации могут содержать методы. Это не методы в обычном понимании.
Это точки доступа к значениям, содержащимся в аннотации.
Для каждого такого метода можно объявить значение по умолчанию.
В момент добавления аннотации необходимо задать значения всех полей
(кроме тех, у которых есть значение по умолчанию).
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Inject {
boolean required() default false;
}
class Link {
@Inject(required = true)
public String url;
@Inject
public String name;
}

21.

Зависимости
Когда в реализации класса A мы используем объект другого класса B,
то для компиляции класса A нам нужно иметь реализацию класса B.
Это называется зависимостью времени компиляции
класса A от класса B.
Если же наш алгоритм вместо объекта класса B использует объект с
интерфейсом I (который класс B реализует), то для компиляции
класса A достаточно иметь интерфейс I, реализация класса B не нужна.
Это называется зависимостью времени выполнения
класса A от класса B.
В случае зависимости времени выполнения говорят, что класс A не
знает про класс B, хотя объект класса A использует объект класса B.

22.

Примеры зависимостей
Зависимости
времени компиляции
Shape
Wall
Circle
House
Зависимость
времени выполнения
Painter
Shape
Класс Painter не знает про класс Circle,
но объект класса Painter использует объект класса Circle
Circle

23.

Зависимость времени выполнения
abstract class Shape {
abstract void paint();
}
class Circle extends Shape {
void paint() {
}
}
class Painter {
void draw(Shape shape) {
shape.paint();
}
}
class Main {
public static void main(String[] args) {
new Painter().draw(new Circle());
}
}

24.

Компонентная архитектура
Our WS
Other WS
Service
UI
Database

25. Сборка мусора

26.

Жизненный цикл объекта
Для того, чтобы использовать объект, его вначале нужно создать
специальным оператором (обычно new).
При создании объекта выделяется память под его переменные.
Для инициализации объекта используется конструктор.
Для удаления объекта и освобождения памяти есть две стратегии:
• Ручное управление с использованием оператора удаления (обычно
delete). Перед очисткой памяти вызывается деструктор.
• Автоматическое управление с использованием сборщика мусора.
Сборщик мусора – прикладной thread, запускаемый средой выполнения
для очистки памяти, занимаемой неиспользуемыми объектами.

27.

Сборка мусора
Когда на объект не остается ни одной ссылки, он становится доступным для
сборки мусора. Сборка мусора осуществляется в произвольный момент
времени (обычно – когда кончается доступная свободная память), который
нельзя контролировать программно.
Память под загруженные классы, а также под static-переменные этих классов
не освобождается. Таким образом, если в static-переменной разместить
большой объект, и потом его не использовать, то эффект будет аналогичным
утечке памяти в языках с ручным управлением памятью.
P.S. На самом деле освобождается, но только в том случае, если не остается ни
одной ссылки на объекты этих классов, на сами классы, а также на объект типа
ClassLoader, которым эти классы были загружены. В обычном приложении
можно считать, что эта память не освобождается.

28.

Способы сборки мусора
Подсчет ссылок
+ Простой
+ Не требует простоя
- Не очищает циклы
- Дополнительная нагрузка на память и процессор
- Не работает в условиях многопоточности
Транзитивное замыкание ссылок
Статические переменные – живые
Локальные переменные потоков – живые
Остальные объекты – мусор
Во время сборки мусора граф не должен меняться,
следовательно, необходимо останавливать работу JVM

29.

Serial GC
Включается опцией -XX:+UseSerialGC
Все новые объекты создаются в зоне Eden.
Eden и Suvivor относятся к младшему поколению, Tenured – к старшему.
Объекты, пережившие хотя бы одну сборку мусора, копируются
в зоны Survivor. Одна из зон Survivor всегда будет пустой.
И, наконец, долгоживущие объекты оказываются в зоне Tenured.

30.

Serial GC – первая сборка

31.

Serial GC – вторая сборка

32.

Serial GC – места пока хватает

33.

Serial GC – после N сборок

34.

Serial GC – полная сборка

35.

Serial GC – особенности
Вся сборка мусора происходит в режиме STW-паузы.
Большие объекты сразу создаются в зоне Tenured.
Если после увеличения кучи до максимума и сборки мусора
памяти все равно не хватает – летит OutOfMemoryError.
По умолчанию относительные размеры регионов следующие:
Tenured – 2/3 всей памяти
Eden – (1/3) * (8/10) всей памяти
Suvivor (каждая) – (1/3) * (1/10) всей памяти

36.

Parallel GC – отличия
Включается опцией -XX:+UseParallelGC.
Несколько потоков работают параллельно. Число потоков
по умолчанию определяется количеством процессорных ядер.
Может самостоятельно подстраиваться под параметры
производительности (максимальное время сборки и пропускную
способность), используя статистику по предыдущим сборкам.
Порядок приоритета по параметрам производительности:
Снижение времени паузы
Повышение пропускной способности
Минимизация используемой памяти
Рекомендуется либо управлять размерами вручную, либо задавать
требуемые параметры производительности, но не все вместе.

37.

Parallel GC – сборка

38.

Concurrent Mark Sweep – отличия
Включается опцией -XX:+UseConcMarkSweepGC.
Выполняется параллельно с работой программы без STW-паузы.
Сборка старшего поколения работает только с зоной Tenured.
Сборка старшего поколения работает постоянно в фоновом режиме.
При сборках в старшем поколении не производится дефрагментация
памяти, т.к. параллельно с работающим приложением это сложно.
В младшем поколении сборка аналогична Parallel GC.
Если память все-таки заканчивается, то происходит STW-пауза,
и сборка производится так же, как в Parallel GC.
Из-за фрагментации рекомендуется на 20% больше памяти,
чем предыдущим сборщикам мусора.

39.

Concurrent Mark Sweep – алгоритм
Останавливает все потоки, помечает объекты, доступные напрямую
из корневых.
Возобновляет работу потоков, ищет все объекты, доступные из
помеченных ранее живых объектов.
Еще раз останавливает все потоки, ищет живые объекты, которые
были пропущены при первой паузе.
Возобновляет работу потоков, производится очистка мусора
в нескольких потоках в параллельном режиме.

40.

Concurrent Mark Sweep – алгоритм

41.

Concurrent Mark Sweep – настройка
Актуальны все настройки для Parallel GC
–XX:CMSInitiatingOccupancyFraction=? задает порог заполненности
зоны Tenured в процентах, после которого происходит STW-пауза и
полная сборка мусора.

42.

G1 GC
Включается опцией -XX:+UseG1GC.
Предполагался для работы с большим размером кучи (4 Гб и выше).
Память разделяется на регионы одинакового размера, за исключением
"громадных", получающихся путем объединения обычных.

43.

G1 GC
Малые сборки – аналогично Parallel GC с STW-паузой, но только над
частью зон, а не над всеми, чтобы не превысить допустимое время
сборки.
Для сборок выбираются регионы, где, предположительно, больше
всего мусора (поэтому и Garbage First).
Параллельно с приложением производится пометка объектов
аналогично CMS с двумя STW-паузами.
На последней фазе – поиск свободных зон для смешанных сборок.
После пометки к каждой малой сборке начинают добавляться
несколько зон из старшего поколения (смешанные сборки).
Если нет свободных регионов – производится полная сборка мусора.

44.

G1 GC – громадные зоны
Громадный объект – занимает более половины зоны.
Громадные объекты никогда не перемещаются во время
сборок.
Громадные объекты могут удаляться в процессе пометки
или при полной сборке.
Громадный объект – один в зоне, даже если там еще есть
место.
English     Русский Rules