我的网络应用中存在内存泄漏问题。当被少数人使用时,应用程序在大约7小时后内存不足。
这就是我的应用的工作原理:
dataSource = (DataSource) new InitialContext().lookup("java:comp/env/" + "jdbc/MyResName");
)。 <h:inputHidden value="true">
<f:validator binding="#{someValidator}"/>
</h:inputHidden>
并且实现是这样的:
@Named
public class SomeValidator extends ValidatorCommon implements Validator {
private final static Logger LOGGER = Logger.getLogger(SomeValidator.class);
@Override
public void validate(FacesContext fc, UIComponent uic, Object o) throws ValidatorException {...}
{...}
这是我的context.xml:
<Resource auth="Container"
driverClassName="org.sqlite.JDBC"
maxTotal="1"
maxIdle="1"
minIdle="1"
maxWaitMillis="5000"
initialSize="1"
name="jdbc/MyResName"
type="javax.sql.DataSource"
removeAbandonedOnBorrow="true"
removeAbandonedTimeout="5"
logAbandoned="true"
validationQuery="SELECT 1"
url="jdbc:sqlite:path/to/db/db.db">
</Resource>
我已经使用VisualVM创建了堆转储,并且MAT显示此漏洞可疑(https://i.imgur.com/wGsnyt5.png):
据我所知,每次请求/访问时都会创建RequestScoped bean,而从特定会话的容器中检索SessionScoped(或者如果它不存在则创建),即使我之间存在交叉引用豆,这一切都应该工作得很好。
这是我实际需要帮助的地方:如何分析这些泄漏的来源?肯定有一些东西不允许释放内存,但我怎么能找到它呢?
我使用的是Primefaces 6.0,Apache Tomcat(TomEE)/8.5.3(7.0.1),JDK 1.7.0_80-b15,Mojarra 2.2.6,sqlite-jdbc 3.14.2.1。
如果需要任何其他文件,请告诉我们,我会修改此帖子以添加它们。
Web.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>primefaces.FONT_AWESOME</param-name>
<param-value>true</param-value>
</context-param>
<resource-env-ref>
<resource-env-ref-name>jdbc/MyResName</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>
<!-- Welcome page -->
<welcome-file-list>
<welcome-file>pages/pub/login.xhtml</welcome-file>
</welcome-file-list>
<!-- Error pages -->
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/pages/pub/err/expired.xhtml</location>
</error-page>
<!-- Prevents comments in xhtml pages to be placed in final html and evaluated -->
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<!-- JSF mapping -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<!-- Primefaces theme -->
<context-param>
<param-name>primefaces.THEME</param-name>
<param-value>cupertino</param-value>
</context-param>
<session-config>
<session-timeout>120</session-timeout>
</session-config>
<filter>
<filter-name>forceUTF8CharSet</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>forceUTF8CharSet</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
<mime-mapping>
<extension>ttf</extension>
<mime-type>application/font-sfnt</mime-type>
</mime-mapping>
<mime-mapping>
<extension>woff</extension>
<mime-type>application/font-woff</mime-type>
</mime-mapping>
<mime-mapping>
<extension>woff2</extension>
<mime-type>application/font-woff2</mime-type>
</mime-mapping>
<mime-mapping>
<extension>eot</extension>
<mime-type>application/vnd.ms-fontobject</mime-type>
</mime-mapping>
<mime-mapping>
<extension>eot?#iefix</extension>
<mime-type>application/vnd.ms-fontobject</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg#latobold</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg#latoblack</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg#latolight</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg#latoregular</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>svg#fontawesomeregular</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
</web-app>
答案 0 :(得分:0)
可能首先尝试使用TomEE 7.0.2。如果它没有帮助,那么尝试调试WebContext map以检查哪些CDI bean没有被释放,那么你将能够知道谁(tomee,tomcat,primefaces,other)负责它并检查你是否可以解决它
答案 1 :(得分:0)
我设法解决了我的问题。
我的问题不在于我的任何bean,处理程序,验证程序,身份验证机制等。真正的问题是我在pom.xml中包含了两个库:
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.6</version>
</dependency>
我不太清楚TomEE在遇到两个独立的实现时会如何表现(TomEE自己及以上),但似乎有些东西阻止了对某些资源的引用,导致WebContext的大小总是增长(它持有所有参与请求处理的对象 - 跨多个页面。或者这可能是jsf实现中的一个错误?
如果有人能够解释实际发生的事情,那么我会接受这样的答案来解决我的问题。在那之前,这个答案(没有太多推理)是解决方案。