当前位置: 首页 > 编程日记 > 正文

java: web应用中不经意的内存泄露

前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下:

1、定义一个类App

package com.cnblogs.yjmyzz.web.controller;import java.util.Date;public class App {boolean isRun = false;public App() {isRun = true;}public void start() {while (isRun) {System.out.println("=======> I AM ALIVE =>" + new Date());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public void stop() {isRun = false;}}

代码里面的内容不是重点,只是示意一下,我打算在spring mvc 应用一启动时,就让这个类实例化,执行其中的start方法,即:每隔一秒输出一句话。

2、定义一个Listener

import com.cnblogs.yjmyzz.web.controller.App;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;@Component
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {App app;@Overridepublic void onApplicationEvent(ContextRefreshedEvent evt) {if (evt.getApplicationContext().getParent() == null) {new Thread(new Runnable() {@Overridepublic void run() {app = new App();app.start();}}).start();}}
}

代码也很简单,应用一启动,就开一个线程,实例化App,然后调用app.start()方法,运行一下,也跟预期的一样,每隔一秒输出类似下面的内容:

=======> I AM ALIVE =>Wed Sep 16 21:55:42 CST 2015

正式部署到jboss上以后,问题来了,在jboss管理控制台上,把这个应用给disable甚至remove后,日志里仍然不断有上面的类似输出,即app的实例仍然活着,其start方法也始终在运行,换句话说,app并没有被销毁。

简单分析一下:jboss的每个server启动后,会伴随启动一个jvm实例,而部署在该server上的web应用,里面创建的各种资源也在这个jvm实例中,就算把应用给停掉甚至删除,由于代码中没有任何清除app或停止start方法的处理,所以这个实例一直存在,不会被销毁,除非server重启。

另一个问题:如果把上面这段代码中,创建线程的部分去掉,改成直接 app = new App(); app.start(); 部署时会发现另一个现象,日志里仍然不断有输出,即代码在执行,但是该应用在jboss中的状态始终是isdeploying,部署一直无法结束,始终处于『部署中』的状态。

原因:start方法中的Thread.sleep()方法会阻塞线程,导致部署无法执行完毕。

解决办法:

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Date;@Component
public class App {boolean isRun = false;@PostConstructpublic void init() {System.out.println("init ==> " + new Date());isRun = true;}public void start() {while (isRun) {System.out.println("=======> I AM ALIVE =>" + new Date());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public void stop() {isRun = false;}@PreDestroypublic void destroy() {System.out.println("destroy ==> " + new Date());stop();}
}

这里做了几处改进:

a) 加上@Component后,App的实例将由Spring容器自动创建,即由容器来管理

b) 加上了@PreDestroy,Bean的生命周期由Spring容器来管理后,凡是Bean里加上该注解的方法,会在Bean销毁前被执行,通常该方法用于清理资源

c) 将初始化的工作,移到了init方法中,并通过@PostConstruct注解告诉Spring,在调用完Bean的默认构造方法后,自动来调用该方法(当然这一步是可选的,并非必须)

@Component
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {@AutowiredApp app;@Overridepublic void onApplicationEvent(ContextRefreshedEvent evt) {if (evt.getApplicationContext().getParent() == null) {new Thread(new Runnable() {@Overridepublic void run() {app.start();}}).start();}}}

Listener中就简单多了,直接@Autowired注入app实例就行了。

个人建议:

a) 如果要在web 应用一启动时,就执行某些操作,特别是对资源类的长连接实例创建(比如:加载数据到缓存中预热、连接到Zookeeper监控节点变化、连接到Ftp准备取数据),最好交给Spring容器来自动创建,且务必记得在Destroy前,清理资源(即:断开连接)

b) 在启动的执行逻辑中,不要使用阻塞线程的操作(比如:Thread.sleep之类的方法),否则部署时,实际上代码已经在后台执行了,jboss管理控制台上,一直处于部署中的状态,也没有任何输出,让人一头雾水,折腾半天才能定位错误,很浪费时间,如果是线上生产环境,是要粗事情的。

