Как разрешить java.яз..Ошибка OutOfMemoryError по " java.яз..Строку", загружен "" затмение памяти анализатора


Я читаю некоторые большие XML-файлы и сохраняю их в базе данных. Это около 800 Мбайт.

Он хранит много записей, а затем завершается и дает исключение :

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.IdentityHashMap.resize(Unknown Source)
    at java.util.IdentityHashMap.put(Unknown Source)

С помощью созданного мною анализатора памяти .hprof файлы, в которых говорится:

  76,581 instances of "java.lang.String", loaded by "<system class loader>" occupy 1,04,34,45,504 (98.76%) bytes. 

Keywords
java.lang.String

У меня есть сеттеры и геттеры для извлечения значений.Как мне решить эту проблему. Любая помощь была бы истощена.

Введите описание изображения здесь

Я сделал с увеличением памяти через JRE.ini . но проблема не решена

EDIT : я использую scireumOpen для чтения XML-файлов.

Пример кода, который я использовал:

public void readD() throws Exception {

        XMLReader reader = new XMLReader();

        reader.addHandler("node", new NodeHandler() {

            @Override
            public void process(StructuredNode node) {
                try {



                    obj.setName(node
                            .queryString("name"));

                    save(obj);

                } catch (XPathExpressionException xPathExpressionException) {
                    xPathExpressionException.printStackTrace();
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
        });

        reader.parse(new FileInputStream(
                "C:/Users/some_file.xml"));

    }

    public void save(Reader obj) {

        try {
            EntityTransaction entityTransaction = em.getTransaction();
            entityTransaction.begin();
            Entity e1=new Entity;
            e1.setName(obj.getName());

            em.persist(e1);
            entityTransaction.commit();

        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
8 3

8 ответов:

Попробуйте использовать другой синтаксический анализатор для обработки XML.

Обработка одного большого XML-файла с 800M, используя, например, DOM, нецелесообразна, так как она занимает очень много памяти.

Попробуйте использовать SAX ot StAX в Java и обработайте результаты синтаксического анализа сразу, не пытаясь загрузить полный XML-файл в память.

А также не храните результат парсинга в общей памяти. Запишите их как можно быстрее в базу данных и максимально сужайте область анализа результатов. возможный.

Возможно, использовать промежуточные таблицы в базе данных и выполнять обработку всех наборов данных внутри базы данных.

Ваша куча не ограничена и не может содержать такой большой xml в памяти. Попробуйте увеличить размер кучи, используя опции-Xmx JRE.

Или

Попробуйте использовать http://vtd-xml.sourceforge.net/ для более быстрой и легкой обработки xml.

  1. самый очевидный ответ, увеличить вашу память JVM, как уже было упомянуто здесь, используя java -XmxNN
  2. Используйте SAXParser вместо дерева DOM (Если вы этого еще не сделали). Это зависит от дизайна вашего приложения, поэтому вы должны изучить его и посмотреть, является ли это возможной стратегией.
  3. Проверьте свой код и попробуйте удалить все ненужные объекты, чтобы их можно было удалить из ГБ. Это может включать в себя т. е. перемещение переменных внутри цикла вместо их наличия вне его, так что ссылки удаляются рано. Установка неиспользуемых элементов в null после того, как они вам больше не нужны.

Не зная вашего кода, это только общие направляющие линии.

Мой главный совет: проверьте ваш код JPA еще раз. Нужно быть как можно более изолированным.

Идея состояла бы в том, чтобы использовать JAXB с аннотациями. IdentityHashMap (ключи используют == вместо equals) - редкая вещь, скорее всего JPA, может быть, XML-теги? Вы также можете посмотреть, какой синтаксический анализатор XML используется (проверьте класс factory или перечислите всех поставщиков синтаксического анализатора XML с помощью интерфейса java SPI, service provider).

Вы можете использовать общие строки, например все строки с длиной меньше 20. С помощью Map<String, String>.

private Map<String, String> sharedStrings = new HashMap<>();

private String shareString(String s) {
    if (s == null || s.length() > 20) {
        return s;
    }
    String t = sharedStrings.get(s);
    if (t == null) {
        t = s;
        sharedStrings.put(t, t);
    }
    return t;
}

public void setXxx(String xxx) {
    this.xxx = sharedString(xxx);
}

Вы можете использовать сжатие (потоки GZip) для больших текстов в бобах.

Не используйте String, если вы используете.Замените его на StringBuffer или StringBuilder.Кроме того, попробуйте увеличить объем памяти.Я думаю, что 2048 в порядке, но если все еще проблема сохраняется, то измените его на 4096m или даже попробуйте с 6000m

Вы можете увеличить размер кучи при запуске Java:

java -Xmx8G

Похоже, что вы редактируете код, прежде чем опубликовать его, или публикуете не совсем правильный код. Пожалуйста, исправьте это.

Во-первых, ваш код не будет компилироваться.

Во-вторых, не передавать считыватель в функцию save. Создайте и заполните Entity in process(StructuredNode node) и передайте Entity, а не Reader, чтобы сохранить функцию.

В-третьих, правильно обрабатывать исключение в функции save. Если возникает исключение, выполняется откат транзакции.

Наконец-то я решил свою проблему. Помогли следующие вещи:

1. размер кучи 2048-это eough.

2.Другая проблема заключалась в том, что я использовал строку .

И строковый объект является неизменяемым

Под неизменяемым мы подразумеваем, что значение, хранящееся в строковом объекте, не может быть изменено. Тогда следующий вопрос, который приходит нам на ум: "если строка неизменна, то как я могу изменить содержимое объекта, когда захочу?". Что ж, если быть точным, это не тот же строковый объект, который отражает изменения, которые вы делаете. Для выполнения изменений внутри системы создается новый строковый объект.

См. различие между string и stringbuffer, Stringbuilder

Поэтому я удалил геттеры и сеттеры для сущностей, отличных от сущностей JPA. И вставлял все данные непосредственно в базу данных, не устанавливая их на какие-либо объекты.

3.Третьей и главной проблемой былJPAEntityManager .

Мой код не гарантирует, что EntityManager всегда будет закрыт после завершения метода. Поскольку в бизнес-логике возникает исключение RuntimeException, то em EntityManager остается открытым!

Так что всегда закрывайте это, а также вы можете установить ваши объекты в null в finally block, Как

finally {
                    Obj1 = null;
                    Obj2 = null;
                    if (entityTransaction.isActive())
                        entityTransaction.rollback();
                    em.clear();
                    em.close();

                }

См. Как закрыть JPA EntityManger в веб-приложениях

+1 за каждый ответ Ребята мне очень помогли. я не отмечаю никакого ответа, потому что я думал о публикации полного ответа для оно.Thanx