1.Java Core
Класс Object
Типы данных
Для каждого объекта JVM хранит
Структура заголовка объекта
Java объект состоит из
Размер ссылки
Типы ссылок на объекты
Группировка полей
По значению или по ссылке?
Почему String в Java является immutable
Модификаторы доступа в Java и ключевые слова
Рефлексия и анотации
Исключения
Внутренние классы
Enum
Generics
Collections
List
Set
Map
2.Модель памяти в Java
Общие данные
Где хранятся данные
Java 8 Metaspace это замена PermGen
Локальные переменные в Java
GC
3.Инициализация, загрузчики классов
Собственные загрузчики
Процесс загрузки класса
Виды загрузчиков
Загрузчики классов
Порядок инициализации
4.ООП
Интерфейс и абстрактный класс
5. AOP
6. SQL
7. Concurrency
В чем разница между volatile и synchronized?
Object это базовый класс для всех остальных объектов в Java. Каждый класс наследуется от Object. Соответственно все классы наследуют методы класса Object.
Методы класса Object:
- public final native Class getClass()
- public native int hashCode()
- public boolean equals(Object obj)
- protected native Object clone() throws CloneNotSupportedException
- public String toString()
- public final native void notify()
- public final native void notifyAll()
- public final native void wait(long timeout) throws InterruptedException
- public final void wait(long timeout, int nanos) throws InterruptedException
- public final void wait() throws InterruptedException
- protected void finalize() throws Throwable
byte (8 бит - [-127, +128]) - наименьший по размеру целочисленный тип, полезен для работы с данными поступающими из сети или файла. Данный тип также хорош для манипуляции необработанными двоичными данными, которые не совместимы напрямую с другими типами данных.
short (16 бит \ -32768 до +32767)
int (32 бита) - используется наиболее часто. В выражениях типы short и byte "повышаются" до int после чего происходят вычисления - так что иногда лучше сразу использовать int - чтобы избежать затрат на подобное неявное преобразование.
long (64 бит) - целочисленный тип, который используют тогда, когда диапазона int недостаточно
char (16 бит \ от 0 до 65536) - "целочисленный" тип и используется для хранения символов в 2 байта каждый (Unicode - десятки символов разных азбук и цифр) - отрицательных значений данного типа не определено.
float (32 бита) - числа с десятичной частью - в ряде процессов обрабатываются быстрее, чем числа с повышенной точною - но этой самой точности как раз таки иногда не хватает
double (64 бита) - числа с десятичной частью (повышенная - "двойная" точность) - например sin, cos и sqrt возвращают именно значения этого типа.
boolean - "логический" тип данных. Присваиваются значения типа true или false - то есть всего два возможных
int a = 300; это 4-х байтная переменная, которая содержит значение из стека;
Integer b = 301; ссылочная переменная и сам объект, на который эта переменная ссылается
###Каждый заголовок может содержать следующую информацию:
- Маркировочное слово (mark word) — к сожалению мне так и не удалось найти назначение этой информации, подозреваю что это просто зарезервированная на будущее часть заголовка.
- Hash Code — каждый объект имеет хеш код. По умолчанию результат вызова метода Object.hashCode() вернет адрес объекта в памяти, тем не менее некоторые сборщики мусора могут перемещать объекты в памяти, но хеш код всегда остается одним и тем же, так как место в заголовке объекта как раз может быть использовано для хранения оригинального значения хеш кода.
- Garbage Collection Information — каждый java объект содержит информацию нужную для системы управления памятью. Зачастую это один или два бита-флага, но также это может быть, например, некая комбинация битов для хранения количества ссылок на объект.
- Type Information Block Pointer — содержит информацию о типе объекта. Этот блок включает информацию о таблице виртуальных методов, указатель на объект, который представляет тип и указатели на некоторые дополнительные структуры, для более эффективных вызовов интерфейсов и динамической проверки типов.
- Lock — каждый объект содержит информацию о состоянии блокировки. Это может быть указатель на объект блокировки или прямое представление блокировки.
- Array Length — если объект — массив, то заголовок расширяется 4 байтами для хранения длины массива.
###Integer весит:
Integer в нашей 32-х разрядной HotSpot JVM.
Все поля, которые не объявлены как static.
Из таких только одно — int value.
Заголовок: 8 байт
Поле int: 4 байта
Выравнивание для кратности 8 : 4 байта
Итого: 16 байт
###String весит:
private final char value[];
private final int offset;
private final int count;
private int hash;
Заголовок: 8 байт
Поля int: 4 байта * 3 == 12 байт
Ссылочная переменная на объект массива: 4 байта
Итого: 24 байта
Cтрока содержит ссылку на массив символов, мы имеем дело с двумя разными объектами — объектом класса String и массивом, который хранит строку.
К полученному размеру нужно добавить и размер выделенного для символов массива.
А это еще 12 байт на сам объект массива + 2 байта на каждый символ строки.
Не забываем добавлять выравнивание для кратности 8 байтам.
Итого в конечном итоге простая, казалось бы, строка new String(«a») выливается в:
new String()
Заголовок: 8 байт
Поля int: 4 байта * 3 == 12 байт
Ссылочная переменная на объект массива: 4 байта
Итого: 24 байта
new char[1]
Заголовок: 8 байт + 4 байта на длину массива == 12 байт
Примитивы char: 2 байта * 1 == 2 байта
Выравнивание для кратности 8 : 2 байта
Итого: 16 байта
Итого, new String("a") == 40 байт
###Размер ссылкиРазмер ссылки в JVM зависит от ее разрядности, подозреваю, что для оптимизации. Поэтому в 32-х разрядных JVM размер ссылки обычно 4 байта, а в 64-х разрядных — 8 байт. Хотя это условие и не обязательно.
###Группировка полейJVM проводит предварительную группировку полей объекта.
Это значит, что все поля класса размещаются в памяти в определенном порядке, а не так как объявлены. Порядок группировки выглядит так:
- 8-ми байтовые типы(double и long)
- 4-х байтовые типы(int и float)
- 2-х байтовые типы(short и char)
- Одно байтовые типы(boolean и byte)
- Ссылочные переменные
В Java существует 4 типа ссылок на объекты:
- strong reference
- soft reference
- weak reference
- phantom reference
В Java объекты, создаваемые через оператор new создаются по strong ссылке. Сборщик мусора (garbage collector) уничтожает такие объекты только тогда, когда на них больше не остается сильных (strong) ссылок.
В пакете java.lang.ref есть 3 класса, которые описывают оставшиеся 3 типа ссылок, соответственно SoftReference, WeakReference, PhantomReference.
Объекты, созданные через SoftReference, будут собраны в случае, если JVM требует память. То есть имеется гарантия, что все soft reference объекты будут собраны перед тем, как JVM выбросит OutOfMemoryError. SoftReference часто используется для кешей, потребляющих большое количество памяти.
WeakReference не спасает объект от финализации, даже если имеется достаточное количество свободной памяти. Как только на объект не останется strong и soft ссылок, он может быть финализирован. Используется для кешей и для создания цепей связанных между собой объектов.
Объекты, созданные через PhantomReference, уничтожаются тогда, когда GC определяют, что ссылаемые объекты могут быть освобождены. Этот тип ссылок используется как альтернатива финализации (для более гибкого освобождения ресурсов).
###По значению или по ссылке В Java объекты всегда передаются по ссылке, а примитивы - по значению-
Примитивы (int, double, long, ...) передаются по значению (копируется значению переменной).
-
Объекты передаются по ссылке (имеется ввиду что передаётся сама ссылка на объект)
Передача по ссылке подразумевает передачу ссылки на объект. В этом случае реализация метода потенциально может модифицировать переданный объект (например, вызвав метод, изменяющий состояние объекта).
В случае передачи по значению параметр копируется. Изменение параметра не будет заметно на вызывающей стороне.
###Почему String в Java является immutable 1) Безопасность. String широко используется , как параметр для многих классов Java, в частности для открытия сетевых соединений, подключений к БД, открытию файлов и пр. И если бы строка изменялась, то мы могли получить доступ к объекту (файлу например), на который мы имеем право, затем изменить строку с именем (случайно или намеренно) и получить доступ уже к другому файлу.Так же String используется в механизме загрузки файлов, и это -- фундаментальный аспект. И если бы строка изменялась, то запрос на загрузку "java.io.Writer" мог бы быть изменён на "DiskErasingWriter".
-
Hashcode Из-за того, что строка не изменяется, она кэширует свой хэшкод и не вычисляет его каждый раз, когда мы его вызываем, что делает строку очень быстрой как ключ для hashmap.
-
Многопоточность immutable делает экземпляры строк thread-safe.
-
Модификаторы доступа (общие) без спецификатора - доступен только в пределах пакета public - доступен везде
-
Модификатор protected
Модификатор protected делает член класса или интерфейса видимым только в классе или интерфейсе и во всех производных классах текущего класса. Код за пределами текущего класса не может получить доступ к членам с модификатором protected.
-
Модификатор private
- private (для полей) - доступен в пределах класса.
- private (для метода) - доступен в пределах класса, модификатор final использовать необязательно. В подклассе невозможно будет переопределить метод. Метод перестаёт являться частью интерфейса базового класса. Одинаковое имя методов в подклассе и в базовом классе не будет являтся переопределением или перегрузкой метода. Это будут два независимых метода.
- private (для внутреннего класса) - доступен в пределах внешнего класса. Создание объекта только через методы внешнего класса.
- private (для конструктора) - создание объекта возможно только через статический метод с указанным возвратным типом имени этого класса.
-
Модификатор final
- final class - делает метод или класс терминальным без возможности расширения класса или переопределения метода. Класс лишается наследования.
- final для полей (примитивного типа) - устанавливает поле как константу, которую нельзя изменить.
- final для полей (ссылка на объект) - когда ссылка будет связана с объектом, она уже не сможет указывать на другой объект. Сам объект при этом может изменяться.
- final для полей (не инициализированых) - не инициализируются значениями по умолчанию, такие поля нужно обязательно инициализировать в конструкторе. Как для примитивов, так и для ссылок на объекты.
- final в списке аргументов метода - переменная становится терминальной. Доступна для анонимного класса созданного внутри метода. А также, метод не может изменить значение, на которое указывает передаваемая ссылка.
void f(final int i) { //! i++; } // запрещено;
int f(final int i) { retun i + 1; } // разрешено;
-
Модификатор static
- static - поле будет существовать в одном единственном экземляре для всех экземпляров. Статические объекты не переопределяются повторно.
- static - к внутреннему классу, будет называться вложенным классом.
- static - для метода, возможность вызова метода без объекта(экземпляра). Обращаться можно непосредственно через класс имя_класса.имя_метода. Метод не может обращаться к не статичным полям.
Рефлексия (от позднелат. reflexio - обращение назад) - это механизм исследования данных о программе во время её выполнения. Рефлексия позволяет исследовать информацию о полях, методах и конструкторах классов. Можно также выполнять операции над полями и методами которые исследуются. Рефлексия в Java осуществляется с помощью Java Reflection API. Этот интерфейс API состоит из классов пакетов java.lang и java.lang.reflect. С помощью интерфейса Java Reflection API можно делать следующее:
- Определить класс объекта.
- Получить информацию о модификаторах класса, полях, методах, конструкторах и суперклассах.
- Выяснить, какие константы и методы принадлежат интерфейсу.
- Создать экземпляр класса, имя которого неизвестно до момента выполнения программы.
- Получить и установить значение свойства объекта.
- Вызвать метод объекта.
- Создать новый массив, размер и тип компонентов которого неизвестны до момента выполнения программ.
Аннотация - средство, которое позволяет встроить информацию поддержки в исходные файлы, то есть аннотации можно использовать для отслеживания ошибок, устранения предупреждений, генерации кода, XML файлов.
Встроенные аннотации
В Java определено много полезных встроенных аннотаций, большинство из их являются специализированными. Аннотации, что имеют общее назначение:
- @Retention - эта аннотация предназначена для применения только в качестве аннотации к другим аннотациям. Определяет политику удержания.
- @Documented - это маркер-интерфейс, который сообщает инструменту, что аннотация должна быть документирована.
- @Target - эта аннотация задает тип объявления, к которым может быть применима аннотация. Принимает один аргумент, который должен быть константой из перечисления ElementType. Например, чтобы указать, что аннотация применима только к полям и локальным переменным: @Targer({ ElementType.FIELD, ElementTyle.LOCAL_VARIABLE } )
- @Inherited - это аннотация-маркер, которая может применяться в другом объявление аннотации, она касается только тех аннотаций, что будут использованы в объявлениях классов. Эта аннотация позволяет аннотации супер класса быть унаследованной в подклассе.
- @Override - аннотация-маркер, которая может применяться только к методам. Метод, аннотированный как @Override, должен переопределять метод супер класса.
- @Deprecated - указывает, что объявление устарело и должно быть заменено более новой формой.
- @SafeVarargs - аннотация-маркер, применяется к методам и конструкторам. Она указывает, что никакие небезопасные действия, связанные с параметром переменного количества аргументов, недопустимы. Применяется только к методам и конструкторам с переменным количеством аргументов, которые объявлены как static или final.
- @SuppressWarnings - эта аннотация указывает, что одно или более предупреждений, которые могут быть выданы компилятором следует подавить.
Существует 3 политики удержания аннотации. Политика удержания определяет, в какой точке аннотация сбрасывается.
Такие политики инкапсулированы в перечисление java.lang.annotation.RetentionPolicy. Это SOURSE,CLASS,RUNTIME.
Аннотации с политикой SOURCE содержаться только в исходном файле и отбрасываются при компиляции.
Аннотации с политикой Class сохраняются в файле, однако они недоступны JVM во время выполнения.
Аннотации с политикой удержания RUNTIME сохраняются в файле во время компиляции и остаются доступными JVM во время выполнения.
###Исключения В Java есть два типа исключений, checked и unchecked. + Checked исключения, это те, которые должны обрабатываться блоком catch или описываться в сигнатуре метода. Unchecked могут не обрабатываться и не быть описанными. + Unchecked исключения в Java - наследованные от RuntimeException, checked - от Exception (не включая unchecked). Пример unchecked исключения - NullPointerException, checked исключения - IOException.Они все наследуются от Throwable
###Внутренние классыВложенные классы делятся на статические и нестатические.
Собственно нестатические вложенные классы имеют и другое название - внутренние классы (inner classes).
Внешний класс (outer class) мы иногда будем называть еще обрамляющим классом.
-
Статические вложенные классы (static nested classes)
Статические вложенные классы, не имеют доступа к нестатическим полям и методам обрамляющего класса, что в некотором роде аналогично статическим методам, объявленным внутри класса. Доступ к нестатическим полям и методам может осуществляться только через ссылку на экземпляр обрамляющего класса. В этом плане static nested классы очень похожи на любые другие классы верхнего уровня.
Кроме этого, static nested классы имеют доступ к любым статическим методам внешнего класса, в том числе и к приватным.
Польза данных классов заключается в основном в логической группировке сущностей, в улучшении инкапсуляции, а также в экономии class-space.
Внутренние классы в Java делятся на такие три вида:
- внутренние классы-члены (member inner classes);
- Внутренние классы-члены (member inner classes)
Внутренние классы-члены ассоциируются не с самим внешним классом, а с его экземпляром. При этом они имеют доступ ко всем его полям и методам.
- Внутренние классы-члены (member inner classes)
- локальные классы (local classes);
- Локальные классы (local inner classes)
Локальные классы (local classes) определяются в блоке Java кода. На практике чаще всего объявление происходит в методе некоторого другого класса. Хотя объявлять локальный класс можно внутри статических и нестатических блоков инициализации.
- Локальные классы (local inner classes)
- анонимные классы (anonymous classes).
- Анонимные классы (anonymous inner classes) Анонимные классы являются важным подспорьем в повседневной жизни Java-программистов. Анонимный класс (anonymous class) - это локальный класс без имени.
Использование анонимных классов оправдано во многих случаях, в частности когда:
- тело класса является очень коротким;
- нужен только один экземпляр класса;
- класс используется в месте его создания или сразу после него;
- имя класса не важно и не облегчает понимание кода.
Перечисление - это класс
Объявляя enum мы неявно создаем класс производный от java.lang.Enum. Условно конструкция enum Season { ... } эквивалентна class Season extends java.lang.Enum { ... }. И хотя явным образом наследоваться от java.lang.Enum нам не позволяет компилятор, все же в том, что enum наследуется, легко убедиться с помощью reflection.
Элементы enum Season (WINTER, SPRING и т.д.) - это статически доступные экземпляры enum-класса Season. Их статическая доступность позволяет нам выполнять сравнение с помощью оператора сравнения ссылок ==.
С помощью enum в Java можно реализовать иерархию классов, объекты которой создаются в единственном экземпляре и доступны статически. При этом элементы enum могут содержать собственные конструкторы.
###GenericsОбобщённое программирование — это такой подход к описанию данных и алгоритмов, который позволяет их использовать с различными типами данных без изменения их описания.
Обобщения - это параметризованные типы. С их помощью можно объявлять классы, интерфейсы и методы, где тип данных указан в виде параметра. Обобщения добавили в язык безопасность типов.
Обобщения позволяет указать, во время компиляции, типы объектов, вы хотите сохранить в коллекции. Затем, когда вы получите и добавить элементы из списка, список уже знает, что, как предполагается типы объектов, которые будут выполнены.
В именах переменных типа принято использовать заглавные буквы. Обычно для коллекций используется буква E, буквами K и V - типы ключей и значение (Key/Value), а буквой T (и при необходимости буквы S и U) - любой тип.
В библиотеке коллекций Java существует два базовых интерфейса, реализации которых и представляют совокупность всех классов коллекций:
- Collection - коллекция содержит набор объектов (элементов). Здесь определены основные методы для манипуляции с данными, такие как вставка (add, addAll), удаление (remove, removeAll, clear), поиск (contains)
- Map - описывает коллекцию, состоящую из пар "ключ — значение". У каждого ключа только одно значение, что соответствует математическому понятию однозначной функции или отображения (тар). Такую коллекцию часто называют еще словарем (dictionary) или ассоциативным массивом (associative array). Никак НЕ относится к интерфейсу Collection и является самостоятельным.
Интерфейс Collection не является базовым. Интерфейс Collection расширяет интерфейс Iterable, у которого есть только один метод iterator(). Это значит что любая коллекция, которая есть наследником Iterable должна возвращать итератор.
Итератор - объект, абстрагирующийся за единым интерфейсом доступ к элементам коллекции. Итератор это паттерн позволяющий получить доступ к элементам любой коллекции без вникания в суть ее реализации.
Идем дальше. Как видим с рисунка, интерфейс Collection расширяют интерфейсы List, Set и Queue. + List - Представляет собой неупорядоченную коллекцию, в которой допустимы дублирующие значения. Иногда их называют последовательностями (sequence). Элементы такой коллекции пронумерованы, начиная от нуля, к ним можно обратиться по индексу. + Set - описывает неупорядоченную коллекцию, не содержащую повторяющихся элементов. Это соответствует математическому понятию множества (set). + Queue - очередь. Это коллекция, предназначенная для хранения элементов в порядке, нужном для их обработки. В дополнение к базовым операциям интерфейса Collection, очередь предоставляет дополнительные операции вставки, получения и контроля.
####List- ArrayList инкапсулирует в себе обычный массив, длина которого автоматически увеличивается при добавлении новых элементов.
Так как ArrayList использует массив, то время доступа к элементу по индексу минимально (В отличии от LinkedList). При удалении произвольного элемента из списка, все элементы находящиеся «правее» смещаются на одну ячейку влево, при этом реальный размер массива (его емкость, capacity) не изменяется.
Если при добавлении элемента, оказывается, что массив полностью заполнен, будет создан новый массив размером (n * 3) / 2 + 1, в него будут помещены все элементы из старого массива + новый, добавляемый элемент.
+ **LinkedList** - Двусвязный список.
Это структура данных, состоящая из узлов, каждый из которых содержит как собственно данные, так и две ссылки («связки») на следующий и предыдущий узел списка.
**Доступ к произвольному элементу осуществляется за линейное время** (но доступ к первому и последнему элементу списка всегда осуществляется за константное время — ссылки постоянно хранятся на первый и последний, так что добавление элемента в конец списка вовсе не значит, что придется перебирать весь список в поисках последнего элемента). В целом же, LinkedList в абсолютных величинах проигрывает ArrayList и по потребляемой памяти и по скорости выполнения операций.
+ **Преимущества ArrayList**: в возможности доступа к произвольному элементу по индексу за постоянное время (так как это массив), минимум накладных расходов при хранении такого списка, вставка в конец списка в среднем производится так же за постоянное время.
* При удалении произвольного элемента из списка, все элементы находящиеся «правее» смещаются на одну ячейку влево, при этом реальный размер массива (его емкость, capacity) не изменяется.
Для эффективного удаления из ArrayList нужно выполнить смещение всех элементов, стоящих «правее» n+m позиции на n элементов левее к началу списка. Таким образом, вместо выполнения n итераций перемещения элементов списка, все выполняется за 1 проход.
- LinkedList наоборот, за постоянное время может выполнять вставку/удаление элементов в списке. Доступ к произвольному элементу осуществляется за линейное время. LinkedList предпочтительно применять, когда происходит активная работа (вставка/удаление) с серединой списка или в случаях, когда необходимо гарантированное время добавления элемента в список.
-
HashSet - коллекция, не позволяющая хранить одинаковые объекты(как и любой Set). HashSet инкапсулирует в себе объект HashMap (то-есть использует для хранения хэш-таблицу).
Хеш-таблица хранит информацию, используя так называемый механизм хеширования, в котором содержимое ключа используется для определения уникального значения, называемого хеш-кодом. Этот хеш-код затем применяется в качестве индекса, с которым ассоциируются данные, доступные по этому ключу. Преобразование ключа в хеш-код выполняется автоматически — вы никогда не увидите самого хеш-кода. Также ваш код не может напрямую индексировать хеш-таблицу.
Выгода от хеширования состоит в том, что оно обеспечивает константное время выполнения методов add(), contains(), remove() и size() , даже для больших наборов.
Если Вы хотите использовать HashSet для хранения объектов СВОИХ классов, то вы ДОЛЖНЫ переопределить методы hashCode() и equals(), иначе два логически-одинаковых объекта будут считаться разными, так как при добавлении элемента в коллекцию будет вызываться метод hashCode() класса Object (который скорее-всего вернет разный хэш-код для ваших объектов).
Важно отметить, что класс HashSet не гарантирует упорядоченности элементов, поскольку процесс хеширования сам по себе обычно не порождает сортированных наборов. Если вам нужны сортированные наборы, то лучшим выбором может быть другой тип коллекций, такой как класс TreeSet. -
LinkedHashSet - поддерживает связный список элементов набора в том порядке, в котором они вставлялись. Это позволяет организовать упорядоченную итерацию вставки в набор. То есть, когда идет перебор объекта класса LinkedHashSet с применением итератора, элементы извлекаются в том порядке, в каком они были добавлены.
-
TreeSet - коллекция, которая хранит свои элементы в виде упорядоченного по значениям дерева. TreeSet инкапсулирует в себе TreeMap, который в свою очередь использует сбалансированное бинарное красно-черное дерево для хранения элементов. TreeSet хорош тем, что для операций add, remove и contains потребуется гарантированное время log(n).
- HashMap — основан на хэш -таблицах, реализует интерфейс Map (что подразумевает хранение данных в виде пар ключ/значение). Ключи и значения могут быть любых типов, в том числе и null. Данная реализация не дает гарантий относительно порядка элементов с течением времени. [Хорошая статья] (http://habrahabr.ru/post/128017/)
- LinkedHashMap - расширяет класс HashMap. Он создает связный список элементов в карте, расположенных в том порядке, в котором они вставлялись. Это позволяет организовать перебор карты в порядке вставки. То есть, когда происходит итерация по коллекционному представлению объекта класса LinkedHashMap, элементы будут возвращаться в том порядке, в котором они вставлялись. Вы также можете создать объект класса LinkedHashMap, возвращающий свои элементы в том порядке, в котором к ним в последний раз осуществлялся доступ. [Рекомендую так же прочитать] (http://habrahabr.ru/post/129037/)
- TreeMap - расширяет класс AbstractMap и реализует интерфейс NavigatebleMap. Он создает коллекцию, которая для хранения элементов применяет дерево. Объекты сохраняются в отсортированном порядке по возрастанию. Время доступа и извлечения элементов достаточно мало, что делает класс TreeMap блестящим выбором для хранения больших объемов отсортированной информации, которая должна быть быстро найдена. [Моя статья про TreeMap] (http://www.quizful.net/post/Java-TreeMap)
- WeakHashMap - коллекция, использующая слабые ссылки для ключей (а не значений). Слабая ссылка (англ. weak reference) — специфический вид ссылок на динамически создаваемые объекты в системах со сборкой мусора. Отличается от обычных ссылок тем, что не учитывается сборщиком мусора при выявлении объектов, подлежащих удалению. Ссылки, не являющиеся слабыми, также иногда именуют «сильными».
Permanent generation используется только JVM для хранения необходимых данных, в том числе метаданные о созданных объектах. изменение размера PG – дорогостоящая (трудоёмкая) операция.
Heap – основной сегмент памяти, где хранятся все ваши объекты.
Heap делится на два подсегмента, Old Generation и New Generation. New Generation в свою очередь делится на Eden и два сегмента Survivor.
При создании объекта, когда вы пишете что-то типа byte[] data = new byte[1024], создаётся в сегменте Eden.
Новые объекты создаются в Eden. Кроме собственно данных для нашего массива байт здесь есть ещё ссылка на эти данные.
Все обьекты обитают в куче и попадают туда при создании.
- обьект состоит из полей класса и методов.
- в куче выделяется место под сам обьект, количество выделенной памяти зависит от полей, если полем класса, к примеру, служит интовая переменная, то не важно, инициализируешь ты ее как "0" или как "1000000" - обьект займет в куче свои биты, + столько байт сколько вмещает тип инт (+32 бита), и так с каждым полем.
Все методы обитают в стеке и попадают туда при вызове.
- Переменные в методах так же имеют стековую память, по скольку они локальные.
- Если в методе создается обьект, то он помещается в кучу, но его ссылка все еще будет находится в стеке и после того как метод покинет стек - обьект станет жертвой сборщика мусора, так как ссылка на него утеряна, и из главного стека программы невозможно будет добраться до такого обьекта.
-
Регистры.
Это самое быстрое хранилище, потому что данные хранятся прямо внутри процессора. Однако количество регистров жестко ограничено, поэтому регистры используются компилятором по мере необходимости. У вас нет прямого доступа к регистрам, вы не сможете найти и малейших следов их поддержки в языке. (С другой стороны, языки C и C++ позволяют порекомендовать компилятору хранить данные в регистрах.)
-
Стек.
Эта область хранения данных находится в общей оперативной памяти (RAM), но процессор предоставляет прямой доступ к ней с использованием указателя стека. Указатель стека перемещается вниз для выделения памяти или вверх для ее освобождения. Это чрезвычайно быстрый и эффективный способ размещения данных, по скорости уступающий только регистрам. Во время обработки программы компилятор Java должен знать жизненный цикл данных, размещаемых в стеке. Это ограничение уменьшает гибкость ваших программ, поэтому, хотя некоторые данные Java хранятся в стеке (особенно ссылки на объекты), сами объекты Java не помещаются в стек.
-
Куча.
Пул памяти общего назначения (находится также в RAM), в котором размещаются все объекты Java. Преимущество кучи состоит в том, что компилятору не обязательно знать, как долго просуществуют находящиеся там объекты. Таким образом, работа с кучей дает значительное преимущество в гибкости. Когда вам нужно создать объект, вы пишете код с использованием new, и память выделяется из кучи во время выполнения программы. Конечно, за гибкость приходится расплачиваться: выделение памяти из кучи занимает больше времени, чем в стеке (даже если бы вы могли явно создавать объекты в стеке, как в C++). Постоянная память. Значения констант часто встраиваются прямо в код программы, так как они неизменны. Иногда такие данные могут размещаться в постоянной памяти (ROM), если речь идет о «встроенных» системах.
-
Не-оперативная память.
Если данные располагаются вне программы, они могут существовать и тогда, когда она не выполняется. Два основных примера: потоковые объекты (streamed objects), в которых объекты представлены в виде потока байтов, обычно используются для посылки на другие машины, и долгоживущие (persistent) объекты, которые запоминаются на диске и сохраняют свое состояние даже после окончания работы программы. Особенностью этих видов хранения данных является возможность перевода объектов в нечто, что может быть сохранено на другом носителе информации, а потом восстановлено в виде обычного объекта, хранящегося в оперативной памяти. В Java организована поддержка легковесного (lightweight) сохранения состояния, а такие механизмы, как JDBC и Hibernate, предоставляют более совершенную поддержку сохранения и выборки информации об объектах из баз данных.
основное отличие возможность динамически расширятся, органиченная по умолчанию только размером нативной памяти. П араметры PermSize и MaxPermSize отныне упразднены (получив эти параметры JVM будет выдавать предупреждение о том, что они более не действуют), и вместо них вводится опциональный параметр MaxMetaspaceSize, посредством которого можно задать ограничение на размер Metaspace.
В результате максимальный Metaspace по умолчанию не ограничен ничем кроме предела объёма нативной памяти. Но его можно по желанию ограничить параметром MaxMetaspaceSize, аналогичным по сути к MaxPermSize.
Таким образом можно будет избежать ошибки «java.lang.OutOfMemoryError: PermGen space» за счёт большей гибкости динамического изменения размера Metaspace. Но, конечно, если размер Metaspace достигнет своей границы — будь то максимум объёма нативной памяти, или лимит заданный в MaxMetaspaceSize — будет выброшено аналогичное исключение: «java.lang.OutOfMemoryError: Metadata space».
###Локальные переменные в Java Локальная переменная - любая переменная примитивного или ссылочного типа, объявленная внутри любого метода. Память для локальной переменной не выделяется в куче (heap) a **выделяется в стеке (call stack) метода**, который создаётся при вызове метода, по завершении работы метода стек уничтожается вместе с локальными переменными.Для локальных переменных не существует дефолтных значений, как это происходит для переменных экземпляров, например. При попытке использовать явно неинициализированную локальную переменную выдаётся ошибка компиляции - variable might not have been initialized.
###GC **Цель сборки мусора** заключается в обнаружении и уничтожении объектов, которые больше не используются программой, с целью освобождения ресурсов. Java-объект может подвергнуться сборке мусора, когда становится недоступным для использующей его программы.- Реализация сборщика мусора в разных JVM - разная.
- Алгоритм сборки мусора существует не один! Объект за один цикл работы GC не удаляется, а только может быть помечен для дальнейшего удаления. Хорошо еще сказать, как GC работает с различными ссылками (сильными, слабыми).
- Сборщик мусора выполняет свою работу, на сколько я знаю, когда заканчивается выделена память под приложение. Так же, можно вызывать сборщик мусора вручную, но выполнять работу в ту же минуту он не будет.
- Режим работы сборщика можно выставить при запуске JVM (т.е. вашей программы), читайте офф доку.
Классы загружаются по мере надобности, за небольшим исключением. Некоторые базовые классы из rt.jar (java.lang.* в частности) загружаются при старте приложения. Классы расширений ($JAVA_HOME/lib/ext), пользовательские и большинство системных классов загружаются по мере их использования.
###Виды загрузчиковВсе классы в Java загружаются с помощью загрузчиков классов.
Вначале работы программы создается 3 основных загрузчика классов:
- базовый загрузчик (bootstrap)
- загрузчик расширений (extention)
- системный загрузчик (system/application)
Помимо основных загрузчиков классов, существует возможность создания пользовательских загрузчиков классов.
Загрузчики классов являются иерархическими.
Загрузчик, который загружает основные системные классы, называется базовым (Bootstrap или Primordial) загрузчиком классов. Именно он загружает внутренние классы JDK и пакеты java.* (rt.jar и i18n.jar).
Важно заметить, что базовый загрузчик является «Изначальным или Корневым» и частью JVM, вследствие чего его нельзя создать внутри кода программы.
Загрузчик расширений – загружает различные пакеты расширений, которые располагаются в директории <JAVA_HOME>/lib/ext или другой директории, описанной в системном параметре java.ext.dirs. Это позволяет обновлять и добавлять новые расширения без необходимости модифицировать настройки используемых приложений. Загрузчик расширений реализован классом sun.misc.Launcher$ExtClassLoader.
Системный загрузчик – загружает классы, пути к которым указаны в переменной окружения CLASSPATH или пути, которые указаны в командном рядке после ключей –classpath или –cp. Системный загрузчик реализован классом sun.misc.Launcher$AppClassLoader.
###Собственные загрузчикиВ Java существует возможность создания собственных загрузчиков классов.
Собственные загрузчики классов используют все серверы приложений и web-контейнеры, что и понятно – приложения, разворачиваемые на сервере приложений, должны загружаться динамически, в противном случае перечисление в переменной CLASSPATH всех библиотек, используемых приложениями, становится задачей нетривиальной.
За создание пользовательских загрузчиков классов отвечает класс ClassLoader. Для того, что бы создать собственный загрузчик классов, необходимо унаследоваться от класса ClassLoader.
###Процесс загрузки класса Процесс загрузки класса состоит из трех частей:-
Loading
-
Linking
-
Initialization
-
Loading – на этой фазе происходит поиск и физическая загрузка файла класса в определенном источнике (в зависимости от загрузчика). Этот процесс определяет базовое представление класса в памяти. На этом этапе такие понятия как методы, поля и т.д. пока не известны.
-
Linking – процесс, который может быть разбит на 3 части:
- Bytecode verification – происходит несколько проверок байт-кода на соответствие ряду зачастую нетривиальных требований определенных в спецификации JVM (http://java.sun.com/docs/books/vmspec/).
- Class preparation – на этом этапе происходит подготовки структуры данных, отображающей поля, методы и реализованные интерфейсы, которые определены в классе.
- Resolving – разрешение все классов, которые ссылаются на текущий класс.
-
Initialization – происходит выполнение статических инициализаторов определенных в классе. Таким образом, статические поля инициализируются стандартными значениями.
Абстрактные классы используются только тогда, когда есть "is a" тип отношений; интерфейсы могут быть реализованы классами которые не связаны друг с другом.
Абстрактный класс может реализовывать методы; интерфейс не может реализовывать методы.
Интерфейс может только описывать константы и методы, но не реализовывать их. Все методы интерфейса по-умолчанию являются публичными (public) и абстрактными (abstract), а поля - public static final.
В Java класс может наследоваться (реализовывать) от многих интерфейсов, но только от одного абстрактного класса.
С абстрактными классами вы теряете индивидуальность класса, наследующего его; с интерфейсами вы просто расширяете функциональность каждого класса.
Абстрактные классы содержат частичную реализацию, которая дополняется в подклассах. Если в абстрактном классе отсутствует частичная реализация, то вместо него рекомендуется использовать интерфейс.
Подклассы абстрактного класса схожи между собой в части реализации, унаследованной от абстрактного класса, и отличаются в части своей реализации абстрактных методов.
## 4.AОП Примерами сквозной функциональности, как мы уже видели выше, могут служить:- логирование
- обработка транзакций
- обработка ошибок
- авторизация и проверка прав
- кэширование
- элементы контрактного программирования
Основной задачей аспектно-ориентированного программирования (АОП) является модуляризация сквозной функциональности, выделение её в аспекты. Для этого языки, поддерживающие концепцию АОП, реализуют следующие средства для выделения сквозной функциональности:
- аспект (aspect) – модуль или класс, реализующий сквозную функциональность. Аспект изменяет поведение остального кода, применяя совет в точках соединения, определённых некоторым срезом. Так же аспект может использоваться для внедрения функциональности;
- совет (advice) – дополнительная логика — код, который должен быть вызван из точки соединения. Совет может быть выполнен до, после или вместо точки соединения;
- точка соединения (join point) — точка в выполняемой программе (вызов метода, создание объекта, обращение к переменной), где следует применить совет;
- срез (pointcut) — набор точек соединения. Срез определяет, подходит ли данная точка соединения к заданному совету;
- внедрение (introduction) — изменение структуры класса и/или изменение иерархии наследования для добавления функциональности аспекта в инородный код;
- цель (target) – объект, к которому будут применяться советы;
переплетение (weaving) – связывание объектов с соответствующими аспектами (возможно на этапе компиляции, загрузки или выполнения программы).
- Упорядоченные — индексы, в которых элементы поля(столбца) упорядочены. Возрастающие Убывающие
- Неупорядоченные — индексы, в которых элементы неупорядочены.
-
Некластерный индекс — не перестраивают физическую структуру таблицы, а лишь организуют ссылки на соответствующие строки. Для идентификации нужной строки в таблице некластерный индекс организует специальные указатели, включающие в себя: информацию об идентификационном номере файла, в котором хранится строка; идентификационный номер страницы соответствующих данных; номер искомой строки на соответствующей странице; содержимое столбца.
-
Кластерный индекс — Принципиальным отличием кластерного индекса от индексов других типов является то, что при его определении в таблице физическое расположение данных перестраивается в соответствии со структурой индекса. Логическая структура таблицы в этом случае представляет собой скорее словарь, чем индекс. Данные в словаре физически упорядочены, например по алфавиту. Кластерные индексы могут дать существенное увеличение производительности поиска данных даже по сравнению с обычными индексами. Увеличение производительности особенно заметно при работе с последовательными данными.
java.util.concurrent.* Concurrent Collections — набор коллекций, более эффективно работающие в многопоточной среде нежели стандартные универсальные коллекции из java.util пакета. Вместо базового враппера Collections.synchronizedList с блокированием доступа ко всей коллекции используются блокировки по сегментам данных или же оптимизируется работа для параллельного чтения данных по wait-free алгоритмам.
Queues — неблокирующие и блокирующие очереди с поддержкой многопоточности. Неблокирующие очереди заточены на скорость и работу без блокирования потоков. Блокирующие очереди используются, когда нужно «притормозить» потоки «Producer» или «Consumer», если не выполнены какие-либо условия, например, очередь пуста или перепонена, или же нет свободного «Consumer»'a.
Synchronizers — вспомогательные утилиты для синхронизации потоков. Представляют собой мощное оружие в «параллельных» вычислениях.
Executors — содержит в себе отличные фрейморки для создания пулов потоков, планирования работы асинхронных задач с получением результатов.
Locks — представляет собой альтернативные и более гибкие механизмы синхронизации потоков по сравнению с базовыми synchronized, wait, notify, notifyAll.
Atomics — классы с поддержкой атомарных операций над примитивами и ссылками.
###В чем разница между volatile и synchronized?-
synchronized имеет два важных момента: это гарантия того, что только один поток выполняет секцию кода в один момент времени (взаимоисключение или mutex), и также гарантия того, что данные, изменённые одним потоком, будут видны всем другим потокам (видимость изменений).
-
volatile проще, нежели синхронизация и подходит только для контроля доступа к одиночному экземпляру или переменной примитивного типа: int, boolean... Когда переменная объявлена как volatile, любая запись её будет осуществляться прямо в память, минуя кеш. Также как и считываться будет прямо из памяти, а не из всевозможного кеша. Это значит, что все потоки будут "видеть" одно и то же значение переменной одновременно.
Шпаргалка по паттернам
Обзор java.concurrency
Процессы и потоки
SQL Join's
JavaEE wiki
Передать в поток данные
Вопросы по Collection Framework
equals и ==
Красно-черное дерево