相关文章:

「游戏圈地震级消息」687亿美元,微软收购游戏巨头动视暴雪

整理 | 苏宓、禾木木 出品 | CSDN 2022年1月18日晚&#xff0c;一条热搜刷爆了朋友圈&#xff1a; 继 2018 年&#xff0c;微软以 75 亿美元收购全球知名的代码托管平台 GitHub 后&#xff0c;2022 年 1 月 18 日&#xff0c;微软将以 687 亿美元的价格收购著名游戏制作和发行公…

java实现用户登录注册功能(用集合框架来实现)

需求&#xff1a;实现用户登录注册功能(用集合框架来实现) 分析&#xff1a; A:需求的类和接口 1.用户类 UserBean 2.用户操作方法接口和实现类 UserDao UserDaoImpl 3.测试类 UserTest B:各个类中的东西 1.用户类UserBean: …

第3次翻译了 Pandas 官方文档,叒写了这一份R万字肝货操作!

作者 | 黄伟呢来源 | 数据分析与统计学之美今天&#xff0c;我继续为大家讲述Pandas如何实现R语言的相关操作。由于 Pandas 旨在提供人们使用 R 进行的大量数据操作和分析功能&#xff0c;因此本页开始提供更详细的 R 语言及其与 Pandas 相关的许多第三方库的介绍。与 R 和 CRA…

PHP autoload机制详解

PHP autoload机制详解 转载自 jeakcccPHP autoload机制详解(1) autoload机制概述在使用PHP的OO模式开发系统时&#xff0c;通常大家习惯上将每个类的实现都存放在一个单独的文件里&#xff0c;这样会很容易实现对类进行复用&#xff0c;同时将来维护时也很便利。这 也是OO设计…

有关博客的一些断想

作者&#xff1a;朱金灿来源&#xff1a;http://blog.csdn.net/clever101随着微博、微信等短平快社交媒体的兴起&#xff0c;文字相对严肃的博客毫无疑问受到很大的冲击。我在想博客会不会因此而消亡呢。我相信不会&#xff0c;因为喜欢轻快的文字固然是人类的天性&#xff0c;…

pythonl学习笔记——爬虫的基本常识

1 robots协议 Robots协议&#xff08;也称为爬虫协议、机器人协议等&#xff09;的全称是“网络爬虫排除标准”&#xff08;Robots Exclusion Protocol&#xff09;&#xff0c;网站通过Robots协议告诉搜索引擎哪些页面可以抓取&#xff0c;哪些页面不能抓取。 如&#xff1a; …

hibernate相关收集

2019独角兽企业重金招聘Python工程师标准>>> 1、Hibernate SQL方言 如果出现如下错误&#xff0c;则可能是Hibernate SQL方言 (hibernate.dialect)设置不正确。 Caused by: java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]last_ins…

盘一盘 2021 年程序员们喜欢的网站数据

作者 | 周萝卜来源 | 萝卜大杂烩世界上流量最大的网站有哪些&#xff0c;也许我们都能脱口而出&#xff0c;比如 Google&#xff0c;YouTube&#xff0c;Facebook 还有 PxxnHub 等等&#xff0c;今天我们就通过多个维度来看看&#xff0c;那些叱咤全球的流量网站&#xff01;数…

烽火18台系列之十一:刚需中的刚需——网站篡改监控

网站篡改事件近些年来越演越烈&#xff0c;其中包括政府、教育、金融、事业企业单位等。根据国家互联网应急响应中心发布的《2015年中国互联网网络安全报告》中指出&#xff0c;“2015年CNCERT/CC工检测到境内被篡改的网站数量为24550个&#xff0c;其中境内政府网站篡改数量为…

Http与RPC通信协议的比较

