fb-contrib icon indicating copy to clipboard operation
fb-contrib copied to clipboard

PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS false positive

Open efenderbosch opened this issue 6 years ago • 3 comments

return dbMapper.batchLoad(contactsIdsOnly).values().stream().
    flatMap(Collection::stream).
    filter(Contact.class::isInstance).
    map(Contact.class::cast). // PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS here
    collect(toList());

javac 10.0.1 spotbugs 3.1.10 fb-contrib 7.4.3.sb MacOS, doesn't seem to happen in our Linux CI builds

efenderbosch avatar Jan 07 '19 16:01 efenderbosch

mind running javap -v -private YourClass

and dumping the byte code for at least this sequence of statements?

mebigfatguy avatar Jan 08 '19 02:01 mebigfatguy

Same issue in SonarQube Community Edition Version 8.9.7 (build 52159), which implies Findbugs Plugin v4.0.6, which implies fb-contrib v7.4.7 (sb-contrib)

OldIMP avatar Apr 19 '22 18:04 OldIMP

and dumping the byte code for at least this sequence of statements?

Java code

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class TestClass {

	public Set<String> test1(List<Object> list) {
		return list.stream()
                    .filter(String.class::isInstance)
                    .map(String.class::cast)
                    .collect(Collectors.toSet());
	}

	public Set<String> test2(List<Object> list) {
		Class<String> StringClass = String.class;
		return list.stream()
                    .filter(StringClass::isInstance)
                    .map(StringClass::cast)
                    .collect(Collectors.toSet());
	}

}

Dump

$ javap -v -private TestClass.class 
Classfile /home/pbludov/src/tmp/TestClass.class
  Last modified 6 мая 2022 г.; size 2162 bytes
  SHA-256 checksum bd6fdc72267018c66ad0983cacb8a8f45d53fde0a2c6238ea500db7f444b579f
  Compiled from "TestClass.java"
public class TestClass
  minor version: 0
  major version: 62
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #51                         // TestClass
  super_class: #2                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 3, attributes: 3
