You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Stefan Höltker (Jira)" <ji...@apache.org> on 2020/04/07 07:24:00 UTC
[jira] [Commented] (LOG4J2-2589) Potential Memory Leak
[ https://issues.apache.org/jira/browse/LOG4J2-2589?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17076999#comment-17076999 ]
Stefan Höltker commented on LOG4J2-2589:
----------------------------------------
Still an error any news to this issue ?
> Potential Memory Leak
> ----------------------
>
> Key: LOG4J2-2589
> URL: https://issues.apache.org/jira/browse/LOG4J2-2589
> Project: Log4j 2
> Issue Type: Bug
> Components: API, Appenders, Configurators, Core
> Affects Versions: 2.11.2
> Environment: Windows 10
> openjdk version "1.8.0_202" OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_202-b08) OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.202-b08, mixed mode)
> Reporter: Stefan Höltker
> Priority: Major
> Attachments: 2019-04-12 13_20_45-eclipse-workspace - C__Daten_analyse_ems_prd_20190409_java_pid11448.hprof - Ecli.png, screenshot-1.png
>
>
> We moved our application from a own small logging component to Log4j2.
> The application runs about 60.000 jobs per day at our biggest installation.
> We write our own Appender wich writes wit Hibernate to our DB (see InnovaIntegrationsportalHibernateAppender).
> After a runtime of ~36h the JVM crashed with OOME, analysing the hprof i saw that there is a amount of 763,5MB of the class org.apache.logging.log4j.core.appender.AbstractManager
> see screenshot of the Analyse attached (2019-04-12 13_20_45-eclips...)
>
> Going deeper i tried to reconstruct the behavior in a test class and profiled its result (see screenshot-1).
> Looks like a memory leak to me.
> InnovaIntegrationsportalHibernateAppender
> {code:java}
> package de.itout.innova.log4j.innova_log4j_appender;
> import de.itout.innova.ssp.entities.ssp.entities.*;
> import de.itout.jpa.util.*;
> import java.io.*;
> import java.util.*;
> import javax.persistence.*;
> import org.apache.logging.log4j.core.*;
> import org.apache.logging.log4j.core.appender.*;
> import org.apache.logging.log4j.core.config.plugins.*;
> import org.apache.logging.log4j.core.layout.*;
> /**
> *
> * @author swendelmann
> */
> @Plugin(name = "InnovaIntegrationsportalHibernateAppender", category = "Core", elementType = "appender")
> public class InnovaIntegrationsportalHibernateAppender extends AbstractAppender
> {
> private String schnittstelle;
> private String version;
> private String laufId;
> private EntityManager em;
> public InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout)
> {
> super(name, filter, layout);
> }
> public InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions)
> {
> super(name, filter, layout, ignoreExceptions);
> }
> private InnovaIntegrationsportalHibernateAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean ignoreExceptions, String schnittstelle, String version, String laufId)
> {
> super(name, filter, layout, ignoreExceptions);
> this.schnittstelle = schnittstelle;
> this.version = version;
> this.laufId = laufId;
> }
> // Your custom appender needs to declare a factory method
> // annotated with `@PluginFactory`. Log4j will parse the configuration
> // and call this factory method to construct an appender instance with
> // the configured attributes.
> @PluginFactory
> public static InnovaIntegrationsportalHibernateAppender createAppender(
> @PluginAttribute("name") String name,
> @PluginElement("Layout") Layout<? extends Serializable> layout,
> @PluginElement("Filter") final Filter filter,
> @PluginAttribute("schnittstelle") String schnittstelle,
> @PluginAttribute("version") String version,
> @PluginAttribute("laufId") String laufId
> )
> {
> if (name == null)
> {
> LOGGER.error("No name provided for InnovaIntegrationsportalHibernateAppender");
> return null;
> }
> if (layout == null)
> {
> layout = PatternLayout.createDefaultLayout();
> }
> if (laufId == null || laufId.isEmpty())
> {
> LOGGER.error("No laufid provided for InnovaIntegrationsportalHibernateAppender");
> }
> return new InnovaIntegrationsportalHibernateAppender(name, filter, layout, true, schnittstelle, version, laufId);
> }
> @Override
> public void append(LogEvent event)
> {
> try
> {
> em = JPAUtil.getEntityManager("SSP");
> em.getTransaction().begin();
> LauflogPK lauflogPK = new LauflogPK(schnittstelle, version, laufId, getNextLaufLogPos());
> Lauflog lauflog = new Lauflog(lauflogPK);
> lauflog.setLevel(event.getLevel().name());
> Date eventDateTime = new Date(event.getTimeMillis());
> lauflog.setLastchangeAenderungsdatum(eventDateTime);
> lauflog.setLastchangeAenderungszeit(eventDateTime);
> lauflog.setLastchangeBenutzer("WENDELMANN");
> lauflog.setLastchangeLogflag('A');
> lauflog.setText(event.getMessage().getFormattedMessage());
> em.persist(lauflog);
> em.getTransaction().commit();
> }
> catch (Throwable t)
> {
> em.getTransaction().rollback();
> LOGGER.error("Cant commit to Database InnovaIntegrationsportalHibernateAppender ", t);
> //TODO Log to file
> }
> finally
> {
> try
> {
> if (em != null)
> {
> em.close();
> }
> }
> catch (Throwable t)
> {
> LOGGER.error("Cant close em: ", t);
> }
> }
> }
> /**
> * SELECT ISNULL(MAX(POS)+1,0) FROM LAUFLOG
> * @return
> */
> private int getNextLaufLogPos()
> {
> Integer i = (Integer) em.createQuery("SELECT MAX(l.lauflogPK.pos)+1 FROM Lauflog l WHERE l.lauflogPK.schnittstelle = :schnittstelle AND l.lauflogPK.version = :version AND l.lauflogPK.lauf = :lauf ")
> .setParameter("schnittstelle", this.schnittstelle)
> .setParameter("version", this.version)
> .setParameter("lauf", this.laufId)
> .getSingleResult();
> if (i == null)
> {
> return 0;
> }
> else
> {
> return i;
> }
> }
> }
> {code}
>
> Test Class for Profiling
> {code:java}
> package de.itout.innova.log4j;
> import de.itout.innova.log4j.innova_log4j_appender.*;
> import de.itout.jpa.util.*;
> import java.io.*;
> import java.nio.charset.*;
> import org.apache.logging.log4j.*;
> import org.apache.logging.log4j.core.*;
> import org.apache.logging.log4j.core.appender.*;
> import org.apache.logging.log4j.core.config.*;
> import org.apache.logging.log4j.core.layout.*;
> import org.junit.*;
> /**
> *
> * @author swendelmann
> */
> public class ProfilingTest
> {
> QEntityManager em;
> private org.apache.logging.log4j.Logger logg = LogManager.getLogger();
> // Potential memory leak
> final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
> public ProfilingTest()
> {
> }
> @Before
> public void setUp()
> {
> em = JPAUtil.getEntityManager("SSP");
> }
> @After
> public void tearDown()
> {
> em.close();
> }
> @Test
> public void testProfiling()
> {
> logg.trace("Start the Main Method");
> int runs = 1000;
> int logs = 10;
> String allSicherungsVerzeichnis = "target/sicherungsverzeichnis/";
> logg.debug("Start Test mit " + runs + " durchläufen");
> for (int i = 0; i < runs; i++)
> {
> String laufid = "LD0" + i;
> File laufLogFile = new File(allSicherungsVerzeichnis + laufid + "_full.log");
> Configuration config = ctx.getConfiguration();
> // Full File Logger
> Layout layout = PatternLayout.newBuilder()
> .withConfiguration(config)
> .withPattern(PatternLayout.SIMPLE_CONVERSION_PATTERN)
> .withCharset(Charset.forName("UTF-8"))
> .build();
> Appender fullAppender = FileAppender.newBuilder()
> .setConfiguration(config)
> .setName(laufid + "FULL")
> .withFileName(laufLogFile.getAbsolutePath())
> .withAppend(true)
> .withImmediateFlush(true)
> .setIgnoreExceptions(false)
> .setLayout(layout)
> .build();
> fullAppender.start();
> config.addAppender(fullAppender);
> // Hibernate Logger
> Appender appender = InnovaIntegrationsportalHibernateAppender.createAppender(laufid, null, null, "LISA_4711", "LI0001", laufid);
> appender.start();
> AppenderRef ref = AppenderRef.createAppenderRef(laufid, Level.ALL, null); // HIER LOGLEVEL DB EINSTELLEN
> AppenderRef refFull = AppenderRef.createAppenderRef(laufid + "FULL", Level.ALL, null); // HIER LOGLEVEL Datei einstellen
> AppenderRef[] refs = new AppenderRef[]
> {
> ref, refFull
> };
> LoggerConfig loggerConfig = LoggerConfig
> .createLogger(false, Level.ALL, laufid, "true", refs, null, config, null);
> loggerConfig.addAppender(appender, Level.ALL, null); // HIER LOGLEVEL ebenfalls einstellen
> loggerConfig.addAppender(fullAppender, Level.ALL, null); // HIER LOGLEVEL Datei einstellen
> config.addLogger(laufid, loggerConfig);
> ctx.updateLoggers();
> org.apache.logging.log4j.Logger log = LogManager.getLogger(laufid);
> for (int j = 0; j < logs; j++)
> {
> log.info("Ich bin nur eine Info und soll nur in das FullFile logging!");
> log.warn("Ich bin ein böser warning und soll in das FullFile und in das Innova Integrationsportal Hibernate Logging");
> }
> appender.stop();
> fullAppender.stop();
> config.removeLogger(laufid);
> config.removeLogger(laufid + "FULL");
> ctx.updateLoggers();
> }
> logg.trace("Fertig");
> }
> }
> {code}
>
--
This message was sent by Atlassian Jira
(v8.3.4#803005)