当前位置: 首页 > 知识库问答 >
问题:

在容器环境中优雅地停止登录

贾建茗
2023-03-14

今天我遇到permgen outofmemory错误。

分析表明,webappclassloader最近的GC根是Logback thread:

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)
<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>
<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中保存修改后,Tomcat8收到通知(我不确定用于监视fs上的更改的API是什么),然后开始重新部署应用程序。这就是permgen outofmemory之前发生的情况。

如何在容器环境中优雅地停止登录?

如何停止“logback-1”线程?

    null

更新我在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的日志源,我找到了changelog条目:

共有1个答案

郎仰岳
2023-03-14

我不完全明白我该怎么办。当前,我从项目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();
        } 
    }
}
<listener>
    <listener-class>com.app.servlet.ShutdownCleanupListener</listener-class>
</listener>

要删除对以下方面的直接依赖,请执行以下操作:

import ch.qos.logback.classic.LoggerContext;

可以使用反射。

不确定我做得对不对。我将查看getpermgen outofmemory是否由于日志返回而出错。

 thread.setName("logback-" + threadNumber.getAndIncrement());
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;
}
 类似资料:
  • 问题内容: 如何在Linux和Windows中正常停止Java进程? 什么时候被调用,什么时候不被调用? 终结器又如何呢? 我可以从外壳向Java进程发送某种信号吗? 我正在寻找最好的便携式解决方案。 问题答案: 在所有未强制终止VM的情况下,都会执行关机挂钩。因此,如果要发出“标准” kill(通过kill命令),则它们将执行。同样,它们将在调用后执行。 但是强行杀死(或),然后它们将不会执行。

  • 问题内容: 我写了一个线程,它花费太多时间执行,而且似乎还没有完全完成。我想优雅地停止线程。有什么帮助吗? 问题答案: 做到这一点的好方法是让一个线程保护一个Thread的变量,并在你要停止它的时候将其设置为外部变量,例如: `class MyThread extends Thread { volatile boolean finished = false; public void stopMe(

  • 不论是什么类型的应用,都会希望在服务停止前能够收到停止通知,有一定的时间做退出前的释放资源、关闭连接、不再接收外部请求等工作。我们对所有应用的优雅停止配置提供了一个全面指导,也提供了每种类型服务,从开发到部署到应用引擎v2的测试优雅停止功能的完整流程。 容器优雅停止最简单办法 当退出容器前,会将容器从服务提供列表中移除,使得外部请求不再打在其上,同时执行退出前可执行Hook。 在这里,我们设置在停

  • 问题内容: 我在Jenkins中有一个插件,可以通过rest运行一个远程服务器。 如何在构建中止时向服务器发送最后一个请求?因此,优雅地完成插件的工作? 我发现的对“终止序列”的唯一参考是this。这使我认为该过程非常繁琐,并且在终止子级(我的插件)之前无法捕获信号。 问题答案: 我有类似的需求,可以通过PostBuildScript插件解决。 我选择运行一个构建步骤,但是您可以运行其他几个选项。

  • 问题内容: 我正在Glassfish v3应用服务器上使用EJB和JPA。我有一个Entity类,在其中我用@Column注释强制其中一个字段是唯一的。 当我尝试将该字段设置为非唯一值的对象持久化时,当由EJB容器管理的事务提交时,我得到了一个异常(如预期的那样)。 我有两个问题要解决: 1)我得到的异常是无用的“ javax.ejb.EJBException:事务异常中止”。如果我递归调用get

  • 我在eclipse(java main method program)中运行一个脚本,它创建线程,每个线程处理一个excel表,然后将处理后的数据保存到数据库中。它已经处理数据2天了,今天突然我从excel处理完每条记录后打印的日志停止了。 我的代码的编写方式是,在处理完一个完整的工作表后,它将一条状态消息写入excel工作表记录中。这部分代码是在finally块中编写的。我一直在等待程序自行终止