предисловие
Откровенно говоря, это что-то вроде вечеринки с заголовками, ощущение шага в науку, на самом деле, это поделиться с вами оOQLкакой-то контент.
OQLчто это такое?
Это язык объектных запросов, основанный на снапшотах в куче java, его синтаксис похож на наш обычный SQL, HQL и т. д., в конце концовQLсемья.
По характеристикам запроса в его куче, естественно, можно провести диагностику памяти, или сгенерировать нужный отчет и т.д.
я сам предпочитаю использоватьOQL, в конце концов, возможность писать код самостоятельно — это достаточно гибко, а гибкость, естественно, является фактором, привлекающим внимание людей.
Вторая причина, естественно:
Сегодня, от введения до фактического примера, неясно, чтоOQL"Друг мой, есть еще один способ отладки.
Как сказано в «Глубоком понимании виртуальной машины Java»: «Ни один инструмент не является« секретным оружием », и если он у вас есть, вы можете« вылечить все болезни »». Так что еще один навык — это просто еще одна идея отладки.
текст
Если вы настаиваете на прочтении текста, я думаю, вы понимаетеheap dump
что это такое,
такструктура памятиТакие понятия вводятся не слишком много в этой статье.
heap dump
Существует множество инструментов анализа, от JConsole до Jhat, и широко используемый MAT, их встроенные функции уже очень мощные, и их можно написать самостоятельно.OQL?
Это легко понять, смотреть на Report и писать SQL, естественно, не одно и то же, первое — результат концентрации на конкретной области, а второе — гибкий язык разработки.
Начнем с простого примера, а позже я буду использовать классическую «Эффективную Java» в «Эффективной Java».возможная утечка памяти"Пример кода, показывающий, как писать"интересный OQL".
простой пример
Первый шаг, безусловно,heap dump
, так как это первоепростой пример, вы можете найти любойheap dump
Начать.
Tip: Инструментальные привычки у всех разные. Сегодняшние операции автора, такие как дамп кучи, чтение файлов hprof и выполнениеOQL, все вjVisualVmосуществляется в.
Если вы опытный любитель марихуаны, конечно, вы можете пропустить простой пример и продолжить чтение следующего содержания~
Сначала начните со списка слевасчастливый процессВозьмите средство просмотра из середины, выполните дамп кучи и убедитесь, что имя должно быть внутренним процессом в IDEA, который запускает автор.
Неудивительно, что он перейдет на страницу анализа heapDump, другие функции будут временно пропущены, выберите в раскрывающемся списке в верхнем левом углу сегодняшнюю тему.OQL Console".
Запросите все «экземпляры строк», которые можно рассматривать какOQL"привет мир" в . Эта статья не исключение:
select
s
from
java.lang.String s
Напишите вышеуказанный OQL в текстовое поле ниже
Как видно из рисунка выше, все экземпляры String выведены, ничем не отличается от обычных средств визуализации БД?После входа в операцию OQL вверху отображаются результаты запроса, по которым можно найти значение, ссылку и другую информацию об объекте.
Здесь тоже есть небольшая деталь, на самом деле в OQL тоже есть диалект, но он ограничен разными запущенными инструментами.
Например, в некоторых книгахselect * from java.lang.String
В качестве первого вводного заявления,
Но в моем нынешнемvisualVM2.0Он сообщит об ошибке при работе в середине и будет нормально выводиться в MAT.
Хотя общая грамматика та же, детали должны основываться на грамматике, представленной на официальном сайте инструмента, который вы привыкли использовать.
Пример в эффективной Java
Если вы читали «Эффективную Java», вы должны помнить классический фрагмент кода, демонстрирующий сценарий, в котором существует риск утечки памяти.
Неважно, если вы его не читали, этот код очень прост, и я также вставил его сюда:
class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly
* doubling the capacity each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
Код очень простой, самореализующийся стек, операция pop забывает удалить ссылку в массиве элементов, и есть риск утечки памяти.
Затем я буду использовать этот код в качестве демонстрации, чтобы увидетьOQLможет сделать что-нибудь.
автортестовый код:
public static void main(String[] args) throws Exception {
// stack1
Stack stack1 = new Stack();
// stack1入栈30个元素
addItem(stack1);
// stack2
Stack stack2 = new Stack();
// stack2入栈30个元素
addItem(stack2);
// stack2出栈20元素
for (int i = 0; i < 20; i++) {
stack2.pop();
}
System.out.println("----Over----");
// 通知full gc, 如果jvm心情不错,可以拿到dump
System.gc();
Thread.sleep(5000);
}
Авторский тест очень прост: два из вышеперечисленных стеков инстанцируются, один не имеет операции извлечения, другой имеет операцию извлечения и экземпляр операции извлечения, который, естественно, сохраняет ссылки с истекшим сроком действия.
Чтобы получить файл дампа, я добавил следующие два параметра запуска:
- -XX:+HeapDumpBeforeFullGC
- -XX:HeapDumpPath=/Users/vt/logs/jvm
То есть дамп перед FullGC.
Давайте посмотрим, что можно сделать с помощью OQL? Чтобы опустить пробел в следующем содержимом, OQL и результаты вывода представлены словами Input и Output.
Вход:
select
s.elements.length
from instanceof
com.vt.example.LeakTest$Stack s
Выход:
33
33
Видно, что распечатываются результаты экземпляров двух стеков, что согласуется с содержимым теста. И длина элементов была увеличена до 33.
Поскольку вывод результата поддерживает формат json, мы могли бы запросить еще какой-нибудь контент.
Вход:
select
{
"elements's length" :s.elements.length,
"instance": s,
"size attr" : s.size,
"count" : (actualCount = count(filter(s.elements, "it != null")))
}
from instanceof
com.vt.example.LeakTest$Stack s
Выход:
{
instance = com.vt.example.LeakTest$Stack#1,
count = 30,
size attr = 30,
elements's length = 33
}
{
instance = com.vt.example.LeakTest$Stack#2,
count = 30,
size attr = 10,
elements's length = 33
}
Приведенный выше оператор OQL автора запрашивает адрес экземпляра, атрибут размера экземпляра, длину контейнера массива в экземпляре иреальный размер.
Реальный размер считается в контейнере массиване нольЭлементы.
То есть упомянутая выше проблема со стеком заключается в том, что для элемента с истекшим сроком действия не устанавливается значение null при извлечении из стека, что приводит к риску утечки памяти.
Итак, взгляните на приведенные выше результаты OQL, знаете ли вы что-нибудь?
Правильно, это элемент, фактически сохраненный вторым экземпляром, который не соответствует размеру атрибута size.Естественно, это экземпляр, в котором возникла проблема.
Но не все так однозначно, давайте оптимизируем другую версию, чтобы посмотреть как:
Вход:
select
{
"实例中数组容器当前大小" :s.elements.length,
"实例地址": s,
"当前size属性" : s.size,
"实际保存的引用数量" : (actualCount = count(filter(s.elements, "it != null"))),
"疑似泄漏" : (actualCount > s.size) ? "<font color='red'>有</font>" : "无"
}
from instanceof
com.vt.example.LeakTest$Stack s
Выход:
Последняя версия описана на китайском, и текст выделен.Так понятнее?
При использовании OQL для непосредственного поиска нужного нам отчета может оказаться невозможным полагаться на базовые функции.
наконец
Увидев это, каждый должен иметь предварительное представление об OQL и о том, как просто «играть», и на этом статья окончена.
На практике OQL выше не обнаруживает утечки памяти.Контент в основном предназначен для демонстрационных функций, что дает новый набор идей читателям, которые не понимают OQL, но это не решение~