Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[java] Implement rule NonSerializableClass #4196

Merged
merged 7 commits into from Nov 25, 2022

Conversation

adangel
Copy link
Member

@adangel adangel commented Nov 4, 2022

Related issues

Note: We still need a replacement for BeanMembersShouldSerialize, see #4177

Not sure, whether we should deprecate BeanMembersShouldSerialize without replacements and just add NonSerializableClass as a new rule. The diff shows, that the implementation is completely different...

Ready?

  • Added unit tests for fixed bug/feature
  • Passing all unit tests
  • Complete build ./mvnw clean verify passes (checked automatically by github actions)
  • Added (in-code) documentation (if needed)

@adangel adangel added this to the 6.52.0 milestone Nov 4, 2022
@pmd-test
Copy link

pmd-test commented Nov 4, 2022

1 Message
📖 Compared to master:
This changeset changes 0 violations,
introduces 34 new violations, 0 new errors and 0 new configuration errors,
removes 19809 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 0 violations,
introduces 34 new violations, 2 new errors and 0 new configuration errors,
removes 19809 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 0 violations,
introduces 44 new violations, 0 new errors and 0 new configuration errors,
removes 19809 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 0 violations,
introduces 232 new violations, 0 new errors and 0 new configuration errors,
removes 19796 violations, 0 errors and 0 configuration errors.
Full report
Compared to master:
This changeset changes 0 violations,
introduces 75 new violations, 544 new errors and 0 new configuration errors,
removes 19796 violations, 0 errors and 0 configuration errors.
Full report

Generated by 🚫 Danger

Use rulechain, consider inner classes/enums
Use fully qualified name for reporting
@adangel
Copy link
Member Author

adangel commented Nov 10, 2022

Does this violation make sense? Wdyt?

https://github.com/spring-projects/spring-framework/tree/v5.3.13/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java#L90

AdvisedSupport is serializable. It has a field interfaces of type java.util.List. The List is a interface and it is itself not serializable. But the implementation used at runtime (e.g. at this specific line it is ArrayList) is serializable. So this is actually not a real problem, but just looking statically at the type of the field, we don't know, whether the value will be serializable or not at runtime.
We could make it optional to check this (e.g. by introducing a property checkInterfaces).

Regarding the other open point (whether to rename or deprecate the old rule BeanMembersShouldSerialize): The new rule creates significantly less violations, as it only considers serializable classes (only 232 violations vs. 19796). When we rename the rule, this helps anyone who has enabled BeanMembersShouldSerialize now, because most of the false-positive noise will be gone without changing the ruleset. However, maybe nobody has this rule enabled anyway atm? Then some change in the ruleset will be necessary either way: adding NonSerializableClass or removing the exclude for BeanMembersShouldSerialize. So I guess, it doesn't really matter.

@oowekyala
Copy link
Member

oowekyala commented Nov 12, 2022

So this is actually not a real problem, but just looking statically at the type of the field, we don't know, whether the value will be serializable or not at runtime.

This problem is apparent in other violations, where no interface is involved. For instance here: https://github.com/openjdk/jdk/blob/jdk-11%2B28/src/java.base/share/classes/java/util/AbstractMap.java#L609

While the rule is technically right, it would be very restrictive to require the type parameters to be serializable when the serialization feature might never be used...

I think the rule is "more probably" right (true positive) when the field type is a non-abstract class (and not Object). When it's an interface or abstract class or a type parameter, maybe we should skip it conservatively (with a property). If we could, it would be nice to allow reporting these with a lower priority.

By default, ignore abstract types like abstract classes, interfaces, generic types and java.lang.Object.
@adangel
Copy link
Member Author

adangel commented Nov 18, 2022

I've added the property "checkAbstractTypes" now.

There is one more special case: the private static final field serialPersistentFields - if this is not defined, then all non-static and non-transient fields must be serializable. Otherwise, only the fields that are defined here, need to be serializable.

That means, that all violations in java.io.ObjectStreamClass (e.g. https://github.com/openjdk/jdk/blob/jdk-11%2B28/src/java.base/share/classes/java/io/ObjectStreamClass.java#L166) are false-positives, because this class defines actually no serializable fields: https://github.com/openjdk/jdk/blob/jdk-11%2B28/src/java.base/share/classes/java/io/ObjectStreamClass.java#L88-L89

This behavior is described here: https://docs.oracle.com/en/java/javase/19/docs/specs/serialization/serial-arch.html#defining-serializable-fields-for-a-class

@adangel adangel merged commit 78ac4bc into pmd:master Nov 25, 2022
adangel added a commit to adangel/pmd that referenced this pull request Nov 25, 2022
@adangel adangel deleted the issue-4176-NonSerializableClass branch November 25, 2022 18:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants