Утечки памяти Oracle T4CPreparedStatement? - PullRequest
5 голосов
/ 20 мая 2010

Небольшая предыстория приложения, о котором я собираюсь рассказать в следующих нескольких строках:

XYZ - это приложение RCP Eclipse Workbench для маскировки данных: вы задаете ему столбец исходной таблицы и столбец целевой таблицы, оно будет применять преобразование (шифрование / тасование / и т.д.) и копировать данные строки от исходной таблицы к целевой таблице. Теперь, когда я маскирую n таблиц одновременно, этим приложением запускаются n потоков.

Вот вопрос:

Я столкнулся с производственной проблемой при первом запуске вышеуказанного приложения. К сожалению, у меня нет логов, чтобы добраться до рута. Тем не менее, я попытался запустить это приложение в тестовом регионе и сделать стресс-тест.

Когда я собрал файлы .hprof и провел их через анализатор (yourKit), я заметил, что объекты oracle.jdbc.driver.T4CPreparedStatement сохраняют кучу. Анализ также говорит мне, что один из моих классов содержит ссылку на этот подготовленный объект и, следовательно, n потоков имеют n таких объектов. T4CPreparedStatement, похоже, имел массивы символов: lastBoundChars и bindChars, каждый из которых имеет размер char [300000].

Итак, я немного исследовал (google!), Получил ojdbc6.jar и попытался декомпилировать T4CPreparedStatement. Я вижу, что T4CPreparedStatement расширяет OraclePreparedStatement, который динамически управляет размером массива lastBoundChars и bindChars.

Итак, мои вопросы здесь:

  1. Вы когда-нибудь сталкивались с такой проблемой, как это?
  2. Знаете ли вы значение lastBoundChars / bindChars?
  3. Я новичок в профилировании, как и вы думаю, я не делаю это правильно? (Я также запустил hprofs через MAT - и это было основным выявленным вопрос - так что я не думаю, что может быть не так?)

Я нашел нечто подобное в Интернете здесь: http://forums.oracle.com/forums/thread.jspa?messageID=2860681

Ценю ваши предложения / советы.

Ответы [ 2 ]

15 голосов
/ 07 августа 2013

Я столкнулся с той же проблемой. Хотя утечка Аффе могла быть проблемой, это была не моя проблема, и я нашел другой ответ после некоторых копаний:

Драйвер JDBC Oracle поддерживает буферы, в которые данные считываются для оптимизации производительности. Размер буфера вычисляется на основе максимально возможного размера строки (поэтому VARCHAR(2000) выделит что-то вроде 2000 char с), умноженного на размер выборки JDBC. Это позволяет драйверу читать данные непосредственно в буфер, а не выделять их по требованию, которое (по-видимому) будет медленнее.

Каждый подготовленный оператор в каждом соединении поддерживает буфер такого типа. Если вы используете большой пул соединений с кэшированием операторов (или вы кешируете PreparedStatement объекты вручную, или пропускаете их ...), то вы можете быстро использовать много места в куче. 1,6 ГБ в моем случае!

Все это объясняется самим Oracle в PDF здесь

Мой опыт основан на драйвере 11.2.0.3.

9 голосов
/ 20 мая 2010

Хотя и возможно, но вряд ли вы обнаружили огромную утечку памяти в 11g. Я бы начал с получения фактического SQL-кода от просочившихся курсоров и поиска кода, в котором создается этот SQL-код. Очень распространенная причина утечек курсоров, которые я обнаружил в прошлом, - это такой код:

try {
PreparedStatment stmt = null;
stmt = con.prepareStatement("SOME AWESOME SQL");
//lots of lines of code that masks the problem
stmt = con.prepareStatment("DIFFERENT SQL"); //You just leaked "SOME AWESOME SQL"!!!
//lots more code
} finally {
stmt.close() //looks like everything is ok, but only the second one actually got closed
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...