[jboss-jira] [JBoss JIRA] (WFLY-12446) Memory leak in StatelessSessionComponent
Matěj Novotný (Jira)
issues at jboss.org
Wed Sep 11 07:25:02 EDT 2019
[ https://issues.jboss.org/browse/WFLY-12446?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13782798#comment-13782798 ]
Matěj Novotný commented on WFLY-12446:
--------------------------------------
Alright, I think I see the issue - *doesn't look like a bug but a user error* . Like I said above, when you retrieve {{@Dependent}} instances via {{Instance}}, you need to keep reference to them and destroy them. Note that every invocation of {{Instance.get()}} gives you new, different instance of the bean that you need to destroy and a for cycle over {{Instance}} means you invoke {{get()}} in order to grab each of those beans.
Therefore in the following code(from example), two sets of {{Command}} instances are created but only one is destroyed (mind the NOTEs I added to the code):
{code}
public CommandResult executeCommand(String commandName, String parameter) {
CommandResult result = null;
logger.infof("CommandService: searching for command -> %s", commandName);
if (commands != null) {
// search command
for (Command command : commands) {
// NOTE - this instantiates the command beans but no destroy is invoked within this for cycle!
String name = command.getName();
logger.infof(" ... %s", name);
// execute if found
if (commandName.equals(name)) {
logger.infof(" ... found command, executing %s", name);
result = command.execute(name + ": " + parameter);
break;
}
}
// command found?
if (result == null) {
logger.infof("CommandService: command not found -> %s", commandName);
result = new CommandResult(0L, "Undefined");
}
// avoid memory leak
logger.info("destroying commands to avoid memory leak!");
for (Command command : commands) {
// NOTE - this is redundant, it created new/different instances of Command and destroys those only!
commands.destroy(command);
}
} else {
logger.info("CommandService: no commands available!");
}
return result;
}
{code}
You can fix this easily by changing the first for cycle as follows and dropping the second one:
{code}
for (Command command : commands) {
String name = command.getName();
logger.infof(" ... %s", name);
// execute if found
if (commandName.equals(name)) {
logger.infof(" ... found command, executing %s", name);
result = command.execute(name + ": " + parameter);
// destroy the instance
commands.destroy(command);
break;
} else {
// destroy the instance
commands.destroy(command);
}
}
{code}
Fixing the code like this, jconsole shows me much less memory used during the load test and especially not hanging around afterwards.
> Memory leak in StatelessSessionComponent
> ----------------------------------------
>
> Key: WFLY-12446
> URL: https://issues.jboss.org/browse/WFLY-12446
> Project: WildFly
> Issue Type: Bug
> Components: CDI / Weld, EJB
> Affects Versions: 17.0.1.Final
> Reporter: Joerg Baesner
> Assignee: Cheng Fang
> Priority: Major
> Attachments: dump-weld.png, playground-jee8.zip, server.log.gz, wfly-12446-heap-dump.png
>
>
> When running the attached reproducer application and doing a memory analysis afterwards, it looks like a memory leak, e. g.
> {code}
> One instance of "org.jboss.as.ejb3.component.stateless.StatelessSessionComponent" loaded by "org.jboss.modules.ModuleClassLoader @ 0x5e0fbc2e0" occupies 936,593,520 (96.13%) bytes. The memory is accumulated in one instance of "java.util.concurrent.ConcurrentLinkedQueue$Node" loaded by "<system class loader>".
> {code}
--
This message was sent by Atlassian Jira
(v7.13.5#713005)
More information about the jboss-jira
mailing list