mirror of
https://gitee.com/arthas/arthas.git
synced 2024-12-02 04:08:34 +08:00
upgrade to fastjson2. #2498
This commit is contained in:
parent
a1e7fe59b6
commit
b73475fe08
@ -57,8 +57,8 @@
|
||||
<shadedPattern>${arthas.deps.package}.io.netty</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>com.alibaba.fastjson</pattern>
|
||||
<shadedPattern>${arthas.deps.package}.com.alibaba.fastjson</shadedPattern>
|
||||
<pattern>com.alibaba.fastjson2</pattern>
|
||||
<shadedPattern>${arthas.deps.package}.com.alibaba.fastjson2</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
@ -204,8 +204,8 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ognl</groupId>
|
||||
@ -258,7 +258,6 @@
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -10,8 +10,8 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.command.model.DashboardModel;
|
||||
import com.taobao.arthas.core.command.model.GcInfoVO;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.taobao.arthas.core.distribution;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.taobao.arthas.core.command.model.Countable;
|
||||
import com.taobao.arthas.core.command.model.ResultModel;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -2,7 +2,7 @@ package com.taobao.arthas.core.distribution.impl;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.taobao.arthas.core.command.model.ResultModel;
|
||||
import com.taobao.arthas.core.distribution.PackingResultDistributor;
|
||||
import com.taobao.arthas.core.shell.session.Session;
|
||||
|
@ -2,7 +2,7 @@ package com.taobao.arthas.core.distribution.impl;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.taobao.arthas.core.command.model.ResultModel;
|
||||
import com.taobao.arthas.core.distribution.DistributorOptions;
|
||||
import com.taobao.arthas.core.distribution.ResultConsumer;
|
||||
|
@ -34,8 +34,8 @@ import com.alibaba.bytekit.asm.instrument.InstrumentTransformer;
|
||||
import com.alibaba.bytekit.asm.matcher.SimpleClassMatcher;
|
||||
import com.alibaba.bytekit.utils.AsmUtils;
|
||||
import com.alibaba.bytekit.utils.IOUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.taobao.arthas.common.AnsiLog;
|
||||
import com.taobao.arthas.common.ArthasConstants;
|
||||
import com.taobao.arthas.common.PidUtils;
|
||||
@ -177,14 +177,9 @@ public class ArthasBootstrap {
|
||||
}
|
||||
|
||||
private void initFastjson() {
|
||||
// disable fastjson circular reference feature
|
||||
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
|
||||
// add date format option for fastjson
|
||||
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteDateUseDateFormat.getMask();
|
||||
// ignore getter error #1661
|
||||
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.IgnoreErrorGetter.getMask();
|
||||
// #2081
|
||||
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNonStringKeyAsString.getMask();
|
||||
JSON.config(JSONWriter.Feature.IgnoreErrorGetter, JSONWriter.Feature.WriteNonStringKeyAsString);
|
||||
}
|
||||
|
||||
private void initBeans() {
|
||||
|
@ -64,13 +64,11 @@ public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequ
|
||||
path = "/index.html";
|
||||
}
|
||||
|
||||
boolean isHttpApiResponse = false;
|
||||
boolean isFileResponseFinished = false;
|
||||
try {
|
||||
//handle http restful api
|
||||
if ("/api".equals(path)) {
|
||||
response = httpApiHandler.handle(ctx, request);
|
||||
isHttpApiResponse = true;
|
||||
}
|
||||
|
||||
//handle webui requests
|
||||
@ -106,16 +104,6 @@ public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequ
|
||||
if (!isFileResponseFinished) {
|
||||
ChannelFuture future = writeResponse(ctx, response);
|
||||
future.addListener(ChannelFutureListener.CLOSE);
|
||||
//reuse http api response buf
|
||||
if (isHttpApiResponse && response instanceof DefaultFullHttpResponse) {
|
||||
final HttpResponse finalResponse = response;
|
||||
future.addListener(new ChannelFutureListener() {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
httpApiHandler.onCompleted((DefaultFullHttpResponse) finalResponse);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,8 @@ package com.taobao.arthas.core.shell.term.impl.http.api;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializeConfig;
|
||||
import com.alibaba.fastjson.serializer.SerializeFilter;
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.alibaba.fastjson.util.IOUtils;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.filter.ValueFilter;
|
||||
import com.taobao.arthas.common.ArthasConstants;
|
||||
import com.taobao.arthas.common.PidUtils;
|
||||
import com.taobao.arthas.core.command.model.*;
|
||||
@ -34,7 +31,6 @@ import com.taobao.arthas.core.shell.term.impl.http.session.HttpSession;
|
||||
import com.taobao.arthas.core.shell.term.impl.http.session.HttpSessionManager;
|
||||
import com.taobao.arthas.core.util.ArthasBanner;
|
||||
import com.taobao.arthas.core.util.DateUtils;
|
||||
import com.taobao.arthas.core.util.JsonUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
@ -68,25 +64,11 @@ public class HttpApiHandler {
|
||||
private final JobController jobController;
|
||||
private final HistoryManager historyManager;
|
||||
|
||||
private int jsonBufferSize = 1024 * 256;
|
||||
private int poolSize = 8;
|
||||
private ArrayBlockingQueue<ByteBuf> byteBufPool = new ArrayBlockingQueue<ByteBuf>(poolSize);
|
||||
private ArrayBlockingQueue<char[]> charsBufPool = new ArrayBlockingQueue<char[]>(poolSize);
|
||||
private ArrayBlockingQueue<byte[]> bytesPool = new ArrayBlockingQueue<byte[]>(poolSize);
|
||||
|
||||
public HttpApiHandler(HistoryManager historyManager, SessionManager sessionManager) {
|
||||
this.historyManager = historyManager;
|
||||
this.sessionManager = sessionManager;
|
||||
commandManager = this.sessionManager.getCommandManager();
|
||||
jobController = this.sessionManager.getJobController();
|
||||
|
||||
//init buf pool
|
||||
JsonUtils.setSerializeWriterBufferThreshold(jsonBufferSize);
|
||||
for (int i = 0; i < poolSize; i++) {
|
||||
byteBufPool.offer(Unpooled.buffer(jsonBufferSize));
|
||||
charsBufPool.offer(new char[jsonBufferSize]);
|
||||
bytesPool.offer(new byte[jsonBufferSize]);
|
||||
}
|
||||
}
|
||||
|
||||
public HttpResponse handle(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
|
||||
@ -113,77 +95,13 @@ public class HttpApiHandler {
|
||||
}
|
||||
result.setRequestId(requestId);
|
||||
|
||||
byte[] jsonBytes = JSON.toJSONBytes(result, JSON_FILTERS);
|
||||
|
||||
//http response content
|
||||
ByteBuf content = null;
|
||||
//fastjson buf
|
||||
char[] charsBuf = null;
|
||||
byte[] bytesBuf = null;
|
||||
|
||||
try {
|
||||
//apply response content buf first
|
||||
content = byteBufPool.poll(2000, TimeUnit.MILLISECONDS);
|
||||
if (content == null) {
|
||||
throw new ApiException("get response content buf failure");
|
||||
}
|
||||
|
||||
//apply fastjson buf from pool
|
||||
charsBuf = charsBufPool.poll();
|
||||
bytesBuf = bytesPool.poll();
|
||||
if (charsBuf == null || bytesBuf == null) {
|
||||
throw new ApiException("get json buf failure");
|
||||
}
|
||||
JsonUtils.setSerializeWriterBufThreadLocal(charsBuf, bytesBuf);
|
||||
|
||||
//create http response
|
||||
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(),
|
||||
HttpResponseStatus.OK, content.retain());
|
||||
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");
|
||||
writeResult(response, result);
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
//response is discarded
|
||||
if (content != null) {
|
||||
content.release();
|
||||
byteBufPool.offer(content);
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
//give back json buf to pool
|
||||
JsonUtils.setSerializeWriterBufThreadLocal(null, null);
|
||||
if (charsBuf != null) {
|
||||
charsBufPool.offer(charsBuf);
|
||||
}
|
||||
if (bytesBuf != null) {
|
||||
bytesPool.offer(bytesBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onCompleted(DefaultFullHttpResponse httpResponse) {
|
||||
ByteBuf content = httpResponse.content();
|
||||
content.clear();
|
||||
if (content.capacity() == jsonBufferSize) {
|
||||
if (!byteBufPool.offer(content)) {
|
||||
content.release();
|
||||
}
|
||||
} else {
|
||||
//replace content ByteBuf
|
||||
content.release();
|
||||
if (byteBufPool.remainingCapacity() > 0) {
|
||||
byteBufPool.offer(Unpooled.buffer(jsonBufferSize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeResult(DefaultFullHttpResponse response, Object result) throws IOException {
|
||||
ByteBufOutputStream out = new ByteBufOutputStream(response.content());
|
||||
try {
|
||||
JSON.writeJSONString(out, IOUtils.UTF8, result, SerializeConfig.globalInstance, JSON_FILTERS, null, JSON.DEFAULT_GENERATE_FEATURE);
|
||||
} catch (IOException e) {
|
||||
logger.error("write json to response failed", e);
|
||||
throw e;
|
||||
}
|
||||
// create http response
|
||||
DefaultFullHttpResponse response = new DefaultFullHttpResponse(request.protocolVersion(),
|
||||
HttpResponseStatus.OK, Unpooled.wrappedBuffer(jsonBytes));
|
||||
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=utf-8");
|
||||
return response;
|
||||
}
|
||||
|
||||
private ApiRequest parseRequest(String requestBody) throws ApiException {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.taobao.arthas.core.shell.term.impl.http.api;
|
||||
|
||||
import com.alibaba.fastjson.serializer.ValueFilter;
|
||||
import com.alibaba.fastjson2.filter.ValueFilter;
|
||||
import com.taobao.arthas.core.command.model.ObjectVO;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.view.ObjectView;
|
||||
@ -12,8 +12,7 @@ import com.taobao.arthas.core.view.ObjectView;
|
||||
public class ObjectVOFilter implements ValueFilter {
|
||||
|
||||
@Override
|
||||
public Object process(Object object, String name, Object value) {
|
||||
|
||||
public Object apply(Object object, String name, Object value) {
|
||||
if (value instanceof ObjectVO) {
|
||||
ObjectVO vo = (ObjectVO) value;
|
||||
String resultStr = StringUtils.objectToString(vo.needExpand() ? new ObjectView(vo).draw() : value);
|
||||
|
@ -1,93 +0,0 @@
|
||||
package com.taobao.arthas.core.util;
|
||||
|
||||
import com.alibaba.fastjson.serializer.SerializeWriter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author gongdewei 2020/5/15
|
||||
*/
|
||||
public class JsonUtils {
|
||||
private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);
|
||||
private static Field serializeWriterBufLocalField;
|
||||
private static Field serializeWriterBytesBufLocal;
|
||||
private static Field serializeWriterBufferThreshold;
|
||||
|
||||
/**
|
||||
* Set Fastjson SerializeWriter Buffer Threshold
|
||||
* @param value
|
||||
*/
|
||||
public static void setSerializeWriterBufferThreshold(int value) {
|
||||
Class<SerializeWriter> clazz = SerializeWriter.class;
|
||||
try {
|
||||
if (serializeWriterBufferThreshold == null) {
|
||||
serializeWriterBufferThreshold = clazz.getDeclaredField("BUFFER_THRESHOLD");
|
||||
}
|
||||
serializeWriterBufferThreshold.setAccessible(true);
|
||||
serializeWriterBufferThreshold.set(null, value);
|
||||
} catch (Throwable e) {
|
||||
logger.error("update SerializeWriter.BUFFER_THRESHOLD value failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Fastjson SerializeWriter ThreadLocal value
|
||||
* @param bufSize
|
||||
*/
|
||||
public static void setSerializeWriterBufThreadLocal(int bufSize) {
|
||||
Class<SerializeWriter> clazz = SerializeWriter.class;
|
||||
try {
|
||||
//set threadLocal value
|
||||
if (serializeWriterBufLocalField == null) {
|
||||
serializeWriterBufLocalField = clazz.getDeclaredField("bufLocal");
|
||||
}
|
||||
serializeWriterBufLocalField.setAccessible(true);
|
||||
ThreadLocal<char[]> bufLocal = (ThreadLocal<char[]>) serializeWriterBufLocalField.get(null);
|
||||
char[] charsLocal = bufLocal.get();
|
||||
if (charsLocal == null || charsLocal.length < bufSize) {
|
||||
bufLocal.set(new char[bufSize]);
|
||||
}
|
||||
|
||||
if (serializeWriterBytesBufLocal == null) {
|
||||
serializeWriterBytesBufLocal = clazz.getDeclaredField("bytesBufLocal");
|
||||
}
|
||||
serializeWriterBytesBufLocal.setAccessible(true);
|
||||
ThreadLocal<byte[]> bytesBufLocal = (ThreadLocal<byte[]>) serializeWriterBytesBufLocal.get(null);
|
||||
byte[] bytesLocal = bytesBufLocal.get();
|
||||
if (bytesLocal == null || bytesLocal.length < bufSize) {
|
||||
bytesBufLocal.set(new byte[bufSize]);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
logger.error("update SerializeWriter.BUFFER_THRESHOLD value failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Fastjson SerializeWriter ThreadLocal value
|
||||
*/
|
||||
public static void setSerializeWriterBufThreadLocal(char[] charsBuf, byte[] bytesBuf) {
|
||||
Class<SerializeWriter> clazz = SerializeWriter.class;
|
||||
try {
|
||||
//set threadLocal value
|
||||
if (serializeWriterBufLocalField == null) {
|
||||
serializeWriterBufLocalField = clazz.getDeclaredField("bufLocal");
|
||||
}
|
||||
serializeWriterBufLocalField.setAccessible(true);
|
||||
ThreadLocal<char[]> bufLocal = (ThreadLocal<char[]>) serializeWriterBufLocalField.get(null);
|
||||
bufLocal.set(charsBuf);
|
||||
|
||||
if (serializeWriterBytesBufLocal == null) {
|
||||
serializeWriterBytesBufLocal = clazz.getDeclaredField("bytesBufLocal");
|
||||
}
|
||||
serializeWriterBytesBufLocal.setAccessible(true);
|
||||
ThreadLocal<byte[]> bytesBufLocal = (ThreadLocal<byte[]>) serializeWriterBytesBufLocal.get(null);
|
||||
bytesBufLocal.set(bytesBuf);
|
||||
} catch (Throwable e) {
|
||||
logger.error("update SerializeWriter.BUFFER_THRESHOLD value failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package com.taobao.arthas.core.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.taobao.arthas.common.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -2,8 +2,8 @@ package com.taobao.arthas.core.view;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.taobao.arthas.common.ArthasConstants;
|
||||
import com.taobao.arthas.core.GlobalOptions;
|
||||
import com.taobao.arthas.core.command.model.ObjectVO;
|
||||
@ -54,7 +54,7 @@ public class ObjectView implements View {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
try {
|
||||
if (GlobalOptions.isUsingJson) {
|
||||
return JSON.toJSONString(object, SerializerFeature.IgnoreErrorGetter);
|
||||
return JSON.toJSONString(object, JSONWriter.Feature.IgnoreErrorGetter);
|
||||
}
|
||||
renderObject(object, 0, deep, buf);
|
||||
return buf.toString();
|
||||
|
6
pom.xml
6
pom.xml
@ -136,9 +136,9 @@
|
||||
<version>0.0.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.83_noneautotype</version>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2</artifactId>
|
||||
<version>2.0.29</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.taobao.text</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user