[Bug] JavaBeanSerializeUtil.serialize() throws IllegalArgumentException on a Map containing a null key
- Dominant language
- Java
- Stars
- 41.6k
- Forks
- 26.4k
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 4
Description
### Pre-check
- [x] I am sure that all the content I provide is in English.
### Search before asking
- [x] I had searched in the [issues](https://github.com/apache/dubbo/issues?q=is%3Aissue) and found no similar issues.
### Apache Dubbo Component
Java SDK (apache/dubbo)
### Dubbo Version
dubbo 3.2.20 (tag dubbo-3.2.20)
### Steps to reproduce this issue
JavaBeanSerializeUtil.serialize() fails on a java.util.HashMap that contains a null key. HashMap permits exactly one null key, so this is a legal argument, and the serializer's own code has an explicit branch for it — but the value that branch produces is then rejected by a null check further down the same call chain.
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
import java.util.HashMap;
import java.util.Map;
public class NullKeyRepro {
public static void main(String[] args) {
Map ok = new HashMap<>();
ok.put("k", "v");
System.out.println("without null key: " + (JavaBeanSerializeUtil.serialize(ok) != null));
Map withNullKey = new HashMap<>();
withNullKey.put(null, "value1"); // HashMap permits one null key
JavaBeanSerializeUtil.serialize(withNullKey); // throws
}
}
### What you expected to happen
The map is serialised, with the null key represented as a null descriptor — which is what the code appears to intend.
### Anything else
### Actual
```
without null key: true
Exception in thread "main" java.lang.IllegalArgumentException: Property name is null
```
### Root cause
`dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java`, lines 162–166:
```java
map.forEach((key, value) -> {
Object keyDescriptor = key == null ? null : createDescriptorIfAbsent(key, accessor, cache);
Object valueDescriptor = value == null ? null : createDescriptorIfAbsent(value, accessor, cache);
descriptor.setProperty(keyDescriptor, valueDescriptor);
});
```
Line 163 deliberately produces `null` for a null key. Line 165 passes it to
`JavaBeanDescriptor.setProperty`, whose first statement (`JavaBeanDescriptor.java`,
lines 118–120) is:
```java
public Object setProperty(Object propertyName, Object propertyValue) {
notNull(propertyName, "Property name is null");
return properties.put(propertyName, propertyValue);
}
```
So the null-producing branch and the null-rejecting guard sit in the same call
chain. Either the ternary on line 163 is dead for keys, or the guard is too strict
for this call site.
### Notes
Not introduced by 3.2.20 — the code path is long-standing. The nearest existing
issue I found, #12248, is a different trigger (a null *parameter* causing an NPE
in generic-call bean mode).
### Do you have a (mini) reproduction demo?
- [ ] Yes, I have a minimal reproduction demo to help resolve this issue more effectively!
### Are you willing to submit a pull request to fix on your own?
- [ ] Yes I am willing to submit a pull request on my own!
### Code of Conduct
- [x] I agree to follow this project's [Code of Conduct](https://www.apache.org/foundation/policies/conduct)
Contributor guide
Research direction
Start with the null-key reproduction and read JavaBeanSerializeUtil.java around lines 162–166, then follow the call into JavaBeanDescriptor.java around lines 118–120. Determine how the existing null-key branch should interact with the property-name check; done means a HashMap containing one null key serializes without IllegalArgumentException while existing non-null-key behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100