unitsofmeasurement / indriya

JSR 385 - Reference Implementation
Other
119 stars 42 forks source link

NPE on hashCode() of de-serialized ProductUnits #309

Closed john2home closed 4 years ago

john2home commented 4 years ago

when serializing Unit with you get a NPE.

using tech.units:indriya:2.0.4 with openjdk 8

java.lang.NullPointerException: null
    at tech.units.indriya.unit.ProductUnit.hashCode(ProductUnit.java:294) ~[indriya-2.0.4.jar:2.0.4]
    at java.util.Objects.hashCode(Objects.java:98) ~[?:1.8.0_265]
    at tech.units.indriya.unit.UnitDimension.hashCode(UnitDimension.java:307) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.unit.BaseUnit.hashCode(BaseUnit.java:144) ~[indriya-2.0.4.jar:2.0.4]
    at java.util.Objects.hashCode(Objects.java:98) ~[?:1.8.0_265]
    at tech.units.indriya.unit.UnitDimension.hashCode(UnitDimension.java:307) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.unit.BaseUnit.hashCode(BaseUnit.java:144) ~[indriya-2.0.4.jar:2.0.4]
    at java.util.Arrays.hashCode(Arrays.java:4146) ~[?:1.8.0_265]
    at java.util.Objects.hash(Objects.java:128) ~[?:1.8.0_265]
    at tech.units.indriya.unit.TransformedUnit.hashCode(TransformedUnit.java:220) ~[indriya-2.0.4.jar:2.0.4]
    at java.util.Arrays.hashCode(Arrays.java:4146) ~[?:1.8.0_265]
    at java.util.Objects.hash(Objects.java:128) ~[?:1.8.0_265]
    at tech.units.indriya.unit.TransformedUnit.hashCode(TransformedUnit.java:220) ~[indriya-2.0.4.jar:2.0.4]
    at java.util.HashMap.hash(HashMap.java:339) ~[?:1.8.0_265]
    at java.util.HashMap.get(HashMap.java:557) ~[?:1.8.0_265]
    at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.nameFor(SimpleUnitFormat.java:373) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.format.SimpleUnitFormat$DefaultFormat.format(SimpleUnitFormat.java:732) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.format.AbstractUnitFormat.format(AbstractUnitFormat.java:148) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.format.AbstractUnitFormat.format(AbstractUnitFormat.java:94) ~[indriya-2.0.4.jar:2.0.4]
    at tech.units.indriya.AbstractUnit.toString(AbstractUnit.java:226) ~[indriya-2.0.4.jar:2.0.4]

use this junit5 code to test:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.measure.Quantity;
import javax.measure.Unit;
import javax.measure.quantity.Length;

import org.assertj.core.api.Assertions;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;

public class TypedValue_serializationTest
{
    @Test
    public void testInvalidUnit() throws Exception
    {
        final Unit<?> serialization = serialization(Units.METRE);
        /*
         * if the test failed the serialization is fixed
         */
        Assertions.catchThrowableOfType(() -> serialization.toString(), NullPointerException.class);
    }
    private static <T> T serialization(final T value) throws Exception
    {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream())
        {
            try (ObjectOutputStream oos = new ObjectOutputStream(out))
            {
                oos.writeObject(value);
                oos.flush();
            }
            try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()))
            {
                try (ObjectInputStream ois = new ObjectInputStream(in))
                {
                    return (T) ois.readObject();
                }
            }
        }
    }
}
andi-huber commented 4 years ago

Fixed in 'master' branch.

Thanks for reporting!