OSI网络结构的七层模型 各层的具体描述如下&#xff1a;第七层&#xff1a;应用层 定义了用于在网络中进行通信和数据传输的接口 - 用户程式&#xff1b;提供标准服务&#xff0c;比如虚拟终端、文件以及任务的传输 和处理&#xff1b; 第六层&#xff1a;表示层 掩…

基于 Python 和 OpenCV 构建智能停车系统

作者 | 努比来源 | 小白学视觉当今时代最令人头疼的事情就是找不到停车位&#xff0c;尤其是找20分钟还没有找到停车位。根据复杂性和效率的不同&#xff0c;任何问题都具有一个或多个解决方案。目前智能停车系统的解决方案&#xff0c;主要包括基于深度学习实现&#xff0c;以…

js获取鼠标位置

1.PageX/PageX:鼠标在页面上的位置,从页面左上角开始,即是以页面为参考点,不随滑动条移动而变化2.clientX/clientY:鼠标在页面上可视区域的位置,从浏览器可视区域左上角开始,即是以浏览器滑动条此刻的滑动到的位置为参考点,随滑动条移动 而变化. 可是悲剧的是,PageX只有FF…

Lua保留指定小数位数

默认会四舍五入 比如&#xff1a;%0.2f 会四舍五入后&#xff0c;保留小数点后2位print(string.format("%.1f",0.26)) ---会输出0.3&#xff0c;而不是0.2 Lua保留一位小数 --- nNum 源数字 --- n 小数位数 function Tool. GetPreciseDecimal(nNum, n)if type(nNum)…

htaccess文件用法收集整理

1.时区设置有些时候&#xff0c;当你在PHP里使用date或mktime函数时&#xff0c;由于时区的不同&#xff0c;它会显示出一些很奇怪的信息。下面是解决这个问题的方法之一。就是设置你的服务器的时区。你可以在这里找到所有支持的时区的清单。 1.SetEnv TZ Australia/Melbourne …

手把手教你使用 YOLOV5 训练目标检测模型

作者 | 肆十二来源 | CSDN博客这次要使用YOLOV5来训练一个口罩检测模型&#xff0c;比较契合当下的疫情&#xff0c;并且目标检测涉及到的知识点也比较多。先来看看我们要实现的效果&#xff0c;我们将会通过数据来训练一个口罩检测的模型&#xff0c;并用pyqt5进行封装&#x…

数据仓库数据模型之:极限存储--历史拉链表

摘要: 在数据仓库的数据模型设计过程中&#xff0c;经常会遇到文内所提到的这样的需求。而历史拉链表&#xff0c;既能满足对历史数据的需求&#xff0c;又能很大程度的节省存储资源。在数据仓库的数据模型设计过程中&#xff0c;经常会遇到这样的需求&#xff1a;1. 数据量比较…

super的用法(带了解)

super的用法&#xff08;带了解&#xff09; super的用法&#xff08;带了解&#xff09;posted on 2018-05-11 21:31 leolaosao 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/leolaosao/p/9026686.html

Posted content type isn't multipart/form-data

版权声明&#xff1a;欢迎转载&#xff0c;请注明沉默王二原创。 https://blog.csdn.net/qing_gee/article/details/48712507 在有文件上传的表单提交过程中&#xff0c;搞不好就会报Posted content type isnt multipart/form-data的错误。 解决办法 <form class"form-…

CSDN 十大技术主题盘点-AI篇

关于2021&#xff0c;我们能看到的技术变化有很多。当云原生向下而生&#xff0c;当分布式数据库席卷而至&#xff0c;当低代码平台扩展了开发的边界&#xff0c;当万物互联蔚然成风……我们看到了太多在2021年形成的变化&#xff0c;但也能看到这些趋势非但没有结束&#xff0…

PHP编程问题集锦

1. Win32下apache2用get方法传递中文参数会出错 test.php?a你好&b你也好传递参数是会导致一个内部错误解决办法:"test.php?a".urlencode(你好)."&b".urlencode(你也好)2. win32下的session不能正常工作 php.ini默认的session.save_path /tmp 这…

