ADDITIONAL SYSTEM INFORMATION :
java.specification.version=22
java.vm.vendor=Oracle Corporation
java.vm.specification.version=22
os.name=Windows 10
sun.java.launcher=SUN_STANDARD
java.specification.vendor=Oracle Corporation
java.version.date=2024-03-19
java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
java.runtime.version=22+36-2370
os.version=10.0
java.runtime.name=OpenJDK Runtime Environment
java.vm.name=OpenJDK 64-Bit Server VM
java.version=22
java.vendor=Oracle Corporation
java.vm.version=22+36-2370
A DESCRIPTION OF THE PROBLEM :
I was playing around with the com.sun.net.httpserver package and noticed that when trying to print the contents of the request headers returned from HttpExchange.getRequestHeaders() it was falsely outputting an empty map even though a previous call to .getSize() returned 4.
Upon further investigation, I figured that the following call stack leads to:
`HttpExchangeImpl::getRequestHeaders()`
-> `ExchangeImpl::getRequestHeaders()`
-> `return Headers.of(req.headers());`
`Headers::of` returns a new instance of `UnmodifiableHeaders`.
This class defines a field `map`, which is also defined in the parent class `Headers`. All headers are stored inside the map defined in the `UnmodifiableHeaders` class. The problem is, `UnmodifiableHeaders` does not override `toString`. Therefore, when trying to call `toString` on a `UnmodifiableHeaders` instance, the parent's `toString` method gets called which prints the contents of the `map` variable defined in the parent class. Which will be empty.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Reproduction is very easy.
Step 1: Create an instance of `Headers` and add one or more header entries to it.
Step 2: Create a copy (instance of `UnmodifiableHeaders`) of the instance using the static factory method `Headers::of`.
Step 3: Make a call to `toString` on the created copy and print the result.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Calling `toString` on an instance of `UnmodifiableHeaders` should print the headers contained in the instance.
ACTUAL -
Calling `.toString` on an instance of `UnmodifiableHeaders` will always print `Headers { {} }`
---------- BEGIN SOURCE ----------
import com.sun.net.httpserver.Headers;
public class BugReproduction {
public static void main(String[] args) {
Headers headers = new Headers();
headers.add("K", "V");
Headers copy = Headers.of(headers);
System.out.println("headers: " + headers);
System.out.println("copy: " + copy);
}
}
---------- END SOURCE ----------
FREQUENCY : always
java.specification.version=22
java.vm.vendor=Oracle Corporation
java.vm.specification.version=22
os.name=Windows 10
sun.java.launcher=SUN_STANDARD
java.specification.vendor=Oracle Corporation
java.version.date=2024-03-19
java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
java.runtime.version=22+36-2370
os.version=10.0
java.runtime.name=OpenJDK Runtime Environment
java.vm.name=OpenJDK 64-Bit Server VM
java.version=22
java.vendor=Oracle Corporation
java.vm.version=22+36-2370
A DESCRIPTION OF THE PROBLEM :
I was playing around with the com.sun.net.httpserver package and noticed that when trying to print the contents of the request headers returned from HttpExchange.getRequestHeaders() it was falsely outputting an empty map even though a previous call to .getSize() returned 4.
Upon further investigation, I figured that the following call stack leads to:
`HttpExchangeImpl::getRequestHeaders()`
-> `ExchangeImpl::getRequestHeaders()`
-> `return Headers.of(req.headers());`
`Headers::of` returns a new instance of `UnmodifiableHeaders`.
This class defines a field `map`, which is also defined in the parent class `Headers`. All headers are stored inside the map defined in the `UnmodifiableHeaders` class. The problem is, `UnmodifiableHeaders` does not override `toString`. Therefore, when trying to call `toString` on a `UnmodifiableHeaders` instance, the parent's `toString` method gets called which prints the contents of the `map` variable defined in the parent class. Which will be empty.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Reproduction is very easy.
Step 1: Create an instance of `Headers` and add one or more header entries to it.
Step 2: Create a copy (instance of `UnmodifiableHeaders`) of the instance using the static factory method `Headers::of`.
Step 3: Make a call to `toString` on the created copy and print the result.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Calling `toString` on an instance of `UnmodifiableHeaders` should print the headers contained in the instance.
ACTUAL -
Calling `.toString` on an instance of `UnmodifiableHeaders` will always print `Headers { {} }`
---------- BEGIN SOURCE ----------
import com.sun.net.httpserver.Headers;
public class BugReproduction {
public static void main(String[] args) {
Headers headers = new Headers();
headers.add("K", "V");
Headers copy = Headers.of(headers);
System.out.println("headers: " + headers);
System.out.println("copy: " + copy);
}
}
---------- END SOURCE ----------
FREQUENCY : always
- relates to
-
JDK-8263506 Make sun.net.httpserver.UnmodifiableHeaders unmodifiable
- Resolved