Напишите заранее (распространенные вопросы на собеседовании)
фундаментальный вопрос:
- Познакомьтесь с областью памяти Java (область данных времени выполнения)
- Процесс создания Java-объектов (пять шагов, рекомендуется писать их по умолчанию и знать, что делает виртуальная машина на каждом шаге)
- Два способа доступа и поиска объектов (дескриптор и прямой указатель)
Расширенный вопрос:
- Класс String и постоянный пул
- Классы-обертки и константные пулы для 8 основных типов
Java-программисты должны видеть документацию
Ха-ха кожу это! Я открываю исходный код документа руководства по изучению Java. Книга, охватывающая основные знания, которые необходимо освоить большинству Java-программистов, постепенно совершенствуется шаг за шагом, и мы с нетерпением ждем вашего участия. Адрес на гитхабе:GitHub.com/snail Climb/…. Взгляните, я не думаю, что вы пожалеете об этом, если можете, поставьте звезду, чтобы поощрить это!
1 Обзор
Для программистов Java, в соответствии с механизмом автоматического управления памятью виртуальной машины, больше нет необходимости писать соответствующую операцию удаления/освобождения для новой операции, такой как программисты, разрабатывающие программы C/C++, и не так просто вызвать утечку памяти и память переполняется проблема. Именно потому, что Java-программисты передают права управления памятью виртуальной машине Java.Если возникают проблемы с утечками и переполнениями памяти, если вы не понимаете, как виртуальная машина использует память, устранить ошибки будет очень сложно. .
2 Область рабочих данных
В процессе выполнения Java-программ виртуальная машина Java делит управляемую ею память на несколько различных областей данных.
Некоторые из этих компонентов являются частными потоками, другие — общими потоками.Частная тема:
- счетчик команд
- стек виртуальных машин
- собственный стек методов
Разделено по темам:
- куча
- область метода
- прямая память
2.1 Счетчик программ
Счетчик программ — это небольшой объем памяти, который можно рассматривать как индикатор номера строки байт-кода, выполняемого текущим потоком.Когда интерпретатор байт-кода работает, он выбирает следующую инструкцию байт-кода для выполнения, изменяя значение этого счетчика.Такие функции, как ветвление, цикл, переход, обработка исключений и восстановление потока, должны полагаться на этот счетчик для завершения.
Кроме того,Чтобы восстановить правильную позицию выполнения после переключения потока, каждый поток должен иметь независимый программный счетчик. Счетчики между потоками не влияют друг на друга и хранятся независимо. Мы называем этот тип области памяти «частной памятью потока».
Из приведенного выше введения мы знаем, что у счетчика программ есть две основные функции:
- Интерпретатор байт-кода последовательно считывает инструкции, изменяя программный счетчик, чтобы реализовать управление потоком кода, например: последовательное выполнение, выбор, цикл, обработка исключений.
- В случае многопоточности счетчик программ используется для записи позиции выполнения текущего потока, чтобы, когда поток переключается обратно, он мог знать, где поток выполнялся в последний раз.
Примечание. Счетчик программ — это единственная область памяти, которая не получает OutOfMemoryError, ее время жизни создается при создании потока и умирает при завершении потока.
2.2 Стек виртуальной машины Java
Как и счетчик программ, стек виртуальной машины Java также является частным потоком, его жизненный цикл такой же, как у потока, и он описывает модель памяти для выполнения методов Java.
Память Java можно грубо разделить на память кучи (Heap) и память стека (Stack), где стек — это стек виртуальной машины или часть таблицы локальных переменных стека виртуальной машины.(На самом деле стек виртуальной машины Java состоит из кадров стека, и каждый кадр стека содержит: таблицу локальных переменных, стек операндов, динамическую ссылку, информацию о выходе из метода.)
В таблице локальных переменных в основном хранятся различные типы данных, известные компилятору.(логическое, байтовое, символьное, короткое, целое, плавающее, длинное, двойное),ссылка на объект(Тип ссылки, который отличается от самого объекта, может быть указателем на начальный адрес объекта или может указывать на дескриптор, представляющий объект или другое местоположение, связанное с объектом).
В стеке виртуальной машины Java есть два исключения: StackOverFlowError и OutOfMemoryError.
- StackOverFlowError:Если объем памяти стека виртуальной машины Java не допускает динамического расширения, когда глубина стека запросов потока превышает максимальную глубину текущего стека виртуальной машины Java, будет выдано исключение StackOverFlowError.
- OutOfMemoryError:Если размер памяти стека виртуальной машины Java допускает динамическое расширение, а память заканчивается, когда поток запрашивает стек, его нельзя динамически расширить, и генерируется исключение OutOfMemoryError.
Стек виртуальной машины Java также является частным потоком, и каждый поток имеет свой собственный стек виртуальной машины Java, который создается при создании потока и умирает, когда поток умирает.
2.3 Стек локальных методов
Это очень похоже на роль, которую играет стек виртуальной машины, разница заключается в следующем:Стек виртуальной машины служит виртуальной машине для выполнения методов Java (то есть байт-кода), в то время как собственный стек методов обслуживает собственные методы, используемые виртуальной машиной.В сочетании со стеком виртуальной машины Java в виртуальной машине HotSpot.
Когда выполняется собственный метод, в стеке собственного метода также создается кадр стека для хранения таблицы локальных переменных, стека операндов, динамической ссылки и информации выхода собственного метода.
После выполнения метода соответствующий кадр стека будет извлечен из стека, и пространство памяти будет освобождено, а также возникнут два исключения, StackOverFlowError и OutOfMemoryError.
2.4 Кучи
Самая большая часть памяти, управляемая виртуальной машиной Java, куча Java — это область памяти, совместно используемая всеми потоками, создаваемая при запуске виртуальной машины.Единственной целью этой области памяти является хранение экземпляров объектов, и почти все экземпляры объектов и массивы выделяются здесь.
Куча Java — это основная область, управляемая сборщиком мусора, поэтому она также называетсяКуча мусора, С точки зрения сборки мусора, поскольку сборщики в основном используют алгоритм сборки мусора поколений, куча Java также может быть подразделена на: новое поколение и старое поколение: чуть более подробно, есть: Eden space, From Survivor , В пространство для выживших и т. д. .Целью дальнейшего деления является более эффективное использование памяти или ее более быстрое выделение.
В JDK 1.8 все постоянное поколение было удалено и заменено областью, называемой метапространством (постоянное поколение использует пространство кучи памяти JVM, в то время как метапространство использует физическую память, на которую напрямую влияет физическая память машины. ограничение).
Рекомендуемое чтение:
- «Модель памяти Java8 — постоянное поколение (PermGen) и метапространство (метапространство)»:woo woo woo.cn blog on.com/crawl to the earth/fear/53…
2.5 Область метода
Как и куча Java, область методов — это область памяти, совместно используемая каждым потоком, которая используется для хранения таких данных, как информация о классе, константы, статические переменные и код, скомпилированный компилятором реального времени, которые были загружены виртуальной машиной. . Хотя спецификация виртуальной машины Java описывает область методов как логическую часть кучи, у нее есть псевдоним Non-Heap, который следует отличать от кучи Java.
Область метода в виртуальной машине HotSpot также часто называют«Постоянное поколение», они по существу не эквивалентны. Просто потому, что команда разработчиков виртуальной машины HotSpot использует постоянное поколение для реализации области методов, чтобы сборщик мусора виртуальной машины HotSpot мог управлять такой частью памяти, как куча Java. Но это не очень хорошая идея, потому что это более склонно к проблемам с переполнением памяти.
Условно говоря, поведение сборки мусора в этой области относительно редкое, но оно не является «постоянным» после того, как данные попадают в область метода.
2.6 Пул констант времени выполнения
Пул констант времени выполнения является частью области методов. В дополнение к информации описания версии класса, поля, метода, интерфейса и т. д. в файле класса также имеется информация о постоянном пуле (используется для хранения различных литералов и символических ссылок, сгенерированных во время компиляции).
Поскольку часть области методов пула констант времени выполнения естественным образом ограничена памятью области методов, исключение OutOfMemoryError будет вызвано, когда пул констант больше не сможет обращаться за памятью.
JDK1.7 и более поздние версии JVM переместили пул констант времени выполнения из области методов и открыли область в куче Java (Heap) для хранения пула констант времени выполнения.
Рекомендуемое чтение:
- «Разница между несколькими пулами констант в Java»:blog.CSDN.net/QQ_26222859…
2.7 Прямая память
Прямая память не является частью области данных среды выполнения виртуальной машины и не является областью памяти, определенной в спецификации виртуальной машины, но эта часть памяти также часто используется. А также может привести к исключению OutOfMemoryError.
Недавно добавлено в JDK1.4Класс NIO (новый ввод/вывод), который вводитКаналиБуферВ режиме ввода-вывода он может напрямую использовать библиотеку собственных функций для непосредственного выделения памяти вне кучи, а затем работать с объектом DirectByteBuffer, хранящимся в куче Java, в качестве ссылки на эту память. Это может значительно повысить производительность в некоторых сценариях, посколькуИзбегайте копирования данных между кучей Java и собственной кучей и обратно..
Выделение собственной прямой памяти не будет ограничено кучей Java, но, поскольку это память, оно будет ограничено общим объемом собственной памяти и адресным пространством процессора.
3 Изучение объектов виртуальной машины HotSpot
Благодаря приведенному выше введению мы, вероятно, знаем ситуацию с памятью виртуальной машины.Давайте подробно рассмотрим весь процесс выделения объектов, размещения и доступа виртуальной машины HotSpot в куче Java.
3.1 Создание объекта
На следующем рисунке показан процесс создания Java-объектов, я полагаю, что лучше всего записать его по умолчанию и понять, что делает каждый шаг.
①Проверка загрузки класса:Когда виртуальная машина встречает новую инструкцию, она сначала проверяет, могут ли параметры этой инструкции найти символическую ссылку этого класса в пуле констант, и проверяет, был ли загружен, разрешен и инициализирован класс, представленный этой символической ссылкой. Если нет, то сначала необходимо выполнить соответствующий процесс загрузки класса.
②Выделить память:существуетпроверка загрузки классаПосле прохождения следующая виртуальная машина будет новым объектомВыделить память. Размер требуемой объекту памяти можно определить после загрузки класса, а задача выделения места под объект эквивалентна делению блока памяти определенного размера из кучи Java.Распределениеимеют«Столкновение указателей»и«Свободный список»два,Выбор метода распределения определяется тем, является ли куча Java регулярной, а является ли куча Java регулярной, определяется тем, имеет ли используемый сборщик мусора функцию уплотнения..
Два способа распределения памяти: (дополнительный контент, необходимо освоить)
Какой из двух вышеперечисленных методов выбрать, зависит от того, является ли память кучи Java обычной или нет. Является ли память кучи Java регулярной, зависит от того, является ли алгоритм сборщика мусора "маркировать-очистка" или "маркировать-очищать" (также известный как "маркировать-сжатие"). Стоит отметить, что память алгоритма копирования также регулярно
Проблема параллелизма выделения памяти (дополнительный контент, необходимо освоить)
Очень важным вопросом при создании объектов является безопасность потоков, потому что в реальном процессе разработки объекты создаются очень часто.В качестве виртуальной машины необходимо обеспечить безопасность потоков.Вообще говоря, виртуальная машина использует два метода для обеспечения безопасность потока:
- CAS+ошибка повторной попытки:CAS — это реализация оптимистической блокировки. Так называемая оптимистическая блокировка заключается в том, чтобы завершить операцию без блокировки каждый раз, но предполагая, что конфликта нет.Если из-за конфликта произойдет сбой, она будет повторять попытку, пока не добьется успеха.Виртуальная машина использует CAS в сочетании с неудачной повторной попыткой, чтобы обеспечить атомарность операций обновления.
- TLAB:Заранее выделяйте часть памяти в области Eden для каждого потока.Когда JVM выделяет память для объекта в потоке, она сначала выделяет его в TLAB.Когда объект больше, чем оставшаяся память в TLAB или памяти TLAB исчерпан, вышеупомянутая память снова используется.CAS для выделения памяти
③ Инициализировать нулевое значение:После завершения выделения памяти виртуальная машина должна инициализировать выделенное пространство памяти нулевым значением (исключая заголовок объекта).Этот шаг гарантирует, что поле экземпляра объекта может использоваться непосредственно в коде Java без назначения начального значения. значение, и программа может получить доступ к нулевому значению, соответствующему типу данных этих полей.
④Установите заголовок объекта:После инициализации нулевого значения,Виртуальной машине необходимо произвести необходимые настройки объектаНапример, этот объект является экземпляром этого класса, как найти информацию о метаданных класса, хэш объекта, возраст создания GC объекта и т. д.Эта информация хранится в заголовке объекта.Кроме того, в зависимости от текущего состояния виртуальной машины, например, включения блокировки смещения и т. д., заголовок объекта будет установлен по-разному.
⑤ Выполните метод инициализации:После завершения вышеуказанной работы с точки зрения виртуальной машины был создан новый объект, но с точки зрения программы на Java создание объекта только началось.<init>
Метод еще не выполнен, и все поля по-прежнему равны нулю. Таким образом, в общем случае за выполнением новой инструкции последует выполнение<init>
метод, объект инициализируется в соответствии с пожеланиями программиста, так что полностью создается действительно пригодный для использования объект.
3.2 Расположение объектов в памяти
В виртуальной машине Hotspot расположение объектов в памяти можно разделить на 3 быстрых области:заголовок объекта,данные экземпляраиВыровнять отступы.
Заголовок объекта виртуальной машины Hotspot включает в себя две части информации,Первая часть используется для хранения собственных данных времени выполнения самого объекта.(хэш, возраст генерации GC, флаг состояния блокировки и т. д.),Другая часть - это указатель типа, то есть указатель объекта на его метаданные класса, и виртуальная машина использует этот указатель, чтобы определить, что объект является экземпляром этого класса.
Часть данных экземпляра — это достоверная информация, которую фактически хранит объект., но и различные типы содержимого полей, определенные в программе.
Заполнение выравнивания не обязательно существует и не имеет особого значения, а служит только заполнителем.Поскольку система автоматического управления памятью виртуальной машины Hotspot требует, чтобы начальный адрес объекта был целым числом, кратным 8 байтам, иными словами, размер объекта должен быть целым числом, кратным 8 байтам. Часть заголовка объекта точно кратна 8 байтам (1 или 2 раза), поэтому, когда часть данных экземпляра объекта не выровнена, она должна быть дополнена дополнением выравнивания.
3.3 Доступ к позиционированию объектов
Создание объекта означает использование объекта, и наша программа на Java работает с конкретным объектом в куче через справочные данные в стеке. Метод доступа к объекту зависит от реализации виртуальной машины. Текущие основные методы доступа:① Используйте ручкуи②Прямой указательДва вида:
-
ручка:Если используется дескриптор, блок памяти будет разделен на пул дескрипторов в куче Java, а адрес дескриптора объекта хранится в ссылке, а дескриптор содержит конкретную информацию об адресе данных и типе экземпляра объекта. данные;
-
прямой указатель:Если используется прямой доступ по указателю, то макет объекта кучи Java должен учитывать, как предотвратить доступ к соответствующей информации данных типа, а адрес, хранящийся в ссылке, является непосредственно объектом.
Оба этих метода доступа к объектам имеют свои преимущества. Самым большим преимуществом использования дескриптора для доступа является то, что в ссылке хранится стабильный адрес дескриптора.При перемещении объекта изменяется только указатель данных экземпляра в дескрипторе, а саму ссылку изменять не нужно. Самое большое преимущество использования метода прямого доступа к указателю заключается в том, что он быстрый, что экономит время на позиционирование указателя.
Четыре ключевые добавки
Класс String и постоянный пул
1 Существует два способа создания объекта String:
String str1 = "abcd";
String str2 = new String("abcd");
System.out.println(str1==str2);//false
Эти два разных метода создания различны: первый способ — получить объект в константном пуле, а второй — создать новый объект непосредственно в куче памяти.
Помните: всякий раз, когда вы используете новый метод, вам нужно создать новый объект.2 Константный пул типа String является особым. Есть два основных способа его использования:
- Строковые объекты, объявленные непосредственно в двойных кавычках, хранятся непосредственно в пуле констант.
- Если это не объект String, объявленный в двойных кавычках, вы можете использовать интерн, предоставленный String. String.intern() — это собственный метод. Его функция: если пул констант времени выполнения уже содержит строку, равную содержимому этого Объект String, возвращает ссылку на строку в пуле констант; если нет, создает строку с тем же содержимым, что и эта строка в пуле констант, и возвращает ссылку на строку, созданную в пуле констант.
String s1 = new String("计算机");
String s2 = s1.intern();
String s3 = "计算机";
System.out.println(s2);//计算机
System.out.println(s1 == s2);//false,因为一个是堆内存中的String对象一个是常量池中的String对象,
System.out.println(s3 == s2);//true,因为两个都是常量池中的String对
3 String Конкатенация строк
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";//常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string";//常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
Старайтесь избегать объединения нескольких строк, так как это приведет к воссозданию объекта. Если вам нужно изменить цвет строки, вы можете использовать StringBuilder или StringBuffer.
String s1 = new String("abc"); Сколько объектов создает это предложение?
Создаются два объекта.
проверять:
String s1 = new String("abc");// 堆内存的地值值
String s2 = "abc";
System.out.println(s1 == s2);// 输出false,因为一个是堆内存,一个是常量池的内存,故两者是不同的。
System.out.println(s1.equals(s2));// 输出true
результат:
false
true
объяснять:
Сначала строка «abc» помещается в пул констант, а затем новая копия строки «abc» помещается в кучу Java (строковая константа «abc» была определена для помещения в пул констант при компиляции). время, а "" в куче Java" abc" определяется во время инициализации во время выполнения), тогда str1 стека Java указывает на "abc" в куче Java.
Классы-обертки и константные пулы для 8 основных типов
- Большинство классов-оболочек базовых типов Java реализуют технологию пула констант, а именно Byte, Short, Integer, Long, Character, Boolean; эти пять классов-оболочек по умолчанию создают кэш-данные соответствующего типа значения [-128, 127]. но за пределами этой области все равно будут создаваться новые объекты.
- Классы-оболочки Float и Double для двух типов с плавающей запятой не реализуют технологию пула констант.
Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出true
Integer i11 = 333;
Integer i22 = 333;
System.out.println(i11 == i22);// 输出false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出false
Исходный код целочисленного кеша:
/**
*此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Сценарии применения:
- Integer i1=40 Java будет напрямую инкапсулировать код в Integer i1=Integer.valueOf(40) при компиляции, чтобы использовать объекты в пуле констант.
- Integer i1 = new Integer(40), в этом случае создается новый объект.
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);//输出false
Более богатый пример целочисленного сравнения:
Integer i1 = 40;
Integer i2 = 40;
Integer i3 = 0;
Integer i4 = new Integer(40);
Integer i5 = new Integer(40);
Integer i6 = new Integer(0);
System.out.println("i1=i2 " + (i1 == i2));
System.out.println("i1=i2+i3 " + (i1 == i2 + i3));
System.out.println("i1=i4 " + (i1 == i4));
System.out.println("i4=i5 " + (i4 == i5));
System.out.println("i4=i5+i6 " + (i4 == i5 + i6));
System.out.println("40=i5+i6 " + (40 == i5 + i6));
результат:
i1=i2 true
i1=i2+i3 true
i1=i4 false
i4=i5 false
i4=i5+i6 true
40=i5+i6 true
объяснять:
Оператор i4 == i5 + i6, поскольку оператор + не применяется к объектам Integer, сначала автоматически распаковываются i5 и i6, а значения складываются, то есть i4 == 40. Тогда объект Integer нельзя напрямую сравнить со значением, поэтому i4 автоматически распаковывается до значения int 40, и, наконец, этот оператор преобразуется в 40 == 40 для числового сравнения.
напиши в конце
Рекомендации по документации с открытым исходным кодом
Java-Guide: Руководство, которое охватывает основные знания, которые необходимо освоить большинству Java-программистов. Оно постепенно совершенствуется шаг за шагом. Мы с нетерпением ждем вашего участия.
Адрес на гитхабе:GitHub.com/snail Climb/…
Ссылаться на:
- Глубокое понимание виртуальной машины Java: расширенные функции JVM и рекомендации (второе издание)
- «Практическая виртуальная машина Java»
- Блог Woohoo.cn on.com/C ZD blog/afraid/5…
- Блог woohoo.cn на.com/Java-Looking for/Afraid…
- blog.CSDN.net/QQ_26222859…
- blog.CSDN.net/Грубый Ухань 201…
Если ты расцветешь, ветерок придет. Добро пожаловать в мою общедоступную учетную запись WeChat: «Руководство по прохождению интервью на Java», теплую общедоступную учетную запись WeChat. В официальном аккаунте много информации, отвечайте на ключевое слово "1" и может увидите то, что хотите!