How to handle a Findbugs “Non-transient non-serializable instance field in serializable class”?

前端 未结 8 1378
没有蜡笔的小新
没有蜡笔的小新 2020-12-24 02:03

Consider the class below. If I run Findbugs against it it will give me an error (\"Non-transient non-serializable instance field in serializable class\") on line 5 but not o

相关标签:
8条回答
  • 2020-12-24 02:12

    You can get rid of those Critical warning messages by adding the following methods to your class:

    private void writeObject(ObjectOutputStream stream)
            throws IOException {
        stream.defaultWriteObject();
    }
    
    private void readObject(ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
    }
    
    0 讨论(0)
  • 2020-12-24 02:14

    However it is best practice to code against interfaces instead of concrete implementations.

    I submit that no, in this case it is not. Findbugs quite correctly tells you that you risk running into a NotSerializableException as soon as you have a non-serializable Set implementation in that field. This is something you should deal with. How, that depends on the design of your classes.

    • If those collections are initialized within the class and never set from outside, then I see absolutely nothing wrong with declaring the concrete type for the field, since fields are implementation details anyway. Do use the interface type in the public interface.
    • If the collection are passed into the class via a public interface, you have to ensure that they are in fact Serializable. To do that, create an interface SerializableSet extends Set, Serializable and use it for your field. Then, either:
      • Use SerializableSet in the public interface and provide implementation classes that implement it.
      • Check collections passed to the class via instanceof Serializable and if they're not, copy them into something that is.
    0 讨论(0)
  • 2020-12-24 02:21

    I know this is an old question that's already answered but just so others know is that you can set the Set<Integer> field as transient if you have no interest in serializing that particular field which will fix your FindBugs error.

    public class TestClass implements Serializable {
    
        private static final long serialVersionUID = 1905162041950251407L;
        private transient Set<Integer> mySet;
    
    }
    

    I prefer this method instead of forcing users of your API to cast to your concrete type, unless it's just internal, then Michael Borgwardt's answer makes more sense.

    0 讨论(0)
  • 2020-12-24 02:21

    You could use a capture helper to ensure that a passed in Set supports two interfaces:

    private static class SerializableTestClass<T extends Set<?> & Serializable> implements Serializable
    {
        private static final long serialVersionUID = 1L;
        private final T serializableSet;
    
        private SerializableTestClass(T serializableSet)
        {
            this.serializableSet = serializableSet;
        }
    }
    
    public static class PublicApiTestClass
    {
        public static <T extends Set<?> & Serializable> Serializable forSerializableSet(T set)
        {
            return new SerializableTestClass<T>(set);
        }
    }
    

    In this way you can have a public API that enforces Serializable without checking/requiring specific implementation details.

    0 讨论(0)
  • 2020-12-24 02:28

    I had HIGH Warning for a protected field in a serializable class. Add transient for the field resolved my problem:

     protected transient Object objectName;
    
    0 讨论(0)
  • 2020-12-24 02:28

    In case you are using findbugs-maven-plugin and have to persist a field, and that field is a class not implementing Serializable interface, for example, a field that has a class defined in a 3rd party. You can manually configure exclude file for findbugs,

    If this is the only case, add it in an exclude file: pom:

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>findbugs-maven-plugin</artifactId>
        <version>3.0.3</version>
        <configuration>
              <xmlOutput>true</xmlOutput>
              <xmlOutputDirectory>target/findbugs/</xmlOutputDirectory>
              <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
              <includeFilterFile>findbugs-include.xml</includeFilterFile>
              <failOnError>true</failOnError>
        </configuration>
    ...
    

    exclude.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <FindBugsFilter>
        <Match>
            <Class name="com.xxx.Foo" /> 
            <Field type="org.springframework.statemachine.StateMachineContext"/>
        </Match>
    

    Entity:

    @Entity
    public class Foo extends Boo {
        StateMachineContext<A, B> stateMachineContext;
    

    Although I don't understand why adding <Bug category="SE_BAD_FIELD"/> would not work. Besides, I don't agree with the solution of adding annotation on the field like @edu.umd.cs.findbugs.annotations.SuppressWarnings(justification="No bug", values="SE_BAD_FIELD"), because building tools better not penetrate business code.maven plugin usage & findbugs filters both include and exclude

    About SE_BAD_FIELD: Non-transient non-serializable instance field in serializable class, I think it should not check on entities. Because, javax.persistence.AttributeConverter offers methods to serialize a field out side (implements Serializable is an inside method to serialize).

    0 讨论(0)
提交回复
热议问题