com.alibaba.fastjson2.introspect.PropertyAccessorFactoryLambda#getByte的getInt(method) 这个调用被写在了 lambda 的方法体内部。而 getInt(method) 本身就是"会 spin 一个新 lambda"的操作(它内部调 LambdaMetafactory.metafactory 造 int 取值器)。
ThreadLocalRandom r = ThreadLocalRandom.current();
ComplexPoJo2.Status[] statuses = ComplexPoJo2.Status.values();
ComplexPoJo2 resp = new ComplexPoJo2();
// 基本类型
resp.setId(r.nextInt(1, 100000));
resp.setTimestamp(System.currentTimeMillis() - r.nextLong(0, 86400_000L));
resp.setScore(r.nextDouble(0.0, 100.0));
resp.setActive(r.nextBoolean());
resp.setLevel((short) r.nextInt(1, 10));
resp.setFlag((byte) r.nextInt(0, 128));
// 字符串
resp.setName("user-" + getRandomStringFast(8));
resp.setDescription(getRandomStringFast(length));
// 日期
resp.setCreateTime(new Date(System.currentTimeMillis() - r.nextLong(0, 30L * 86400_000)));
resp.setUpdateTime(beanParent.getCreateTime() != null ? beanParent.getCreateTime() : new Date());
// BigDecimal
resp.setAmount(BigDecimal.valueOf(r.nextDouble(1.0, 9999.99)).setScale(2, BigDecimal.ROUND_HALF_UP));
// 枚举
resp.setStatus(statuses[r.nextInt(statuses.length)]);
// 数组
byte[] bin = new byte[r.nextInt(16, 64)];
r.nextBytes(bin);
resp.setBinaryData(bin);
int[] intArr = new int[r.nextInt(4, 12)];
for (int i = 0; i < intArr.length; i++) intArr[i] = r.nextInt(0, 1000);
resp.setIntArray(intArr);
// List<String> tags
int tagCount = r.nextInt(2, 6);
List<String> tags = new ArrayList<>(tagCount);
for (int i = 0; i < tagCount; i++) tags.add("tag-" + getRandomStringFast(4));
resp.setTags(tags);
// List<Integer> scores
int scoreCount = r.nextInt(3, 8);
List<Integer> scores = new ArrayList<>(scoreCount);
for (int i = 0; i < scoreCount; i++) scores.add(r.nextInt(0, 100));
resp.setScores(scores);
// Set<String> categories
int catCount = r.nextInt(2, 5);
Set<String> categories = new HashSet<>(catCount);
for (int i = 0; i < catCount; i++) categories.add("cat-" + getRandomStringFast(3));
resp.setCategories(categories);
// Map<String, String> attributes
int attrCount = r.nextInt(2, 5);
Map<String, String> attrs = new HashMap<>(attrCount);
for (int i = 0; i < attrCount; i++) attrs.put("attr-" + i, getRandomStringFast(8));
resp.setAttributes(attrs);
// Map<String, Integer> counters
int counterCount = r.nextInt(2, 5);
Map<String, Integer> counters = new HashMap<>(counterCount);
for (int i = 0; i < counterCount; i++) counters.put("counter-" + i, r.nextInt(0, 10000));
resp.setCounters(counters);
// Map<String, MetaEntry>
int metaCount = r.nextInt(2, 4);
Map<String, ComplexPoJo2.MetaEntry> metaMap = new HashMap<>(metaCount);
for (int i = 0; i < metaCount; i++) {
ComplexPoJo2.MetaEntry entry = new ComplexPoJo2.MetaEntry();
entry.setKey("mk-" + i);
entry.setValue(getRandomStringFast(12));
entry.setCount(r.nextInt(1, 100));
Map<String, String> extra = new HashMap<>(2);
extra.put("ex1", getRandomStringFast(6));
extra.put("ex2", getRandomStringFast(6));
entry.setExtra(extra);
metaMap.put("meta-" + i, entry);
}
resp.setMetaMap(metaMap);
// 嵌套对象 AddressInfo
resp.setAddress(randomAddress(r));
// List<OrderItem>
int itemCount = r.nextInt(2, 5);
List<ComplexPoJo2.OrderItem> items = new ArrayList<>(itemCount);
for (int i = 0; i < itemCount; i++) items.add(randomOrderItem(r));
resp.setItems(items);
// Map<String, List<OrderItem>>
int groupCount = r.nextInt(2, 4);
Map<String, List<ComplexPoJo2.OrderItem>> grouped = new HashMap<>(groupCount);
for (int i = 0; i < groupCount; i++) {
int gItemCount = r.nextInt(1, 4);
List<ComplexPoJo2.OrderItem> gItems = new ArrayList<>(gItemCount);
for (int j = 0; j < gItemCount; j++) gItems.add(randomOrderItem(r));
grouped.put("group-" + i, gItems);
}
resp.setGroupedItems(grouped);
return resp;
}
private ComplexPoJo2.AddressInfo randomAddress(ThreadLocalRandom r) {
String[] cities = {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Hangzhou", "Chengdu", "Wuhan"};
ComplexPoJo2.AddressInfo addr = new ComplexPoJo2.AddressInfo();
addr.setCountry("China");
addr.setProvince("Province-" + getRandomStringFast(4));
addr.setCity(cities[r.nextInt(cities.length)]);
addr.setStreet("Street-" + r.nextInt(1, 999));
addr.setZipCode(String.format("%06d", r.nextInt(100000, 999999)));
addr.setLatitude(r.nextDouble(18.0, 53.0));
addr.setLongitude(r.nextDouble(73.0, 135.0));
return addr;
}
private ComplexPoJo2.OrderItem randomOrderItem(ThreadLocalRandom r) {
ComplexPoJo2.OrderItem item = new ComplexPoJo2.OrderItem();
item.setItemId("item-" + getRandomStringFast(6));
item.setItemName("Product-" + getRandomStringFast(8));
item.setQuantity(r.nextInt(1, 50));
double unitPrice = r.nextDouble(1.0, 999.99);
item.setUnitPrice(unitPrice);
item.setTotalPrice(BigDecimal.valueOf(unitPrice * item.getQuantity()).setScale(2, BigDecimal.ROUND_HALF_UP));
Map<String, String> props = new HashMap<>(3);
props.put("color", getRandomStringFast(5));
props.put("size", getRandomStringFast(3));
props.put("brand", getRandomStringFast(6));
item.setProperties(props);
item.setDeliveryAddress(randomAddress(r));
return item;
}
public static String getRandomStringFast(int length){
final String pool="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
ThreadLocalRandom random=ThreadLocalRandom.current();
char[] buf=new char[length];
for(int i=0;i<length;i++){
buf[i]=pool.charAt(random.nextInt(62));
}
return new String(buf);
}
问题描述
com.alibaba.fastjson2.introspect.PropertyAccessorFactoryLambda#getByte的getInt(method) 这个调用被写在了 lambda 的方法体内部。而 getInt(method) 本身就是"会 spin 一个新 lambda"的操作(它内部调 LambdaMetafactory.metafactory 造 int 取值器)。
导致序列化一百万次 flag → getInt 被调 100 万次 → spin 100 万次 → $$Lambda$ 编号飙到 150 万
环境信息
重现步骤
不断调用 ComplexPoJo2 sample = getIPBeanParentPOJO(new ComplexPoJo(), strlength);
logger.info("bigInfo payload: {}", LogUtils.dump(sample));进行日志打印,
其中getIPBeanParentPOJO为
@OverRide
public ComplexPoJo2 getIPBeanParentPOJO(ComplexPoJo beanParent,int length) throws InterruptedException {
期待的正确结果
压测后,性能不差于fastjson1.x
fastjson1和fastjson2火焰图
218363_20260710182318667.html
218368_20260710185516618.html