Constant pool:
    #1 = Methodref          #2.#3         // java/lang/Object."<init>":()V
    #2 = Class              #4            // java/lang/Object
    #3 = NameAndType        #5:#6         // "<init>":()V
    #4 = Utf8               java/lang/Object
    #5 = Utf8               <init>
    #6 = Utf8               ()V
    #7 = InterfaceMethodref #8.#9         // java/util/List.stream:()Ljava/util/stream/Stream;
    #8 = Class              #10           // java/util/List
    #9 = NameAndType        #11:#12       // stream:()Ljava/util/stream/Stream;
   #10 = Utf8               java/util/List
   #11 = Utf8               stream
   #12 = Utf8               ()Ljava/util/stream/Stream;
   #13 = Class              #14           // java/lang/String
   #14 = Utf8               java/lang/String
   #15 = Methodref          #16.#17       // java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
   #16 = Class              #18           // java/util/Objects
   #17 = NameAndType        #19:#20       // requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
   #18 = Utf8               java/util/Objects
   #19 = Utf8               requireNonNull
   #20 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
   #21 = InvokeDynamic      #0:#22        // #0:test:(Ljava/lang/Class;)Ljava/util/function/Predicate;
   #22 = NameAndType        #23:#24       // test:(Ljava/lang/Class;)Ljava/util/function/Predicate;
   #23 = Utf8               test
   #24 = Utf8               (Ljava/lang/Class;)Ljava/util/function/Predicate;
   #25 = InterfaceMethodref #26.#27       // java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
   #26 = Class              #28           // java/util/stream/Stream
   #27 = NameAndType        #29:#30       // filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
   #28 = Utf8               java/util/stream/Stream
   #29 = Utf8               filter
   #30 = Utf8               (Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
   #31 = InvokeDynamic      #1:#32        // #1:apply:(Ljava/lang/Class;)Ljava/util/function/Function;
   #32 = NameAndType        #33:#34       // apply:(Ljava/lang/Class;)Ljava/util/function/Function;
   #33 = Utf8               apply
   #34 = Utf8               (Ljava/lang/Class;)Ljava/util/function/Function;
   #35 = InterfaceMethodref #26.#36       // java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
   #36 = NameAndType        #37:#38       // map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
   #37 = Utf8               map
   #38 = Utf8               (Ljava/util/function/Function;)Ljava/util/stream/Stream;
   #39 = Methodref          #40.#41       // java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
   #40 = Class              #42           // java/util/stream/Collectors
   #41 = NameAndType        #43:#44       // toSet:()Ljava/util/stream/Collector;
   #42 = Utf8               java/util/stream/Collectors
   #43 = Utf8               toSet
   #44 = Utf8               ()Ljava/util/stream/Collector;
   #45 = InterfaceMethodref #26.#46       // java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
   #46 = NameAndType        #47:#48       // collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
   #47 = Utf8               collect
   #48 = Utf8               (Ljava/util/stream/Collector;)Ljava/lang/Object;
   #49 = Class              #50           // java/util/Set
   #50 = Utf8               java/util/Set
   #51 = Class              #52           // TestClass
   #52 = Utf8               TestClass
   #53 = Utf8               Code
   #54 = Utf8               LineNumberTable
   #55 = Utf8               LocalVariableTable
   #56 = Utf8               this
   #57 = Utf8               LTestClass;
   #58 = Utf8               test1
   #59 = Utf8               (Ljava/util/List;)Ljava/util/Set;
   #60 = Utf8               list
   #61 = Utf8               Ljava/util/List;
   #62 = Utf8               LocalVariableTypeTable
   #63 = Utf8               Ljava/util/List<Ljava/lang/Object;>;
   #64 = Utf8               Signature
   #65 = Utf8               (Ljava/util/List<Ljava/lang/Object;>;)Ljava/util/Set<Ljava/lang/String;>;
   #66 = Utf8               test2
   #67 = Utf8               StringClass
   #68 = Utf8               Ljava/lang/Class;
   #69 = Utf8               Ljava/lang/Class<Ljava/lang/String;>;
   #70 = Utf8               SourceFile
   #71 = Utf8               TestClass.java
   #72 = Utf8               BootstrapMethods
   #73 = MethodHandle       6:#74         // REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
   #74 = Methodref          #75.#76       // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
   #75 = Class              #77           // java/lang/invoke/LambdaMetafactory
   #76 = NameAndType        #78:#79       // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
   #77 = Utf8               java/lang/invoke/LambdaMetafactory
   #78 = Utf8               metafactory
   #79 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
   #80 = MethodType         #81           //  (Ljava/lang/Object;)Z
   #81 = Utf8               (Ljava/lang/Object;)Z
   #82 = MethodHandle       5:#83         // REF_invokeVirtual java/lang/Class.isInstance:(Ljava/lang/Object;)Z
   #83 = Methodref          #84.#85       // java/lang/Class.isInstance:(Ljava/lang/Object;)Z
   #84 = Class              #86           // java/lang/Class
   #85 = NameAndType        #87:#81       // isInstance:(Ljava/lang/Object;)Z
   #86 = Utf8               java/lang/Class
   #87 = Utf8               isInstance
   #88 = MethodType         #20           //  (Ljava/lang/Object;)Ljava/lang/Object;
   #89 = MethodHandle       5:#90         // REF_invokeVirtual java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
   #90 = Methodref          #84.#91       // java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
   #91 = NameAndType        #92:#20       // cast:(Ljava/lang/Object;)Ljava/lang/Object;
   #92 = Utf8               cast
   #93 = MethodType         #94           //  (Ljava/lang/Object;)Ljava/lang/String;
   #94 = Utf8               (Ljava/lang/Object;)Ljava/lang/String;
   #95 = Utf8               InnerClasses
   #96 = Class              #97           // java/lang/invoke/MethodHandles$Lookup
   #97 = Utf8               java/lang/invoke/MethodHandles$Lookup
   #98 = Class              #99           // java/lang/invoke/MethodHandles
   #99 = Utf8               java/lang/invoke/MethodHandles
  #100 = Utf8               Lookup
{
  public TestClass();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LTestClass;

  public java.util.Set<java.lang.String> test1(java.util.List<java.lang.Object>);
    descriptor: (Ljava/util/List;)Ljava/util/Set;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=2, args_size=2
         0: aload_1
         1: invokeinterface #7,  1            // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
         6: ldc           #13                 // class java/lang/String
         8: dup
         9: invokestatic  #15                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
        12: pop
        13: invokedynamic #21,  0             // InvokeDynamic #0:test:(Ljava/lang/Class;)Ljava/util/function/Predicate;
        18: invokeinterface #25,  2           // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
        23: ldc           #13                 // class java/lang/String
        25: dup
        26: invokestatic  #15                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
        29: pop
        30: invokedynamic #31,  0             // InvokeDynamic #1:apply:(Ljava/lang/Class;)Ljava/util/function/Function;
        35: invokeinterface #35,  2           // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
        40: invokestatic  #39                 // Method java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
        43: invokeinterface #45,  2           // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
        48: checkcast     #49                 // class java/util/Set
        51: areturn
      LineNumberTable:
        line 8: 0
        line 9: 9
        line 10: 26
        line 11: 40
        line 8: 51
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      52     0  this   LTestClass;
            0      52     1  list   Ljava/util/List;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      52     1  list   Ljava/util/List<Ljava/lang/Object;>;
    Signature: #65                          // (Ljava/util/List<Ljava/lang/Object;>;)Ljava/util/Set<Ljava/lang/String;>;

  public java.util.Set<java.lang.String> test2(java.util.List<java.lang.Object>);
    descriptor: (Ljava/util/List;)Ljava/util/Set;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=2
         0: ldc           #13                 // class java/lang/String
         2: astore_2
         3: aload_1
         4: invokeinterface #7,  1            // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
         9: aload_2
        10: dup
        11: invokestatic  #15                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
        14: pop
        15: invokedynamic #21,  0             // InvokeDynamic #0:test:(Ljava/lang/Class;)Ljava/util/function/Predicate;
        20: invokeinterface #25,  2           // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
        25: aload_2
        26: dup
        27: invokestatic  #15                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
        30: pop
        31: invokedynamic #31,  0             // InvokeDynamic #1:apply:(Ljava/lang/Class;)Ljava/util/function/Function;
        36: invokeinterface #35,  2           // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
        41: invokestatic  #39                 // Method java/util/stream/Collectors.toSet:()Ljava/util/stream/Collector;
        44: invokeinterface #45,  2           // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
        49: checkcast     #49                 // class java/util/Set
        52: areturn
      LineNumberTable:
        line 16: 0
        line 17: 3
        line 18: 11
        line 19: 27
        line 20: 41
        line 17: 52
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      53     0  this   LTestClass;
            0      53     1  list   Ljava/util/List;
            3      50     2 StringClass   Ljava/lang/Class;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            0      53     1  list   Ljava/util/List<Ljava/lang/Object;>;
            3      50     2 StringClass   Ljava/lang/Class<Ljava/lang/String;>;
    Signature: #65                          // (Ljava/util/List<Ljava/lang/Object;>;)Ljava/util/Set<Ljava/lang/String;>;
}
SourceFile: "TestClass.java"
BootstrapMethods:
  0: #73 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #80 (Ljava/lang/Object;)Z
      #82 REF_invokeVirtual java/lang/Class.isInstance:(Ljava/lang/Object;)Z
      #80 (Ljava/lang/Object;)Z
  1: #73 REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #88 (Ljava/lang/Object;)Ljava/lang/Object;
      #89 REF_invokeVirtual java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
      #93 (Ljava/lang/Object;)Ljava/lang/String;
InnerClasses:
  public static final #100= #96 of #98;   // Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles

pbludov avatar May 05 '22 21:05 pbludov