You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@johnzon.apache.org by "liucongcong (Jira)" <ji...@apache.org> on 2023/04/09 04:50:00 UTC
[jira] [Created] (JOHNZON-396) JsonStreamParserImpl has a memory leak problem
liucongcong created JOHNZON-396:
-----------------------------------
Summary: JsonStreamParserImpl has a memory leak problem
Key: JOHNZON-396
URL: https://issues.apache.org/jira/browse/JOHNZON-396
Project: Johnzon
Issue Type: Bug
Components: Core
Affects Versions: 1.1.10, 1.2.19
Reporter: liucongcong
Attachments: image-2023-04-09-12-09-44-529.png, image-2023-04-09-12-44-02-385.png, image-2023-04-09-12-44-39-048.png, image-2023-04-09-12-45-10-166.png
When some large strings are parsed, the JsonStreamParserImpl's buffer will doAutoAdjust(..).
In doAutoAdjust method, the first time fallBackCopyBuffer will release to bufferProvider, i found the fallBackCopyBuffer is from valueBuffer but release to bufferProvider.
When using the default QUEUE BufferStrategy and always trigger the doAutoAdjust will cause a OOM fault.
this is my unit test case:
{code:java}
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonParser;
import javax.json.stream.JsonParserFactory;
import org.apache.johnzon.core.JsonParserFactoryImpl;
import org.junit.Test;
public class JsonStreamBufferMemoryLeakTestCase {
@Test
public void normalCase() {
Map<String, Object> config = new HashMap<>();
config.put(JsonParserFactoryImpl.MAX_STRING_LENGTH, 4);
JsonParserFactory parserFactory = JsonProvider.provider()
.createParserFactory(config);
JsonParser parser = parserFactory
.createParser(new StringReader("{ \"a\": \"\\\"a2\\\"\" }"));
parser.getValue();
parser.close();
// parserFactory.bufferProvider.queue.size() = 1
// parserFactory.valueBufferProvider.queue.size() = 1
System.out.println(parserFactory); // debugger breakpoint for view queue size.
}
@Test
public void leakCase() {
Map<String, Object> config = new HashMap<>();
config.put(JsonParserFactoryImpl.MAX_STRING_LENGTH, 2);
JsonParserFactory parserFactory = JsonProvider.provider()
.createParserFactory(config);
JsonParser parser = parserFactory
.createParser(new StringReader("{ \"a\": \"\\\"a2\\\"\" }"));
parser.getValue();
parser.close();
// expect: parserFactory.bufferProvider.queue.size() = 1 and parserFactory.valueBufferProvider.queue.size() = 1
// but: parserFactory.bufferProvider.queue.size() = 2 and parserFactory.valueBufferProvider.queue.size() = 0
parser = parserFactory
.createParser(new StringReader("{ \"a\": \"\\\"a2\\\"\" }"));
parser.getValue();
parser.close();
// expect: parserFactory.bufferProvider.queue.size() = 1 and parserFactory.valueBufferProvider.queue.size() = 1
// but: parserFactory.bufferProvider.queue.size() = 3 and parserFactory.valueBufferProvider.queue.size() = 0
parser = parserFactory
.createParser(new StringReader("{ \"a\": \"\\\"a2\\\"\" }"));
parser.getValue();
parser.close();
// expect: parserFactory.bufferProvider.queue.size() = 1 and parserFactory.valueBufferProvider.queue.size() = 1
// but: parserFactory.bufferProvider.queue.size() = 4 and parserFactory.valueBufferProvider.queue.size() = 0
System.out.println(parserFactory); // debugger breakpoint for view queue size.
}
}{code}
source code analysis:
!image-2023-04-09-12-44-02-385.png|width=734,height=185!
!image-2023-04-09-12-44-39-048.png|width=716,height=203!
!image-2023-04-09-12-45-10-166.png|width=702,height=122!
--
This message was sent by Atlassian Jira
(v8.20.10#820010)