The current implementation of Double.toString(double) internally allocates a fixed-size byte[] to temporarily hold the result of the conversion. It fills it with the outcome of the conversion, and generates 9-17 digits in the significand, even if there are trailing zeros. The reason is that the left-to-right digits generation makes it hard to foresee trailing zeros during the generation. Finally, it passes the byte[] to a String constructor which, in turn, allocates another array and (partially) copies the content from the fixed-size byte[].
There are two problems with this approach: (1) the extra allocation of the fixed-size byte[] to hold the temporary result; and (2) the useless generation of trailing zeros which are later removed.
To address both of them in one go, the proposed enhancement pre-computes the correct size for the byte[], and avoids generating useless trailing zeros. Moreover, it makes use of an internal method that accepts a byte[] as the final carrier for the String characters (when the runtime uses compact strings). The method assumes that the array is correctly sized and that the caller relinquishes ownership of the array. This avoids the additional allocation of the extra fixed-size byte[].
Besides avoiding one allocation per conversion, on the author's platform the modified implementation is never slower and is faster for short outputs.
Similar results hold for Float.toString(float) as well. (All 2^32 float outputs have been exhaustively and extensively tested.)