如何使用Jackson对JDI的Value对象进行内容查看与格式化JSON输出
问题原因
你直接用Jackson序列化JDI的Value对象无法获取业务数据,Value只是JDI提供的远端目标JVM对象的本地代理类,本身仅存储了远端对象的引用状态、是否被回收等元信息,你看到的collected字段就是代理类自带的属性,和远端真实对象的业务字段无关。
解决方案
不需要手动编写全量递归判断逻辑,给Jackson注册对应Value各子类型的自定义序列化器即可,步骤如下:
- 编写
Value类型的通用序列化器,自动处理类型分发和递归序列化
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.sun.jdi.*; import java.io.IOException; public class JdiValueSerializer extends StdSerializer<Value> { public JdiValueSerializer() { super(Value.class); } @Override public void serialize(Value value, JsonGenerator gen, SerializerProvider provider) throws IOException { if (value == null) { gen.writeNull(); return; } // 按实际子类型分发处理 if (value instanceof StringReference) { gen.writeString(((StringReference) value).value()); } else if (value instanceof PrimitiveValue) { // 处理基本类型/包装类型 if (value instanceof BooleanValue) { gen.writeBoolean(((BooleanValue) value).value()); } else if (value instanceof ByteValue) { gen.writeNumber(((ByteValue) value).value()); } else if (value instanceof CharValue) { gen.writeString(String.valueOf(((CharValue) value).value())); } else if (value instanceof ShortValue) { gen.writeNumber(((ShortValue) value).value()); } else if (value instanceof IntValue) { gen.writeNumber(((IntValue) value).value()); } else if (value instanceof LongValue) { gen.writeNumber(((LongValue) value).value()); } else if (value instanceof FloatValue) { gen.writeNumber(((FloatValue) value).value()); } else if (value instanceof DoubleValue) { gen.writeNumber(((DoubleValue) value).value()); } } else if (value instanceof ArrayReference) { ArrayReference arr = (ArrayReference) value; gen.writeStartArray(); for (Value item : arr.getValues()) { provider.defaultSerializeValue(item, gen); } gen.writeEndArray(); } else if (value instanceof ObjectReference) { ObjectReference obj = (ObjectReference) value; if (obj.isCollected()) { gen.writeString("[已回收对象]"); return; } gen.writeStartObject(); // 遍历对象所有字段,可自行加规则过滤静态/常量等字段 for (Field field : obj.referenceType().allFields()) { // 示例:过滤静态字段 // if(field.isStatic()) continue; Value fieldValue = obj.getValue(field); gen.writeFieldName(field.name()); provider.defaultSerializeValue(fieldValue, gen); } gen.writeEndObject(); } else if (value instanceof VoidValue) { gen.writeNull(); } else { // 兜底逻辑,避免未知类型导致序列化失败 gen.writeString(value.type().name()); } } }
- 初始化复用
ObjectMapper并注册序列化器,不要在循环中重复创建ObjectMapper
// 全局初始化一次即可 ObjectMapper mapper = new ObjectMapper(); SimpleModule jdiModule = new SimpleModule("JdiValueSerializeModule"); jdiModule.addSerializer(Value.class, new JdiValueSerializer()); // 可选配置:格式化输出JSON mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.registerModule(jdiModule); // 断点事件处理逻辑 StackFrame sf = event.thread().frame(0); for (Value v : sf.getArgumentValues()) { try { System.out.println(mapper.writeValueAsString(v)); } catch (Exception e) { e.printStackTrace(); } }
可选优化
如果有特殊类型需要定制序列化逻辑,只需要新增对应子类型的序列化器注册到模块中即可,不需要修改原有业务代码。
内容的提问来源于stack exchange,提问作者AntoineG
相关产品推荐
相关产品推荐