jsonp详解

json相信大家都用的多&#xff0c;jsonp我就一直没有机会用到&#xff0c;但也经常看到&#xff0c;只知道是“用来跨域的”&#xff0c;一直不知道具体是个什么东西。今天总算搞明白了。下面一步步来搞清楚jsonp是个什么玩意。 同源策略 首先基于安全的原因&#xff0c;浏览器…

PHP面向对象精华

PHP面向对象精华1 使用extends实现继承以及重载、魔术方法的含义 class B extends A 声明的时候B里可以没有A里的方法 调用的时候$bnew B(); $b->A里的方法(); $b->A里的属性1; $b->B里的方法(); $b->B里的方法(); 如果$anew A(); 可以 $a->A里的方法(); $a->…

springmvc和mybatis整合关键配置

springmvcmybaits的系统架构&#xff1a; 第一步&#xff1a;整合dao层 mybatis和spring整合&#xff0c;通过spring管理mapper接口。 使用mapper的扫描器自动扫描mapper接口在spring中进行注册。 第二步&#xff1a;整合service层 通过spring管理 service接口。 使用配置方式将…

阿里亲制明信片,字节、百度直接发锅……这些公司的新年礼盒越来越会玩~

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍整理 | 王晓曼出品 | 程序人生&#xff08;ID&#xff1a;coder _life&#xff09;每到年末&#xff0c;各大互联网大厂的新年礼盒都会作为…

html中radio、checkbox选中状态研究(静下心来看,静下心来总结)

html中radio、checkbox选中状态研究&#xff08;静下心来看&#xff0c;静下心来总结&#xff09; 一、总结 1、单选框的如果有多个checked 会以最后一个为准 2、js动态添加checked属性&#xff1a;不行&#xff1a;通过 $("[namesex]:eq(1)").attr("checked&q…

新年新气象,100 行 Python 代码制作动态鞭炮

作者 | FrigidWinter来源 | CSDN博客放鞭炮贺新春&#xff0c;在我国有两千多年历史。关于鞭炮的起源&#xff0c;有个有趣的传说。西方山中有焉&#xff0c;长尺余&#xff0c;一足&#xff0c;性不畏人。犯之令人寒热&#xff0c;名曰年惊惮&#xff0c;后人遂象其形&#xf…

php 反射类简介

反射是操纵面向对象范型中元模型的API&#xff0c;其功能十分强大&#xff0c;可帮助我们构建复 杂&#xff0c;可扩展的应用。其用途如&#xff1a;自动加载插件&#xff0c;自动生成文档&#xff0c;甚至可用来扩充 PHP 语言。php 反射api 由若干类组成&#xff0c;可帮助我们…

shell时间

Shell 调用系统时间变量 Linux常用命令获取今天时期&#xff1a;date %Y%m%d 或 date %F 或 $(date %y%m%d) 获取昨天时期&#xff1a;date -d yesterday %Y%m%d 获取前天日期&#xff1a;date -d -2day %Y%m%d 依次类推比如获取10天前的日期&#xff1a;date -d -10day %Y%m%d…

杨老师课堂_Java核心技术下之控制台模拟记事本案例...

预览效果图&#xff1a; 背景介绍&#xff1a; 编写一个模拟记事本的程序通过在控制台输入指令&#xff0c;实现在本地新建文件打开文件和修改文件等功能。 要求在程序中&#xff1a; 用户输入指令1代表“新建文件”&#xff0c;此时可以从控制台获取用户输入的文件内容&#x…

PHP的URL处理

完整URL地址&#xff1a; http://username:passwordhostname/path?argvalue#auchor 协议&#xff1a;http:// 用户名和密码&#xff1a; username:password 以&#xff1a;将两者分隔 主机名&#xff1a;hostname 和/为分隔符 路径&#xff1a; /path 以/开头、包含/符号 参…