- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
今天我收到 PermGen OutOfMemory
错误。
分析表明 最近的 GC Root WebappClassLoader
是 Logback 线程:
this - value: org.apache.catalina.loader.WebappClassLoader #4
<- contextClassLoader (thread object) - class: java.lang.Thread, value: org.apache.catalina.loader.WebappClassLoader #4
即:
java.lang.Thread#11 - logback-1
此线程的堆转储中的线程转储:
"logback-1" daemon prio=5 tid=34 WAITING
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:458)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
Local Variable: java.util.concurrent.SynchronousQueue$TransferStack$SNode#1
Local Variable: java.util.concurrent.SynchronousQueue$TransferStack#6
at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:925)
Local Variable: java.util.concurrent.SynchronousQueue#6
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
Local Variable: java.util.concurrent.ThreadPoolExecutor#34
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
Local Variable: java.util.concurrent.ThreadPoolExecutor$Worker#11
at java.lang.Thread.run(Thread.java:745)
我使用具有热重新部署功能 reloadable="true"
并通过 PreResources
外部化 CLASSPATH
的 Tomcat 8:
<Context docBase="/home/user/devel/app/src/main/webapp"
reloadable="true">
<Resources>
<!-- To override application.properties and logback.xml -->
<PreResources className="org.apache.catalina.webresources.DirResourceSet"
base="/home/user/devel/app/.config"
internalPath="/"
webAppMount="/WEB-INF/classes" />
</Resources>
</Context>
和 logback.xml
与 scan="true"
:
<configuration debug="false" scan="true" scanPeriod="5 seconds">
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
...
在 /home/user/devel/app/.config/logback.xml
中保存修改后 Tomcat 8 收到通知(我不确定使用什么 API 来监视 fs 上的更改)和应用程序重新部署开始了。这就是 PermGen OutOfMemory
之前发生的情况。
容器环境下如何优雅停止Logback?
如何停止"logback-1"
线程?
我找到了一些相关的讨论,但不明白如何处理这些信息:
更新 我在 visualvm
中使用堆转储。在错误的 logback-1
线程的引用跳转下:
lvl1 = flatten(filter(referees(heap.findObject(0xf4c77610)), "!/WebappClassLoader/(classof(it).name)"))
lvl2 = flatten(map(lvl1, "referees(it)"))
lvl3 = flatten(map(lvl2, "referees(it)"))
它指的是
ch.qos.logback.core.util.ExecutorServiceUtil$1
通过在 ExecutorServiceUtil
的 Logback 源中进行 grepping I found changelog entry :
All threads opened by ch.qos.logback.core.util.ExecutorServiceUtil#THREAD_FACTORY are now daemons, which fixes an application hang on shutdown when LoggerContext#stop() is not called (LOGBACK-929). Note that daemon threads are abruptly terminated by the JVM, which may cause undesirable results, such as corrupted files written by the FileAppender. It is still highly recommended for the application to call LoggerContext#stop() (e.g., in a shutdown hook) to gracefully shutdown appenders.
在容器环境中,守护线程是危险的并会导致内存泄漏,对吗?
最佳答案
我不完全明白我应该做什么。目前,我从项目 pom.xml
和这一行中删除了 jul-to-slf4j
桥:
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
来自 logback.xml
。即使使用这一行,应用程序也没有 "logback-1"
线程。
public class ShutdownCleanupListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) { }
@Override
public void contextDestroyed(ServletContextEvent sce) {
if (LoggerFactory.getILoggerFactory() instanceof LoggerContext) {
((LoggerContext) LoggerFactory.getILoggerFactory() ).stop();
}
}
}
在 web.xml
中:
<listener>
<listener-class>com.app.servlet.ShutdownCleanupListener</listener-class>
</listener>
移除直接依赖于:
import ch.qos.logback.classic.LoggerContext;
可以使用反射。
不确定我做的是否正确。我将查看是否由于 Logback 而出现 PermGen OutOfMemory
错误。
更新 在我发现来自 ExecutorServiceUtil
类的引用依赖项后,我检查了 Logback 源,发现该类创建的线程名称如上面的 bad:
thread.setName("logback-" + threadNumber.getAndIncrement());
该类仅在ch.qos.logback.core.ContextBase
中使用,线程在里面倾斜:
public void stop() {
// We don't check "started" here, because the executor service uses
// lazy initialization, rather than being created in the start method
stopExecutorService();
started = false;
}
请注意,LoggerContext
是 ContextBase
的子类,因此上述解决方案真正解决了我的问题。
关于tomcat - 在容器环境中优雅地停止 Logback,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34493817/
我正在尝试使用 janino 的条件处理来删除冗余的 logback 配置文件。 下面是我添加的条件逻辑
我有三个独立的项目,每个项目都有自己的嵌入式 logback.xml 文件。这些文件中的每一个都在用户的主目录中包含一个通用的日志配置文件: 在包含之后,我有这个规范: 这允许用户配置
我使用这个logback配置文件: %d{HH:mm:ss.SSS} [%-10.-10thread] %-5level %-30logger{1} - %msg%n
我的公司有一个环境管理工具,使您能够以 Java 编程方式从环境中查找属性。我想利用这个工具来配置 logback。例如,假设我有一个如下的 logback.xml(特别是文件 appender 部分
这似乎是一个粗心的错误,但我似乎找不到原因。使用 logback/slf4j(最新版本 slf4j-api-1.6.1,logback core/classic 0.9.24)进行记录。最简单的测试日
这是经典的logback的错误还是我遗漏了一些东西? The documentation非常明确地表明scanPeriod是可选属性: By default, the configuration fi
我正在尝试设置一个 logback 配置,该配置创建一个解压缩的日志文件作为第一卷,然后将压缩文件写入不同的目录。我相信最好的方法是在单个 appender 中创建多个 rollingPolicy 元
我用各种框架(jsf、Spring、Hibernate)编写了一个网络应用程序,我的记录器库是 Logback 和 slf4j。 目前我无法在日志文件中显示未捕获的异常(例如 NullPointers
这似乎是一个粗心错误,但我似乎找不到原因。使用 logback/slf4j 进行日志记录(最新版本 slf4j-api-1.6.1、logback core/classic 0.9.24)。用于测试的
我需要能够在事件中搜索多种模式中的任何一种,并用屏蔽值替换模式中的文本。这是我们应用程序中的一项功能,旨在防止敏感信息落入日志中。由于信息可能来自多种来源,因此对所有输入应用过滤器是不切实际的。此外,
我怎样才能创建一个 RollingFileAppender在接受谨慎标志的 Logback 中,还允许我指定日志文件的位置? 我尝试了以下操作,但正如我从文档中了解到的,logback 不支持 fil
我在文档中看不到任何相关内容,但收到以下异常 Failed to instantiate [ch.qos.logback.classic.LoggerContext] Reported excepti
我是 Logback 的新手,我正在尝试为 Windows 和 Linux 动态添加带有属性文件的文件路径。 这是我拥有的代码 sinppet,我怎样才能获得 ${MY_HOME} 的值 $
由于我必须登录到自定义(单个)数据库表,我编写了一个自定义 logback appender,扩展了 logback DBAppender . 我有一些单元测试来验证 appender 是否正常工作,
我正在尝试在 micronaut 中设置访问日志,但是,由于 logback-access 库使用 servlet 过滤器,我没有看到直接的方法。有不同的解决方案吗?一些隐藏的 Micronaut 配
我想使用 slf4j+logback 来登录 JBossAS7。 此外,我必须解决以下要求: 我需要在多个已部署的应用程序/EAR 中共享一个 logback 配置/上下文 我需要在运行时更改 log
我已经使用 LogbackValve 为 Tomcat 7.0 启用了 logback-access 日志。我的 logback-access 配置如下所示。 access.lo
我正在开发一个应用程序,使用我的另一个项目作为 Maven 依赖项。 期望 我希望我的依赖项使用自己的 logback.xml 来登录自己的文件。我希望应用程序使用自己的 logback.xml 文件
我在给定的 tomcat 中运行了许多相同的应用程序,它们都在不同的 URL 和 web.xml 文件下。 我想为每个文件创建一个相同的logback.xml。但我希望模式中包含服务器名称或显示名称。
它正在输出到控制台。logger.info("你好,世界信息。");//工作得很好... 但是以下代码返回“无法找到资源”错误: Logger logger = LoggerFactory.getLo
我是一名优秀的程序员,十分优秀!