botteonr opened a new issue, #1935:
URL: https://github.com/apache/plc4x/issues/1935
### What happened?
Production use case:
- Constantly reading and writing (every second) from and to a Plc via modbus
tcp.
Issue:
- After running for days (or weeks depend on -Xmx) the application crashes
because an OutOfMemoryError.
Comparing dumps (from production) show an increase of byte[] objects like:
`java.lang.String#45053 :
FooRxEntity$ByteBuddy$opFq0T9M$auxiliary$5LGzfXOE`.
The ByteBuddy instances are created here:
```org.apache.plc4x.java.opm.PlcEntityManager#connect(java.lang.Class<T>,
java.lang.String, T)```
therefore I think that PlcEntityManager is responsible for the leak.
Code to reproduce the issue:
```java
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import org.apache.plc4x.java.DefaultPlcDriverManager;
import org.apache.plc4x.java.api.exceptions.PlcConnectionException;
import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.mock.connection.MockConnection;
import org.apache.plc4x.java.mock.connection.MockDevice;
import org.apache.plc4x.java.opm.OPMException;
import org.apache.plc4x.java.opm.PlcEntityManager;
import org.apache.plc4x.java.spi.messages.utils.ResponseItem;
import org.apache.plc4x.java.spi.values.PlcSTRING;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
public class Plc4jMockConnectionTest {
@Test
void shouldRead() throws PlcConnectionException {
MockDevice mockDevice = Mockito.mock(MockDevice.class);
DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
MockConnection connection = (MockConnection)
driverManager.getConnection("mock:test");
when(mockDevice.read(any())).thenAnswer(invocation -> new
ResponseItem(PlcResponseCode.OK, new PlcSTRING("1")));
connection.setDevice(mockDevice);
PlcEntityManager entityManager = new PlcEntityManager(driverManager);
while (true) {
try {
FooRxEntity read = entityManager.read(FooRxEntity.class,
"mock:test");
Thread.sleep(10);
} catch (OPMException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
```
And the entity:
```java
import org.apache.plc4x.java.opm.PlcEntity;
import org.apache.plc4x.java.opm.PlcTag;
@PlcEntity
public class FooRxEntity {
@PlcTag("input-register:1:WORD")
private short bp102;
@PlcTag("input-register:2:WORD")
private short bp105;
@PlcTag("input-register:3:WORD")
private short bp112;
@PlcTag("input-register:4:WORD")
private short bp115;
@PlcTag("input-register:5:WORD")
private short bp122;
@PlcTag("input-register:6:WORD")
private short bp125;
@PlcTag("input-register:7:WORD")
private short bp360;
@PlcTag("input-register:8:WORD")
private short bp260;
@PlcTag("input-register:9:WORD")
private short bf102;
@PlcTag("input-register:10:WORD")
private short bf112;
@PlcTag("input-register:11:WORD")
private short bf122;
@PlcTag("input-register:21:WORD")
private short bt220;
@PlcTag("input-register:22:WORD")
private short bt230;
@PlcTag("input-register:23:WORD")
private short bt260;
@PlcTag("input-register:24:WORD")
private short bt320;
@PlcTag("input-register:25:WORD")
private short bt330;
@PlcTag("input-register:26:WORD")
private short bt360;
@PlcTag("holding-register:2049:WORD")
private int bf102Setpoint;
@PlcTag("holding-register:2050:WORD")
private int bf112Setpoint;
@PlcTag("holding-register:2051:WORD")
private int bf122Setpoint;
@PlcTag("holding-register:2057:WORD")
private short qm;
}
```
The test is started with VM options `-Xms128m -Xmx128m`. After ~4 minutes
OOM is thrown.

I can reproduce the OOE with a real connection. This take a lot more time
because the plc support a max reading rate of ~300ms.
Real test:
```java
@Test
void shouldRead() {
PlcDriverManager driverManager = new DefaultPlcDriverManager();
PlcConnectionManager connectionManager =
driverManager.getConnectionManager();
PlcEntityManager entityManager = new PlcEntityManager(connectionManager);
while (true) {
try {
FooRxEntity read = entityManager.read(FooRxEntity.class,
"modbus-tcp:tcp://192.168.100.222:502");
Thread.sleep(300);
} catch (OPMException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
```
Mock dump:
[heapdump-1733998935197.zip](https://github.com/user-attachments/files/18109924/heapdump-1733998935197.zip)
Production dump:
[heapdump-1732691913936.zip](https://drive.proton.me/urls/TG7PBNMKJ0#0xVnVgoyf7CW)
Please let me know if you need more details and thank you in advance.
### Version
v0.12.0
### Programming Languages
- [X] plc4j
- [ ] plc4go
- [ ] plc4c
- [ ] plc4net
### Protocols
- [ ] AB-Ethernet
- [ ] ADS /AMS
- [ ] BACnet/IP
- [ ] CANopen
- [ ] DeltaV
- [ ] DF1
- [ ] EtherNet/IP
- [ ] Firmata
- [ ] KNXnet/IP
- [X] Modbus
- [ ] OPC-UA
- [ ] S7
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]