36. 11 Can you find the Bug? public String sendMessage (User user, String body, Date time) { return sendMessage(user, body, null); } public String sendMessage (User user, String body, Date time, List attachments) { String xml = buildXML (body, attachments); String response = sendMessage(user, xml); return response; }
37. 12 Infinite recursive loopHigh priority correctness public String sendMessage (User user, String body, Date time) { return sendMessage(user, body, null); } public String sendMessage (User user, String body, Date time, List attachments) { String xml = buildXML (body, attachments); String response = sendMessage(user, xml); return response; }
38. 13 Can you find the Bug? public String foundType() { return this.foundType(); }
39. 14 Infinite recursive loop public String foundType() { return this.foundType(); } // should be public String foundType() { return this.foundType; } • Findbugs found 5 infinite recursive loops in JDK1.6.0-b13 • Including this one written by Joshua Bloch • Smart people make dumb mistakes • 27 across all versions of JDK, 31 in Google’s Java code • Embrace and fix your dumb mistakes
40. 15 Can you find the Bug? if (name != null || name.length > 0)
41. 16 Can you find the Bug? if (name != null || name.length > 0) if (name != null &&name.length > 0) Found in //com.sun.corba.se.impl.naming.cosnaming.NamingContextImpl
42. 17 Can you find the Bug? if (part == null | part.equals(""))
43. 18 Can you find the Bug? if (part == null | part.equals("")) if (part == null ||part.equals("")) Found in //com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser
44. 19 Null Pointer Bugs found in com.sun…. if (name != null || name.length > 0) if (part == null | part.equals("")) // sun.awt.x11.ScrollPanePeer if (g != null) paintScrollBars(g,colors); g.dispose();
47. 22 Problem? public final WritableRaster filter( Raster src, WritableRasterdst) { intdstLength = dst.getNumBands(); // Create a new destination Raster,if needed if (dst == null) dst = createCompatibleDestRaster(src);
48. 23 Redundant Check for Null Is it a bug or a redundant check? public final WritableRaster filter( Raster src, WritableRasterdst) { intdstLength = dst.getNumBands(); // Create a new destination Raster,if needed if (dst == null) dst = createCompatibleDestRaster(src); can't be null because there would have been a NPE if it were null
49.
50.
51. 26 Bad Method Call // com.sun.xml.internal.txw2.output.XMLWriter try { ... } catch (IOException e) { new SAXException("Server side Exception:" + e); } Exception created and dropped rather than thrown try { ... } catch (IOException e) { throw new SAXException("Server side Exception:" + e); }
53. 28 Method Ignores return valueCorrectness public static String getNameById(String userId) { String str = userId; ... str= str.replace(' ', '_'); return str; } Methods whose return value shouldn't be ignored • Strings are immutable, so functions like trim() and replace() return new String
54. 29 What does it Print? Integer one = 1; Long addressTypeCode = 1L; if (addressTypeCode.equals(one)) { System.out.println("equals"); } else { System.out.println("not equals"); }
55. 30 Comparing Different Types Integer one = 1; Long addressTypeCode = 1L; if (addressTypeCode.equals(one)) { System.out.println("equals"); } else { System.out.println("not equals"); } According to the contract of equals(), objects of different classes should always compare as unequal;
65. 32 Best Way to use Findbugs •Want to find an effective/profitable way to use static analysis to improve software quality Mistakes That Don’t Mistakes That Matter Testing Deployment Static Analysis
74. 36 Can you find the (Google) bug ? // calculate DR amount by aggregating CR amounts BigDecimaldrAmount = new BigDecimal(0); for (JournalEntry je: journalEntries) drAmount.add(je.getCrAmount()); // persist to db getTrxnService().saveJournalEntry(id, drAmount, // aggregated amount true, // Debit "USD", "Revenue");
75. 37 A Google Bug //Ignored return value of BigDecimal.add for (JournalEntry je: journalEntries) drAmount.add(je.getCrAmount()); // should be drAmount= drAmount.add(je.getCrAmount()); Fixed within 30 minutes of being reported
76. 38 Bug ? int value2; Public boolean equals(Integer value1){ return value1== intValue() ; } public Integer intValue() { return value2; }
77. 39 Using reference equality rather than .equals int value2; Public boolean equals(Integer value1){ return value1.equals(intValue() ); } public Integer intValue() { return value2; } For boxed primitives, == and != are computed using pointer equality, but <, <=, >, >= are computed by comparing unboxed primitive values This can bite you on other classes (e.g., String) • but boxed primitives is where people get bit
78. 40 Bug ? ConcurrentMap<Long,XmitTimeStat> xmit_time_stats = ...; ..... stat = new XmitTimeStat(); xmit_time_stats.putIfAbsent(key, stat); stat.xmit_rsps_sent.addAndGet(sent);
79. 41 misusing putIfAbsentorg.jgroups.protocols.pbcast.NAKACK ConcurrentMap<Long,XmitTimeStat> xmit_time_stats = ...; ..... stat = new XmitTimeStat(); XmitTimeStat stat2 = xmit_time_stats.putIfAbsent(key, stat); if (stat2 != null) stat = stat2; stat.xmit_rsps_sent.addAndGet(sent); ConcurrentMap provides putIfAbsent • atomically add key -> value mapping • but only if the key isnʼt already in the map • if non-null value is returned, put failed and value returned is the value already associated with the key