[
https://issues.jboss.org/browse/WFLY-12446?page=com.atlassian.jira.plugin...
]
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)