最近很多小伙伴都在问findbugs和数据库密码安全性问题和数据库中的访问密钥和安全锁这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展2.findbugs总结、Debian11.2
最近很多小伙伴都在问findbugs和数据库密码安全性问题和数据库中的访问密钥和安全锁这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展2.findbugs 总结、Debian 11.2 发布,修复 Bug 及安全性问题、findbugs、FindBugs 2.0.1 RC3 发布等相关知识,下面开始了哦!
本文目录一览:- findbugs和数据库密码安全性问题(数据库中的访问密钥和安全锁)
- 2.findbugs 总结
- Debian 11.2 发布,修复 Bug 及安全性问题
- findbugs
- FindBugs 2.0.1 RC3 发布
findbugs和数据库密码安全性问题(数据库中的访问密钥和安全锁)
我正在使用以下代码初始化数据库连接:
public Connection getConnection() { try { if (null == connection) { String driverName = "com.mysql.jdbc.Driver"; // MySQL MM JDBC driver Class.forName(driverName); // Create a connection to the database String serverName = "localhost"; String database = "database"; String url = "jdbc:mysql://" + serverName + "/" + mydatabase; // a JDBC url String username = "username"; String password = "password"; connection = DriverManager.getConnection(url, username, password); } return connection; } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); } catch (SQLException sqle) { sqle.printStackTrace(); } throw new NullPointerException("Cannot establish database connection..."); }
而且我知道这样做是不好的做法,而且我还FindBugs
违反了代码,并遇到了如下安全问题: This code creates a databaseconnect using a hardcoded, constant password. Anyone with access to either thesource code or the compiled code can easily learn the password.
在没有此安全漏洞的情况下初始化数据库连接的最佳方法是什么?
答案1
小编典典绝大多数Web应用程序都使用硬编码的用户名/密码进行SQL连接。通常不赞成将生产凭证检查到源代码控制中,或者赋予实习生删除生产数据库的能力。生产凭证应受到保护,只有特权员工才能访问它们。
Web应用程序通常会泄漏其配置文件。例如,如果.xml文件存储在webroot中,则可以远程访问它:http://localhost/configs/db_config.xml
。
通常的做法是禁止访问数据库(对于mysql,阻止tcp端口3306)。实际上,这是PCI-DSS的要求。即使要获取用户名和密码,也将毫无用处。
2.findbugs 总结
一 Bad practice (坏实现)
1.Confusing method name
a.Class names shouldn''t shadow simple name of implemented interface
This class/interface has a simple name that is identical to that of an implemented/extended interface, except that the interface is in a different package (e.g., alpha.Foo extends beta.Foo). This can be exceptionally confusing, create lots of situations in which you have to look at import statements to resolve references and creates many opportunities to accidentally define methods that do not override methods in their superclasses.
不要定义与实现接口名一样的类 / 接口名
1 public interface BaseMapper<T> extends com.baomidou.mybatisplus.mapper.BaseMapper<T> {
2 public interface BaseMappers<T> extends com.baomidou.mybatisplus.mapper.BaseMapper<T> {
3 //特别注意,由于继承了通用BaseMapper,该接口不能被扫描到,否则会出错,MapperScan(value="com.letsun.**.mapper*",markerInterface=CommonMapper.class)
4
5 /**
6 * 自定义多表复杂查询
7 * @param map
8 * @param page
9 * @return List<T>
10 * @author xx<2018年4月12日>
11 */
12 List<T> selectComplex(Map<String,Object> map,Pagination page);
13 }
b.Method names should start with a lower case letter()
Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.
方法应该是动词,并且首字母小写其他内部单词大写
1 //获取下一个位置,并移动起始位置
2 public final boolean GetNextgetNext(Out<String> strMsg) {
3 strMsg.setData("");
4
5 //空
6 if (m_end == m_start) {
7 return false;
8 }
9
10 strMsg.setData(m_ringList[m_start]);
11 m_start = (m_start + 1) % m_capacity;
12
13 return true;
14 }
c.Class names should start with an upper case letter
Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple and descriptive. Use whole words-avoid acronyms and abbreviations (unless the abbreviation is much more widely used than the long form, such as URL or HTML).
类名首字母应该大写
1 public class testTest {}
d.Field names should start with a lower case letter
Names of fields that are not final should be in mixed case with a lowercase first letter and the first letters of subsequent words capitalized.
不是 final 的类属性首字母应小写
1 public class OrderApiConfig {
2
3 public static String Base base = "tms.";
4 }
e.Class is not derived from an Exception,even though it is named as such
This class is not derived from another exception, but ends with ''Exception''. This will be confusing to users of this class.
Class 没有继承 Exception,虽然名字像一个异常,不能这样命名,会产生误解
1 public class GpsException extends AbsIniFilter
2 {
3 @Override
4 public void Excute()
5 {
6 this.getenumActionCategory(), this.getenumActionType(), TaAutoScheduleLog.EnumContentType.GpsException, TaAutoScheduleLog.EnumTppe.GpsException, "", "", OperUser);
7 }
8 }
2.Mutable enum field
a.Enum field is public and mutable
A mutable public field is defined inside a public enum, thus can be changed by malicious code or by accident from another package. Though mutable enum fields may be used for lazy initialization, it''s a bad practice to expose them to the outer world. Consider declaring this field final and/or package-private.
枚举对象的某个属性不应该是 public,尽管可变枚举属性会执行懒加载。应考虑用 final 及 / 或 private 修饰属性。
1 public enum EnumInvalid {
2 No(20),Yes(10);
3
4 public final int code;
5
6 EnumInvalid(int code) {
7 this.code = code;
8 }
9 public static EnumInvalid getByCode(int code) {
10 EnumInvalid[] enums = EnumInvalid.values();
11 for (EnumInvalid dd_TypeEnum : enums) {
12 if (dd_TypeEnum.code == code) {
13 return dd_TypeEnum;
14 }
15 }
16 return null;
17 }
18 }
b.Public enum method unconditionally sets its field
This public method declared in public enum unconditionally sets enum field, thus this field can be changed by malicious code or by accident from another package. Though mutable enum fields may be used for lazy initialization, it''s a bad practice to expose them to the outer world. Consider removing this method or declaring it package-private.
私有方法应该使用 private
1 public enum EnumCode {
2 /**
3 * 订单异常
4 *
5 */
6 // [Description("订单异常")]
7 order_exception(-3,"订单异常");
8
9 private int intValue;
10
11 private String name;
12 private static java.util.HashMap<Integer, EnumCode> mappings;
13
14 private synchronized static java.util.HashMap<Integer, EnumCode> getMappings() {
15 if (mappings == null) {
16 mappings = new java.util.HashMap<Integer, EnumCode>();
17 }
18 return mappings;
19 }
20
21 private EnumCode(int value,String name) {
22 intValue = value;
23 this.name = name;
24 EnumCode.getMappings().put(value, this);
25 }
26
27 public int getValue() {
28 return intValue;
29 }
30
31 public static EnumCode forValue(int value) {
32 return getMappings().get(value);
33 }
34
35
36 public static String getValueByCode(Integer code) {
37 for (EnumCode platformFree : EnumCode.values()) {
38 if (code.equals(platformFree.intValue)) {
39 return platformFree.getName();
40 }
41 }
42 return null;
43 }
44
45 public String getName() {
46 return name;
47 }
48
49 public int getIntValue() {
50 return intValue;
51 }
52
53 public void setIntValue(int intValue) {
54 this.intValue = intValue;
55 }
56 private void setIntValue(int intValue) {
57 this.intValue = intValue;
58 }
59
60 public void setName(String name) {
61 this.name = name;
62 }
63 private void setName(String name) {
64 this.name = name;
65 }
66 }
3.Bad use of return value from method
a.Method ignores exceptional return value
This method returns a value that is not checked. The return value should be checked since it can indicate an unusual or unexpected function execution. For example, the File.delete() method returns false if the file could not be successfully deleted (rather than throwing an Exception). If you don''t check the result, you won''t notice if the method invocation signals unexpected behavior by returning an atypical return value.
方法忽略了异常返回值,需捕获
1 private static void CreateDirectory(String directory) {
2 File file = new File(directory);
3 if (!file.exists() || !file.isDirectory()) {
4 try {
5 file.mkdirs();
6 }
7 catch (Exception ex)
8 {
9 throw ex;
10 }
11 }
12 }
4.Stream not colsed on all paths
a.Mathod may fail to close stream
The method creates an IO stream object, does not assign it to any fields, pass it to other methods that might close it, or return it, and does not appear to close the stream on all paths out of the method. This may result in a file descriptor leak. It is generally a good idea to use a finally block to ensure that streams are closed.
需确保数据流关闭
1 public static String doPost(final Map<String, Object> strParams, final Map<String, File> fileParams) {
2 HttpURLConnection conn = null;
3 try {
4 URL url = new URL(Const.ErpfileUrl);
5 conn = (HttpURLConnection) url.openConnection();
6 conn.setRequestMethod("POST");
7 conn.setReadTimeout(TIME_OUT);
8 conn.setConnectTimeout(TIME_OUT);
9 conn.setDoOutput(true);
10 conn.setDoInput(true);
11 conn.setUseCaches(false);// Post 请求不能使用缓存
12 // 设置请求头参数
13 conn.setRequestProperty("Connection", "Keep-Alive");
14 conn.setRequestProperty("Charset", "UTF-8");
15 conn.setRequestProperty("Content-Type", CONTENT_TYPE + "; boundary=" + BOUNDARY);
16 /**
17 * 请求体
18 */
19 // 上传参数
20 DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
21 // getStrParams()为一个
22 dos.writeBytes(getStrParams(strParams).toString());
23 dos.flush();
24
25 // 文件上传
26 StringBuilder fileSb = new StringBuilder();
27 for (Map.Entry<String, File> fileEntry : fileParams.entrySet()) {
28 fileSb.append(PREFIX).append(BOUNDARY).append(LINE_END)
29 /**
30 * 这里重点注意: name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件 filename是文件的名字,包含后缀名的
31 * 比如:abc.png
32 */
33 .append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileEntry.getKey() + "\"" + LINE_END)
34 .append("Content-Type: */*" + LINE_END) // 此处的ContentType不同于 请求头 中Content-Type
35 .append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
36 dos.writeBytes(fileSb.toString());
37 dos.flush();
38 InputStream is = new FileInputStream(fileEntry.getValue());
39 byte[] buffer = new byte[1024];
40 int len = 0;
41 while ((len = is.read(buffer)) != -1) {
42 dos.write(buffer, 0, len);
43 }
44 is.close();
45 dos.writeBytes(LINE_END);
46 }
47 // 请求结束标志
48 dos.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END);
49 dos.flush();
50 dos.close();
51
52 BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
53 StringBuilder response = new StringBuilder();
54 String line = null;
55 while ((line = reader.readLine()) != null) {
56 response.append(line);
57 }
58 reader.close();
59 return response.toString();
60 } catch (Exception e) {
61 e.printStackTrace();
62 } finally {
63 if (conn != null) {
64 conn.disconnect();
65 }
66 }
67
68 return "";
69 }
5.Dubious method invocation
a.Adding elements of an entry set may fail due to reuse of Entry objects
The entrySet() method is allowed to return a view of the underlying Map in which a single Entry object is reused and returned during the iteration. As of Java 1.6, both IdentityHashMap and EnumMap did so. When iterating through such a Map, the Entry value is only valid until you advance to the next iteration. If, for example, you try to pass such an entrySet to an addAll method, things will go badly wrong.
一个入口的添加可能因为重用 Entry 对象导致失败,entrySet () 方法允许重复使用导致数据异常。
1 public static String sortMapForSign(Map<String, Object> paramMap, String accessKey) {
2 TreeMap<String,Object> treeMap=new TreeMap<>();
3 treeMap.putAll(paramMap);
4 // 参数排序
5 List<Map.Entry<String, Object>> entryList = new ArrayList<>();
6 entryList.addAll(paramMap.entrySet());
7 Collections.sort(entryList, (o1, o2) -> o1.getKey().compareTo(o2.getKey()));
8 // 拼接成待签名串
9 StringBuffer sb = new StringBuffer(accessKey);
10 for (Map.Entry<String, Object> entry : entryList) {
11 for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
12 String paramKey = entry.getKey();
13 sb.append(paramKey + entry.getValue());
14 }
15 String nativSign = Md5Utils.md5Encode(sb.toString()).toUpperCase();
16 return nativSign;
17 }
6.Bad implementation of Serializable class
a.Class defines clone() but doesn''t implement Cloneable
This class defines a clone() method but the class doesn''t implement Cloneable. There are some situations in which this is OK (e.g., you want to control how subclasses can clone themselves), but just make sure that this is what you intended.
类定义了 clone () 但没有实现 Cloneable
1 private static class Distance {
2 private static class Distance implements Cloneable {
3 /**
4 *
5 *
6 */
7 public BigDecimal QH_distance = new BigDecimal(0);
8 /**
9 *
10 *
11 */
12 public BigDecimal PH_distance = new BigDecimal(0);
13
14 public Distance clone() {
15 Distance varCopy = new Distance();
16
17 varCopy.QH_distance = this.QH_distance;
18 varCopy.PH_distance = this.PH_distance;
19
20 return varCopy;
21 }
22
23 public void setQH_distance(BigDecimal qh_distance2) {
24 // TODO Auto-generated method stub
25
26 }
27
28 public void setPH_distance(BigDecimal ph_distance2) {
29 // TODO Auto-generated method stub
30
31 }
32 }
7.Incorrect definition of Serializable class
a.serialVersionUID isn''t final
This class defines a serialVersionUID field that is not final. The field should be made final if it is intended to specify the version UID for purposes of serialization.
serialVersionUID 不是 final 的
1 public class GetTaskStatusByCarModel implements Serializable {
2 /**
3 * @Fields serialVersionUID : TODO
4 */
5 private static long serialVersionUID = 1L;
6 private static final long serialVersionUID = 1L;
7 }
b.Comparator doesn''t implement Serializable
This class implements the Comparator interface. You should consider whether or not it should also implement the Serializable interface. If a comparator is used to construct an ordered collection such as a TreeMap, then the TreeMap will be serializable only if the comparator is also serializable. As most comparators have little or no state, making them serializable is generally easy and good defensive programming.
Comparator 没有实现 Serializable
1 class MyComparator implements Comparator<GetHistoryConsumedTimeModel> {
2 class MyComparator implements Comparator<GetHistoryConsumedTimeModel>, Serializable {
3 @Override
4 public int compare(GetHistoryConsumedTimeModel s1, GetHistoryConsumedTimeModel s2) {
5 int num = s1.getval().intValue() - s2.getval().intValue();
6 int num1 = (num == 0 ? s1.getID().compareTo(s2.getID()) : num);
7 return num1;
8 }
9 }
8.Format string problem
a.Format string should use %n rather than \n
This format string include a newline character (\n). In format strings, it is generally preferable better to use %n, which will produce the platform-specific line separator.
格式化代码应该使用 % n 代替 \n
1 sbLog.append(String.format("请求路径: %s%n", request.getRequestURL().toString()));
2 sbLog.append(String.format("请求方式: %s\r\n", request.getMethod()));
3 sbLog.append(String.format("请求类名: %s\r\n", joinPoint.getSignature().getDeclaringTypeName()));
4
9.Dropped or ignored exception
a.Method might ignore exception
This method might ignore an exception. In general, exceptions should be handled or reported in some way, or they should be thrown out of the method.
异常需捕获或者手动处理。
1 if (StringUtils.isNotBlank(bagReq.getNeedToDate())) {
2 try {
3
4 SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy",Locale.US);
5 Date d=sdf.parse(bagReq.getNeedToDate());
6 sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.US);
7 wrapper.eq("NeedToDate", sdf.format(d));
8 } catch (Exception e) {
9 // TODO: handle exception
10 }
11
12 }
10.Checking String equality using == or !=(严重)
a.Comparison of String objects using == or !=
This code compares java.lang.String objects for reference equality using the == or != operators. Unless both strings are either constants in a source file, or have been interned using the String.intern() method, the same string value may be represented by two different String objects. Consider using the equals(Object) method instead
对象的比较不要使用 == 和!=,要使用 equals 方法
1 private static <T> boolean IsCanCompare(Class<T> t) {
2 if (t.isAssignableFrom(Comparable.class)) { //(t.IsValueType) {
3 return true;
4 } else {
5 // String是特殊的引用类型
6 if (t.getName() == String.class.getName()) {
7 return true;
8 }
9 if(t.getName().equals(String.class.getName()))
10 {
11 return true;
12 }
13 return false;
14 }
15 }
二 Correctness (一般的正确性问题,可能导致错误的代码)
1.Null pointer dereference
a.Possible null pointer dereference
There is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can''t ever be executed; deciding that is beyond the ability of FindBugs.
1 public int UpdateBagState(String waybillNo, String operationMan) {
2 String tWaybingllNo ="";
3 if(null != waybillNo && waybillNo.contains(",")) {
4 String[] tWaybillNoArr = waybillNo.split(",");
5 if(tWaybillNoArr[0].length() == 0) {
6 tWaybingllNo = tWaybillNoArr[0];
7 }else {
8 return 0;
9 }
10
11 }else {
12 if(null != waybillNo&&waybillNo.length() == 0) {
13 return 0;
14 }else {
15 tWaybingllNo = waybillNo;
16 }
17 }
b.Possible null pointer dereference in method on exception path
A reference value which is null on some exception control path is dereferenced here. This may lead to a NullPointerException when the code is executed. Note that because FindBugs currently does not prune infeasible exception paths, this may be a false warning.
Also note that FindBugs considers the default case of a switch statement to be an exception path, since the default case is often infeasible.
1 public PickupingScan GetPickupingScanByTaskNo(String taskNo) {
2 String url = ApiConfig.Pickup;
3 Map<String, Object> requestParameters = new HashMap<String, Object>();
4 requestParameters.put("elasticsearchFlag", "N");
5 requestParameters.put("countFlag", "N");
6 requestParameters.put("page", 1);
7 requestParameters.put("pageSize", 10);
8 Map<String, Object> obj1 = new HashMap<String, Object>();
9 List<Object> list1 = new ArrayList<Object>();
10 Map<String, Object> obj2 = new HashMap<String, Object>();
11 obj2.put("conditionOperation", "");
12 obj2.put("propertyName", "orderNumber");
13 List<Object> list2 = new ArrayList<Object>();
14 list2.add(taskNo);
15 obj2.put("values", list2);
16 obj2.put("postBrackets", ")");
17 obj2.put("type", "string");
18 obj2.put("frontBrackets", "(");
19 obj2.put("operation", "equal");
20 obj2.put("columnName", "order_number");
21 list1.add(obj2);
22 obj1.put("vos", list1);
23 requestParameters.put("generic", obj1);
24 String res = ASMOpenApi.request(url,requestParameters );
25 if (StringUtils.isNotBlank(res)) {
26 ObjectMapper mapper = new ObjectMapper();
27 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
28 KyeResponse<CommonResult<Pickup>> responseModel = null;
29 try {
30 responseModel = mapper.readValue(res, new com.fasterxml.jackson.core.type.TypeReference<Response<CommonResult<Pickup>>>() {
31 });
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 // Response<CommonResult<Pickup>> responseModel = JSONObject.parseObject(res, new TypeReference<Response<CommonResult<Pickup>>>() {
36 // });
37 if (responseModel!=null||responseModel.isFail())
38 return null;
39 if (responseModel.getData() == null || responseModel.getData().getrows() == null || responseModel.getData().getrows().size() == 0)
40 return null;
41 return ConfigConverter.MapConfigToPickupingScan(responseModel.getData().getrows().get(0));
42 }
43 return null;
44 }
c.Non-virtual method call passes null for non-null parameter
A possibly-null value is passed to a non-null method parameter. Either the parameter is annotated as a parameter that should always be non-null, or analysis has shown that it will always be dereferenced.
可能为 null 的值将传递给非 null 方法参数。 要么将参数注释为应始终为非 null 的参数,要么分析表明它将始终被取消引用。
Response<GetTaskHistoryConsumedTime> result = autoScheduleCoreHelper.GetHistoryConsumedTime(_type, company_no, number, weight,null"", departName);
d.Null pointer dereference(严重)
A null pointer is dereferenced here. This will lead to a NullPointerException when the code is executed.
1 public List<AddSubscribeCusomterModel> OrderNoValid(String orderNo) {
2
3 TaTask taskEntity = null;
4 this.OrderNoValidCheck(orderNo, taskEntity);
5 AddSubscribeCusomterModel newModel = new AddSubscribeCusomterModel();
6 newModel.setorderno(orderNo);
7 if(taskEntity!=null)
8 {
9 newModel.setcompanyname(taskEntity.getCol007());
10 newModel.setcarno(taskEntity.getCarNo());
11 newModel.setappointment_name(taskEntity.getCol008());
12 newModel.setType(taskEntity.getType() + "");
13 }
14 List<AddSubscribeCusomterModel> lst = new ArrayList<AddSubscribeCusomterModel>();
15 lst.add(newModel);
16 return lst;
17 }
e.Read of unwritten field
The program is dereferencing a field that does not seem to ever have a non-null value written to it. Unless the field is initialized via some mechanism not seen by the analysis, dereferencing this value will generate a null pointer exception.
此字段是永远不会写入值,如果不需要的话就删除掉
1 public class StopUnFinishTask extends AbsDispatch
2 {
3
4
5 private TaManualLogNew.EnumManualSubType _enumManualSubType = TaManualLogNew.EnumManualSubType.Manual_StopUnFinishTask;
6 @Override
7 protected TaManualLogNew.EnumManualSubType getenumManualSubType()
8 {
9 return _enumManualSubType;
10 }
11 @Override
12 protected void setenumManualSubType(TaManualLogNew.EnumManualSubType value)
13 {
14 _enumManualSubType = value;
15 }
16
17 }
f.Method call passes null for non-null parameter
This method call passes a null value for a non-null method parameter. Either the parameter is annotated as a parameter that should always be non-null, or analysis has shown that it will always be dereferenced.
方法调用传递 null 给非空参数
1 public static String encode(String unencoded) {
2 byte[] bytes = null;
3 try {
4 bytes = unencoded.getBytes("UTF-8");
5 } catch (UnsupportedEncodingException ignored) {
6 }
7 if(bytes!=null)
8 {
9 return encode(bytes);
10 }
11 return null;
12 }
g.Value is null and guaranteed to be dereferenced on exception path
There is a statement or branch on an exception path that if executed guarantees that a value is null at this point, and that value that is guaranteed to be dereferenced (except on forward paths involving runtime exceptions)
null 值会在 exception 处理中被用到
1 public static String doPost(String url, Map<String, String> param,Map<String, String> hearer) {
2 // 创建Httpclient对象
3 CloseableHttpClient httpClient = HttpClients.createDefault();
4 CloseableHttpResponse response = null;
5 String resultString = "";
6 try {
7 // 创建Http Post请求
8 HttpPost httpPost = new HttpPost(url);
9 if (hearer != null && !hearer.isEmpty()) {
10 for (Entry<String, String> enty : hearer.entrySet()) {
11 httpPost.addHeader(enty.getKey(), enty.getValue());
12 }
13 }
14 // 创建参数列表
15 if (param != null) {
16 List<NameValuePair> paramList = new ArrayList<NameValuePair>();
17 for (String key : param.keySet()) {
18 paramList.add(new BasicNameValuePair(key, param.get(key)));
19 }
20 // 模拟表单
21 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
22 httpPost.setEntity(entity);
23 }
24 // 执行http请求
25 response = httpClient.execute(httpPost);
26 resultString = EntityUtils.toString(response.getEntity(), "utf-8");
27 } catch (Exception e) {
28 e.printStackTrace();
29 } finally {
30 try {
31 if(response!=null)
32 {
33 response.close();
34 }
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39 return resultString;
40 }
2.Redundant comparison to null
a.Nullcheck of value previously dereferenced
A value is checked here to see whether it is null, but this value can''t be null because it was previously dereferenced and if it were null a null pointer exception would have occurred at the earlier dereference. Essentially, this code and the previous dereference disagree as to whether this value is allowed to be null. Either the check is redundant or the previous dereference is erroneous.
对一个已经使用的值进行了 null 检测
1 private TA_ZWICRecordset GetRecordset(Map<String, Object> dic, String url) {
2 String res = OpenApi.request(url, dic);
3 if (StringUtils.isNotBlank(res)) {
4 ObjectMapper mapper = new ObjectMapper();
5 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
6 Response<ERPResponseResult<RecordSetResponseModel>> responseModel = null;
7 try {
8 responseModel = mapper.readValue(res, new com.fasterxml.jackson.core.type.TypeReference<Response<ERPResponseResult<RecordSetResponseModel>>>() {
9 });
10 } catch (IOException e) {
11 e.printStackTrace();
12 }
13 if (responseModel == null || responseModel.isFail() || responseModel.getData() == null || responseModel.getData().getRows() == null)
14 return null;
15
16 List<RecordSetResponseModel> models = responseModel.getData().getRows();
17
18 Collections.sort(models, new Comparator<RecordSetResponseModel>() {
19 @Override
20 public int compare(RecordSetResponseModel o1, RecordSetResponseModel o2) {
21 return o2.getCol_006() > o1.getCol_006() ? 1 : -1;
22 }
23 });
24
25 if(models!=null && models.size()>0)
26 {
27 return RecordSetConverter.ToEntity(models.get(0));
28 }
29 }
30 return null;
31 }
3.Suspicious bitwise logical expression
a.BitWise OR of signed byte value
Loads a byte value (e.g., a value loaded from a byte array or returned by a method with return type byte) and performs a bitwise OR with that value. Byte values are sign extended to 32 bits before any any bitwise operations are performed on the value. Thus, if b[0] contains the value 0xff, and x is initially 0, then the code ((x << 8) | b[0]) will sign extend 0xff to get 0xffffffff, and thus give the value 0xffffffff as the result.
In particular, the following code for packing a byte array into an int is badly wrong:
int result = 0;
for(int i = 0; i < 4; i++)
result = ((result << 8) | b[i]);
The following idiom will work instead:
int result = 0;
for(int i = 0; i < 4; i++)
result = ((result << 8) | (b[i] & 0xff));
不能 在带符号的 byte 值上进行位 OR 运算
1 private static long byteArrayToLong(byte[] b) {
2 long resultHigh = 0;
3 long resultLow = 0;
4 for (int i = 0; i < b.length; i = i + 2) {
5 resultHigh = resultHigh << 8 | b[i];
6 resultHigh = ((resultHigh << 8) | (b[i]&0xff));
7 resultLow = resultLow << 8 | b[i + 1];
8 resultLow = (resultLow << 8) | (b[i + 1]&0xff);
9 }
10
11 return resultHigh ^ resultLow;
12 }
4.Casting from integer values
a.Integral value cast to double and then passed to Math.ceil
This code converts an integral value (e.g., int or long) to a double precision floating point number and then passing the result to the Math.ceil() function, which rounds a double to the next higher integer value. This operation should always be a no-op, since the converting an integer to a double should give a number with no fractional part. It is likely that the operation that generated the value to be passed to Math.ceil was intended to be performed using double precision floating point arithmetic.
不能 int 转换成 double,然后传递给 Math.ceil
1 public ERPResponseResult(List<T> models, int rowTotal, int page, String pagesizestr) {
2 Integer curentpagesize = 1;
3 if (!StringUtils.isBlank(pagesizestr)) {
4 curentpagesize = Ints.tryParse(pagesizestr);
5 }
6 if (curentpagesize == null) {
7 curentpagesize = 0;
8 }
9 this.setRows(models);
10 this.setRowTotal(rowTotal);
11 this.setPage(page);
12 this.setPageSize(curentpagesize);
13 this.setPageTotal(getPageSize() == 0 ? getPageSize() : (int) Math.ceil(Double.parseDouble(Integer.toString(rowTotal))/ Double.parseDouble(Integer.toString(getPageSize()))));
14 // erpResult.pageTotal = rowTotal / erpResult.pageSize;
15 }
5.Format string problem
a.MessageFormat supplied where printf style format expected(严重)
A method is called that expects a Java printf format string and a list of arguments. However, the format string doesn''t contain any format specifiers (e.g., %s) but does contain message format elements (e.g., {0}). It is likely that the code is supplying a MessageFormat string when a printf-style format string is required. At runtime, all of the arguments will be ignored and the format string will be returned exactly as provided without any formatting.
需要使用 printf 样式时使用了 MessageFormat
1 mDebugLog.append("\n").append(String.format("TaskJson:{0}%s", taskJson));
b.More arguments are passed than are actually used in the format string
A format-string method with a variable number of arguments is called, but more arguments are passed than are actually used by the format string. This won''t cause a runtime exception, but the code may be silently omitting information that was intended to be included in the formatted string.
缺少占位符
1 FileLogHelper.Error(String.format("【UpdataCarDepart】根据车牌更新点部失败 车牌:%s 点部:%s 原因:%s", model.getcarno(),model.getdepart(),ex.getMessage()));
2
6.Dubious method invocation
a.Bad constant value for month(严重)
This code passes a constant month value outside the expected range of 0..11 to a method.
对于 month 错误的常量值
1 public static Date getLastMonthTime(boolean startOrEnd) {
2 Calendar calendar = Calendar.getInstance();
3 int month = calendar.get(Calendar.MONTH) - 1;
4 int year = calendar.get(Calendar.YEAR);
5 Date dtStart;
6 Date dtEnd;
7 if (month == 0) { // 表示上月为12月 去年的
8 calendar.set(year - 1, 1211, 1);
9 dtStart = calendar.getTime();
10 calendar.set(year - 1, 1211, 31, 23, 59, 59);
11 dtEnd = calendar.getTime();
12 } else {
13 // dtStart = new Date(new Date().Year, month, 1);
14 calendar.set(year, month, 1);
15 dtStart = calendar.getTime();
16 calendar.add(Calendar.MONTH, 1);
17 calendar.add(Calendar.SECOND, -1);
18 dtEnd = calendar.getTime();
19 }
20 return startOrEnd ? dtStart : dtEnd;
21 }
7.Regular expressions
a."." or "|" used for regular expression(严重)
A String function is being invoked and "." or "|" is being passed to a parameter that takes a regular expression as an argument. Is this what you intended? For example
s.replaceAll(".", "/") will return a String in which every character has been replaced by a ''/'' character
s.split(".") always returns a zero length array of String
"ab|cd".replaceAll("|", "/") will return "/a/b/|/c/d/"
"ab|cd".split("|") will return array with six (!) elements: [, a, b, |, c, d]
不能使用 spil 分隔 "." 和 "|"
1 String[] depotManualDealConfig = strDepotManualDealConfig.split("\\|");
1 String[] depotManualDealConfig = StringUtils.split(strDepotManualDealConfig,"|");
b.Invalid syntax for regular expression(严重)
The code here uses a regular expression that is invalid according to the syntax for regular expressions. This statement will throw a PatternSyntaxException when executed.
非法的正则表达式
1 String regex = "[\\u4E00-\\u9FFF0-9a-zA-Z-—\\\\/#()()]\"), @\"[\\u4E00-\\u9FFF].*";
2 Pattern pattern = Pattern.compile(regex);
8.Suspicious integer expression
a.Bad comparison of signed byte
Signed bytes can only have a value in the range -128 to 127. Comparing a signed byte with a value outside that range is vacuous and likely to be incorrect. To convert a signed byte b to an unsigned value in the range 0..255, use 0xff & b
byte 比较使用错误,有符号位比较范围在 - 128 到 127,如果要用无符号位比较用 0xff 转换
1 private static String UrlEncode(String url)
2 {
3 byte[] bytes;
4 try
5 {
6 bytes= url.getBytes("UTF-8");
7 }
8 catch (Exception ex)
9 {
10 return null;
11 }
12 int num = bytes.length;
13 StringBuilder stringBuilder = new StringBuilder(num * 3);
14 for (int i = 0; i < num; i++)
15 {
16 if (bytes[i] > -128)
17 {
18 stringBuilder.append("%");
19 stringBuilder.append(String.format("%02X", bytes[i]));
20 i++;
21 stringBuilder.append("%");
22 stringBuilder.append(String.format("%02X", bytes[i]));
23 }
24 else
25 {
26 String result;
27 try {
28 result=new String(bytes,"UTF-8");
29 }
30 catch (Exception ex)
31 {
32 return null;
33 }
34 stringBuilder.append(result);
35 }
36 }
37 return stringBuilder.toString();
38 }
b.Bad comparison of nonnegative value with negative constant or zero
This code compares a value that is guaranteed to be non-negative with a negative constant or zero.
不为负数的值比较使用错误
1 if (notExistDepartIdList == null || notExistDepartIdList.size() <== 0) {
2 String idList = StringUtils.join(notExistDepartIdList, ",");
3 String errorMsg = String.format("保存失败,这些点部不存在:%1$s", idList);
4 return errorMsg;
5 }
9.Useless/non-informative string generated
a.Invocation of toString on an array(严重)
The code invokes toString on an array, which will generate a fairly useless result such as [C@16f0472. Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array. See Programming Puzzlers, chapter 3, puzzle 12.
调用了数组的 toString, 使用错误
1 private boolean AddValidate(AddAIStationConfigRequest input) {
2
3 int type = input.gettype();
4 TsAiStationConfig dbEntity = tsAiStationConfigService.Get(input.getname(), type);
5 if (dbEntity != null && StringUtils.isNotBlank(dbEntity.getId())) {
6 throw new Exception("版本号已存在");
7 }
8
9 List<TsAiStationConfig> list = tsAiStationConfigService.GetList(type);
10
11 if (list != null && !list.isEmpty() && StringUtils.isNotBlank(input.getdepotids())) {
12 String[] inputdepotidArray = input.getdepotids().split(",");
13 List<String> dbDepotIdList = list.parallelStream().map(p -> p.getDepotIds()).collect(Collectors.toList());
14
15 if (dbDepotIdList != null && !dbDepotIdList.isEmpty() && inputdepotidArray != null) {
16 for (String depots : dbDepotIdList) {
17
18 if(StringUtils.isBlank(depots)) {
19 continue;
20 }
21
22 String[] dbList = depots.split(",");
23
24 for (String db_depot : dbList) {
25 if(Arrays.asList(inputdepotidArray).contains(db_depot))
26 {
27 throw new Exception("已存在,dbDepotIdList:" + JSONObject.toJSONString(dbDepotIdList));
28 }
29 if (inputdepotidArray.toString().contains(db_depot)) {
30 throw new Exception("已存在,dbDepotIdList:" + JSONObject.toJSONString(dbDepotIdList));
31 }
32 }
33 }
34 for (String input_depot : inputdepotidArray) {
35 TsPositionConfig posCfg = positionCachedHelper.IsOpenEntity(input_depot);
36 if (posCfg == null) {
37 throw new Exception("未开启" + input_depot);
38 }
39 }
40 }
41 }
42 return true;
43 }
10.Ignored parameter
a.A parameter is dead upon entry to a method but overwritten
The initial value of this parameter is ignored, and the parameter is overwritten here. This often indicates a mistaken belief that the write to the parameter will be conveyed back to the caller.
参数没有被使用,但是被重新赋值了,这种
1 public GetUseableTrcukModel Get(String depot_id, String carno, int cached)
2 {
3 cached = 0;
4 String key = RedisPrefixKey.ac13 + depot_id;
5 GetUseableTrcukModel model = null;
6 if (redisUtils.hHasKey(key, carno))
7 {
8 model = (GetUseableTrcukModel)redisUtils.hget(key, carno);
9 cached = 1;
10 }
11 return model;
12 }
11.Bad casts of object references
a.Impossible downcast of toArray() result
This code is casting the result of calling toArray() on a collection to a type more specific than Object[], as in:
String[] getAsArray(Collection<String> c) {
return (String[]) c.toArray();
}
This will usually fail by throwing a ClassCastException. The toArray() of almost all collections return an Object[]. They can''t really do anything else, since the Collection object has no reference to the declared generic type of the collection.
The correct way to do get an array of a specific type from a collection is to use c.toArray(new String[]); or c.toArray(new String[c.size()]); (the latter is slightly more efficient).
There is one common/known exception exception to this. The toArray() method of lists returned by Arrays.asList(...) will return a covariantly typed array. For example, Arrays.asArray(new String[] { "a" }).toArray() will return a String []. FindBugs attempts to detect and suppress such cases, but may miss some.
数组转换使用了错误的方法
1 String[] carNoLst = (String[])list.stream().map(p -> p.getCarNo()).collect(Collectors.toList()).toArray();
2 String[] carNoLst = list.stream().map(p -> p.getCarNo()).collect(Collectors.toList()).toArray(new String[list.size()]);
12.Unwritten field
a.Unwritten field
This field is never written. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.
属性没有使用过,建议去掉
1 public class UpdateBagStateModel {
2 /**
3 * 批次号
4 *
5 */
6 private String batchno;
7
8 public final String getbatchno() {
9 return batchno;
10 }
11
12 public final void setbatchno(String value) {
13 batchno = value;
14 }
15
16 /**
17 * 运单号
18 *
19 */
20 //C# TO JAVA CONVERTER TODO TASK: Java annotations will not correspond to .NET attributes:
21 private String waybillno;
22 public final String getwaybillno() {
23 return waybillno;
24 }
25
26 public final void setwaybillno(String value) {
27 waybillno = value;
28 }
29
30 private String operationman;
31
32 public final String getOperationman()
33 {
34 return operationman;
35 }
36
37
38 }
b.Field only ever set to null
All writes to this field are of the constant value null, and thus all reads of the field will return null. Check for errors, or remove it if it is useless.
属性曾经设置为 null,看具体代码,有些类属性没用了要去掉或者重新定义成局部变量。
13.Confusing method name
a.Very confusing method names
The referenced methods have names that differ only by capitalization. This is very confusing because if the capitalization were identical then one of the methods would override the other.
非常容易迷惑的方法名
1 protected TaAutoScheduleLog.EnumActionCategory getenumActionCategorygetEnumActionCategory()
2 {
3 return TaAutoScheduleLog.EnumActionCategory.ERP;
4 }
三 Dodgy code (具有潜在危险的代码,可能运行期产生错误)
1.Null pointer dereference
a.Possible null pointer dereference due to return value of called method
The return value from a method is dereferenced without a null check, and the return value of that method is one that should generally be checked for null. This may lead to a NullPointerException when the code is executed.
1 public static boolean deleteDirectory(String filePath) {
2 boolean flag = false;
3 // 如果sPath不以文件分隔符结尾,自动添加文件分隔符
4 if (!filePath.endsWith(File.separator)) {
5 filePath = filePath + File.separator;
6 }
7 File dirFile = new File(filePath);
8 // 如果dir对应的文件不存在,或者不是一个目录,则退出
9 if (!dirFile.exists() || !dirFile.isDirectory()) {
10 return false;
11 }
12 flag = true;
13 // 删除文件夹下的所有文件(包括子目录)
14 File[] files = dirFile.listFiles();
15 if(files!=null) {
16 for (int i = 0; i < files.length; i++) {
17 // 删除子文件
18 if (files[i].isFile()) {
19 flag = deleteFile(files[i].getAbsolutePath());
20 if (!flag) {
21 break;
22 }
23
24 } // 删除子目录
25 else {
26 flag = deleteDirectory(files[i].getAbsolutePath());
27 if (!flag) {
28 break;
29 }
30
31 }
32 }
33 }
34 if (!flag){
35 return false;
36 }
37
38 // 删除当前目录
39 if (dirFile.delete()) {
40 return true;
41 } else {
42 return false;
43 }
44 }
b.Load of known null value
The variable referenced at this point is known to be null due to an earlier check against null. Although this is valid, it might be a mistake (perhaps you intended to refer to a different variable, or perhaps the earlier check to see if the variable is null should have been a check to see if it was non-null).
1 if (entity == null) {
2 throw new RuntimeException("entity == null:ExcuteErpOldDispatch" + entity.getCarNo());
3 }
c.Read of unWritten public or protected field
The program is dereferencing a public or protected field that does not seem to ever have a non-null value written to it. Unless the field is initialized via some mechanism not seen by the analysis, dereferencing this value will generate a null pointer exception.
引用的对象可能永远为空,即定义对象的时候就赋值 null,这种写法是危险的。
1 public class BaseVoice
2 {
3
4 protected TaVoiceMsg mTaVoiceMsg = null;
5 protected MsgContent mMsgContent = null;
6 }
2.RuntimeException capture
a.Exception is caught when Exception is not thrown
This method uses a try-catch block that catches Exception objects, but Exception is not thrown within the try block, and RuntimeException is not explicitly caught. It is a common bug pattern to say try { ... } catch (Exception e) { something } as a shorthand for catching a number of types of exception each of whose catch blocks is identical, but this construct also accidentally catches RuntimeException as well, masking potential bugs.
A better approach is to either explicitly catch the specific exceptions that are thrown, or to explicitly catch RuntimeException exception, rethrow it, and then catch all non-Runtime Exceptions, as shown below:
try {
...
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
... deal with all non-runtime exceptions ...
}
异常捕获之后未处理
1 public static String getPreTime(String sj1, String jj) {
2 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
3 String mydate1 = "";
4 try {
5 Date date1 = format.parse(sj1);
6 long Time = (date1.getTime() / 1000) + Integer.parseInt(jj) * 60;
7 date1.setTime(Time * 1000);
8 mydate1 = format.format(date1);
9 } catch (Exception e) {
10 //todo
11 }
12 return mydate1;
13 }
3.Bad casts of object references
a.instanceof will always retrun true
This instanceof test will always return true (unless the value being tested is null). Although this is safe, make sure it isn''t an indication of some misunderstanding or some other logic error. If you really want to test the value for being null, perhaps it would be clearer to do better to do a null test rather than an instanceof test.
instanceof 判断永远为 true
public static String buildKyeApiSignForGet(String accessKey, Map<String, Object> object) {
if (object instanceof Mapobject!=null) {
return sortMapForSign((Map<String,Object>)object, accessKey);
} else {
throw new RuntimeException("待签名串类型不符合MAP");
}
}
4.Redundant comparison to null
a.Redundant nullcheck of value known to be non-null
This method contains a redundant check of a known non-null value against the constant null.
对一个已知不是 null 的值重复进行空值判断
1 String dddrivename = (dd == null ? "" : dd.getDD_003());
2 String dddriveid = (dd == null ? "" : dd.getdriverId());
3 String ddcarno = (dd == null ? "" : dd.getDD_004());
b.Redundant nullcheck of value known to be null
This method contains a redundant check of a known null value against the constant null.
对一个已知是 null 的值重复进行非空值判断
1 TaAutoDispatchTask task = null;
2 if (task != null) {
3 }
5.Questionable integer math
a.Computation of average could overflow
The code computes the average of two integers using either division or signed right shift, and then uses the result as the index of an array. If the values being averaged are very large, this can overflow (resulting in the computation of a negative average). Assuming that the result is intended to be nonnegative, you can use an unsigned right shift instead. In other words, rather that using (low+high)/2, use (low+high) >>> 1
This bug exists in many earlier implementations of binary search and merge sort. Martin Buchholz found and fixed it in the JDK libraries, and Joshua Bloch widely publicized the bug pattern.
计算平均值可能溢出
1 private int GetClockwiseNearestNode(Integer[] keys, int hashOfItem) {
2 int begin = 0;
3 int end = keys.length - 1;
4
5 if (keys[end] < hashOfItem || keys[0] > hashOfItem) {
6 return 0;
7 }
8
9 int mid = begin;
10 while ((end - begin) > 1) {
11 mid = (end + begin) / 2;
12 mid=(end&begin)+((end^begin)>>1);
13 if (keys[mid] >= hashOfItem) {
14 end = mid;
15 } else {
16 begin = mid;
17 }
18 }
19
20 return end;
21 }
6.Dead local store
a.Dead store to loccal variable
This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.
Note that Sun''s javac compiler often generates dead stores for final local variables. Because FindBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.
未用的局部变量,但有可能是误报
7.Casting from integer values
a.Result of integer multiplication cast to long
This code performs integer multiply and then converts the result to a long, as in:
long convertDaysToMilliseconds(int days) { return 1000*3600*24*days; }
If the multiplication is done using long arithmetic, you can avoid the possibility that the result will overflow. For example, you could fix the above code to:
long convertDaysToMilliseconds(int days) { return 1000L*3600*24*days; }
or
static final long MILLISECONDS_PER_DAY = 24L*3600*1000;
long convertDaysToMilliseconds(int days) { return days * MILLISECONDS_PER_DAY; }
整形乘法的结果转换为 long 型
1 /**
2 * 得到一个时间延后或前移几天的时间,nowdate为时间,delay为前移或后延的天数
3 */
4 public static String getNextDay(String nowdate, String delay) {
5 try {
6 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
7 String mdate = "";
8 Date d = strToDate(nowdate);
9 long myTime = (d.getTime() / 1000) + Integer.parseInt(delay) * 24L * 60 * 60;
10 d.setTime(myTime * 1000);
11 mdate = format.format(d);
12 return mdate;
13 } catch (Exception e) {
14 return "";
15 }
16 }
8.Switch case falls through
a.Switch statement found where default case is missing
This method contains a switch statement where default case is missing. Usually you need to provide a default case.
Because the analysis only looks at the generated bytecode, this warning can be incorrect triggered if the default case is at the end of the switch statement and the switch statement doesn''t contain break statements for other cases.
Switch 语句中没有包含 default
1 switch (params.getType()) {
2 case 0:
3 enumType = AutoScheduleBLL_zl.EnumType.waybillno;
4 break;
5 case 1:
6 enumType = AutoScheduleBLL_zl.EnumType.orderno;
7 break;
8 case 2:
9 enumType = AutoScheduleBLL_zl.EnumType.depot;
10 break;
11 default:
12 break;
13 }
9.Useless code
a.Useless object created
Our analysis shows that this object is useless. It''s created and modified, but its value never go outside of the method or produce any side-effect. Either there is a mistake and object was intended to be used or it can be removed.
This analysis rarely produces false-positives. Common false-positive cases include:
- This object used to implicitly throw some obscure exception.
未使用的对象应删除掉,不然有可能抛出异常
1 List<Object> vals2 = new ArrayList<>();
2 vals2.add("2018-05-05");
3 vals2.add("2018-05-09");
4 //vo2.setValues(vals2);
10.Misuse of static fields
a.Write to static field from instance method
This instance method writes to a static field. This is tricky to get correct if multiple instances are being manipulated, and generally bad practice.
静态对象不要多次实例化
11.Bad use of return value from method
a.Return value of method without side effect is ignored
This code calls a method and ignores the return value. However our analysis shows that the method (including its implementations in subclasses if any) does not produce any effect other than return value. Thus this call can be removed.
We are trying to reduce the false positives as much as possible, but in some cases this warning might be wrong. Common false-positive cases include:
- The method is designed to be overridden and produce a side effect in other projects which are out of the scope of the analysis.
- The method is called to trigger the class loading which may have a side effect.
- The method is called just to get some exception.
If you feel that our assumption is incorrect, you can use a @CheckReturnValue annotation to instruct FindBugs that ignoring the return value of this method is acceptable.
未使用的代码最好去掉
1 public List<TaSubdivisionBag> GetSubByWaybillNo(String listno) {
2 if (listno.length() == 0) {
3 new java.util.ArrayList<TaSubdivisionBag>();
4 }
5
6 String[] list = listno.split(",");
7 return taSubdivisionBagService.GetSubByWaybillNo(list);
8 }
12.Dubious method used
a.Thread passed where Runnable expected(严重)
A Thread object is passed as a parameter to a method where a Runnable is expected. This is rather unusual, and may indicate a logic error or cause unexpected behavior.
Thread 对象作为参数传递给期望 Runnable 的方法。 这很不寻常,可能表示存在逻辑错误或导致意外行为。
1 ExecutorService es = Executors.newCachedThreadPool();
2
3 for(TsPositionConfig entity : list) {
4 es.execute(new Thread(() -> {
5 OpenOrClose(entity);
6 }));
7 es.execute(new Runnable() {
8 @Override
9 public void run() {
10 OpenOrClose(entity);
11 }
12 });
13 }
14 es.shutdown();
13.Unwritten field
a.Unwritten public or protected field
No writes were seen to this public/protected field. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.
未被使用的 public 或 protected 属性,
14.Unread field
a.Unread public/proected field
This field is never read. The field is public or protected, so perhaps it is intended to be used with classes not seen as part of the analysis. If not, consider removing it from the class.
未被使用的 public 或 protected 属性
15.Unused field
a.Unused public or protected field
This field is never used. The field is public or protected, so perhaps it is intended to be used with classes not seen as part of the analysis. If not, consider removing it from the class.
未被使用的 public 或 protected 属性
四 Experimental (可试验代码 / 有潜在风险代码,主要是资源回收方面)
1.Unsatisfied obligation to clean up stream or resource
a.Method may fail to clean up stream or resource on checked exception
This method may fail to clean up (close, dispose of) a stream, database object, or other resource requiring an explicit cleanup operation.
In general, if a method opens a stream or other resource, the method should use a try/finally block to ensure that the stream or resource is cleaned up before the method returns.
This bug pattern is essentially the same as the OS_OPEN_STREAM and ODR_OPEN_DATABASE_RESOURCE bug patterns, but is based on a different (and hopefully better) static analysis technique. We are interested is getting feedback about the usefulness of this bug pattern. To send feedback, either:
send email to findbugs@cs.umd.edu
file a bug report: http://findbugs.sourceforge.net/reportingBugs.html
In particular, the false-positive suppression heuristics for this bug pattern have not been extensively tuned, so reports about false positives are helpful to us.
See Weimer and Necula, Finding and Preventing Run-Time Error Handling Mistakes, for a description of the analysis technique.
方法可能因为 checked exception 导致清理流或资源失败
1 public static String doPost(final Map<String, Object> strParams, final Map<String, File> fileParams) {
2 HttpURLConnection conn = null;
3 try {
4 URL url = new URL(Const.ErpfileUrl);
5 conn = (HttpURLConnection) url.openConnection();
6 conn.setRequestMethod("POST");
7 conn.setReadTimeout(TIME_OUT);
8 conn.setConnectTimeout(TIME_OUT);
9 conn.setDoOutput(true);
10 conn.setDoInput(true);
11 conn.setUseCaches(false);// Post 请求不能使用缓存
12 // 设置请求头参数
13 conn.setRequestProperty("Connection", "Keep-Alive");
14 conn.setRequestProperty("Charset", "UTF-8");
15 conn.setRequestProperty("Content-Type", CONTENT_TYPE + "; boundary=" + BOUNDARY);
16 /**
17 * 请求体
18 */
19 // 上传参数
20 DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
21 // getStrParams()为一个
22 dos.writeBytes(getStrParams(strParams).toString());
23 dos.flush();
24
25 // 文件上传
26 StringBuilder fileSb = new StringBuilder();
27 for (Map.Entry<String, File> fileEntry : fileParams.entrySet()) {
28 fileSb.append(PREFIX).append(BOUNDARY).append(LINE_END)
29 /**
30 * 这里重点注意: name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件 filename是文件的名字,包含后缀名的
31 * 比如:abc.png
32 */
33 .append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileEntry.getKey() + "\"" + LINE_END)
34 .append("Content-Type: */*" + LINE_END) // 此处的ContentType不同于 请求头 中Content-Type
35 .append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
36 dos.writeBytes(fileSb.toString());
37 dos.flush();
38 InputStream is = new FileInputStream(fileEntry.getValue());
39 try {
40 byte[] buffer = new byte[1024];
41 int len = 0;
42 while ((len = is.read(buffer)) != -1) {
43 dos.write(buffer, 0, len);
44 }
45 }
46 catch (Exception ex)
47 {
48 ex.printStackTrace();
49 }
50 finally {
51 is.close();
52 }
53 dos.writeBytes(LINE_END);
54 }
55 // 请求结束标志
56 dos.writeBytes(PREFIX + BOUNDARY + PREFIX + LINE_END);
57 dos.flush();
58 dos.close();
59
60 BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
61 StringBuilder response = new StringBuilder();
62 String line = null;
63 while ((line = reader.readLine()) != null) {
64 response.append(line);
65 }
66 return response.toString();
67 } catch (Exception e) {
68 e.printStackTrace();
69 } finally {
70 if (conn != null) {
71 conn.disconnect();
72 }
73 }
74
75 return "";
76 }
b.Method may fail to clean up stream or resource
This method may fail to clean up (close, dispose of) a stream, database object, or other resource requiring an explicit cleanup operation.
In general, if a method opens a stream or other resource, the method should use a try/finally block to ensure that the stream or resource is cleaned up before the method returns.
需显示的回收资源
1 public final void setFilePath(String value) {
2 FilePath = value;
3 if (StringUtils.isNotBlank(value)) {
4 File file = new File(value);
5 if (file.exists()) {
6 try {
7 InputStream is=new FileInputStream(file);
8 this.setStream(is);
9 is.close();
10 } catch (FileNotFoundException e) {
11 e.printStackTrace();
12 }
13 catch (IOException e)
14 {
15 e.printStackTrace();
16 }
17 }
18 }
19 }
五 Internationalization (国际化,当对字符串使用 upper 或 lowercase 方法,如果是国际的字符串,可能会不恰当的转换。)
1.Dubious method used
a.Reliance on default encoding
Found a call to a method which will perform a byte to String (or String to byte) conversion, and will assume that the default platform encoding is suitable. This will cause the application behaviour to vary between platforms. Use an alternative API and specify a charset name or Charset object explicitly.
不能随意信任默认字符编码,应显示处理
1 public final int Hash(String item) {
2
3 //ORIGINAL LINE: uint hash = Hash(Encoding.ASCII.GetBytes(item));
4 int hash = Hash(item.getBytes("UTF-8"));
5 return (int)hash;
6 }
六 Performance (性能问题代码,可能导致性能不佳的代码)
1.Dubious method used
a.Method invokes inefficient new String(String) constructor
Using the java.lang.String(String) constructor wastes memory because the object so constructed will be functionally indistinguishable from the String passed as a parameter. Just use the argument String directly.
方法调用了效率很低的 new String (String) 构造方法,只需直接使用 String
1 String regexUnion = new String("^(130|131|132|155|156|185|186|145|176)[0-9]{8}$");
b.Method invokes inefficient Boolean constructor;use Boolean.valueOf(...) instead
Creating new instances of java.lang.Boolean wastes memory, since Boolean objects are immutable and there are only two useful values of this type. Use the Boolean.valueOf() method (or Java 1.5 autoboxing) to create Boolean objects instead.
方法调用了低效的 Boolean 构造方法;使用 Boolean.valueOf (...) 代替
1 mDebugLog.append("\n").append(String.format("IsTelePhoneVoice:{0}", (new Boolean(mIsTelePhoneVoice)).toString()));
2 mDebugLog.append("\n").append(String.format("IsTelePhoneVoice:{0}", Boolean.valueOf(mIsTelePhoneVoice)));
c.Method invokes inefficient new String() constructor
Creating a new java.lang.String object using the no-argument constructor wastes memory because the object so created will be functionally indistinguishable from the empty string constant "". Java guarantees that identical string constants will be represented by the same String object. Therefore, you should just use the empty string constant directly.
使用了 new String ()
1 tA_RecordsChangeLogBLL.AddUpdateLog(people.getPeopleNo(), new String()"", peopleModelAfter,
2 TaRecordsChangeLog.EnmuTableType.TB_People.getValue(), "整车业务", "");
2.Inefficient Map Iterator
a.Inefficient use of keySet iterator instead of entrySet iterator
This method accesses the value of a Map entry, using a key that was retrieved from a keySet iterator. It is more efficient to use an iterator on the entrySet of the map, to avoid the Map.get(key) lookup.
此方法使用从 keySet 迭代器检索的键访问 Map 条目的值。 在 map 的 entrySet 上使用迭代器更有效,以避免 Map.get(键)查找。
1 public List<GetDriverScoreDetailsModel> GetDriverScoreDetails(GetDriverScoreDetailsRequest request,Out<Integer> rowTotal) {
2 rowTotal.setData(0);
3 if ((StringUtils.isBlank(request.getbeg_createtime()) && !StringUtils.isBlank(request.getend_createtime()))
4 || (StringUtils.isBlank(request.getend_createtime()) && !StringUtils.isBlank(request.getbeg_createtime()))) {
5 throw new Exception("开始任务时间和结束任务时间必须同时输入或同时不输入!");
6 }
7 Date dt_beg_tasktime = null;
8 try {
9 dt_beg_tasktime = TimeUtils.format(request.getbeg_createtime(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
10 } catch (Exception e) {
11 dt_beg_tasktime = null;
12 }
13
14 Date dt_end_tasktime = null;
15 try {
16 dt_end_tasktime = TimeUtils.format(request.getend_createtime(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
17 } catch (Exception e) {
18 dt_end_tasktime = null;
19 }
20
21 if(StringUtils.isBlank(request.getbeg_createtime()) || StringUtils.isBlank(request.getend_createtime())) {
22 throw new Exception("开始任务时间或结束任务时间不能为空!");
23 }else if ((!StringUtils.isBlank(request.getbeg_createtime()) && dt_beg_tasktime == null)
24 || (!StringUtils.isBlank(request.getend_createtime()) && dt_end_tasktime == null)) {
25 throw new Exception("开始任务时间或结束任务时间格式不正确!");
26 } else if (dt_beg_tasktime.after(dt_end_tasktime)) {
27 throw new Exception("开始任务时间不能大于结束任务时间!");
28 }
29
30
31 List<TaDriveScoreDetails> lstDriverScore =taDriveScoreDetailsService.GetDriverScoreDetails(request, rowTotal);
32 if (lstDriverScore == null) {
33 return null;
34 }
35
36 lstDriverScore.stream().filter(d -> d.getIsDel() != null && d.getIsDel().intValue() == 0).collect(Collectors.toList());
37
38 Map<String, List<TaDriveScoreDetails>> detailGroupBy = new HashMap<>();
39 for (TaDriveScoreDetails scoreDetails : lstDriverScore) {
40 String key = scoreDetails.getCol002() + "-" + scoreDetails.getCol011() + "-" + scoreDetails.getCol012() + "-" + scoreDetails.getCol003();
41 List<TaDriveScoreDetails> temp = null;
42 if (detailGroupBy.containsKey(key)) {
43 temp = detailGroupBy.get(key);
44 } else {
45 temp = new ArrayList<>();
46 }
47 temp.add(scoreDetails);
48 detailGroupBy.put(key, temp);
49 }
50 List<GetDriverScoreDetailsModel> listModel = new ArrayList<GetDriverScoreDetailsModel>();
51 Iterator<Map.Entry<String,List<TaDriveScoreDetails>>> it=detailGroupBy.entrySet().iterator();
52 while (it.hasNext())
53 {
54 Map.Entry<String,List<TaDriveScoreDetails>> me=it.next();
55 String key=me.getKey();
56 List<TaDriveScoreDetails> list=me.getValue();
57 for (String key : detailGroupBy.keySet()) {
58 List<TaDriveScoreDetails> list = detailGroupBy.get(key);
59 if (list == null || list.size() == 0)
60 continue;
61
62 GetDriverScoreDetailsModel model = new GetDriverScoreDetailsModel();
63 String[] keyarray = key.split("-");
64 model.setDriver_name(keyarray[0]);
65 model.setPosition_name(keyarray[1]);
66 model.setDept(keyarray[2]);
67 model.setTask_no(keyarray[3]);
68
69 try {
70 String taskTime = TimeUtils.parseDateToStr(list.get(0).getCol004(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
71 model.setTask_time(taskTime);
72 } catch (Exception e) {
73 model.setTask_time(null);
74 }
75
76 try {
77 String advanceTime = TimeUtils.parseDateToStr(list.get(0).getCol005(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
78 model.setSign_time(advanceTime);
79 } catch (Exception e) {
80 model.setSign_time(null);
81 }
82
83 try {
84 String createtime = TimeUtils.parseDateToStr(list.get(0).getCreateTime(), TimeUtils.YYYY_MM_DD_HH_MM_SS);
85 model.setCreatetime(createtime);
86 } catch (Exception e) {
87 model.setCreatetime(null);
88 }
89 model.setIs_late((list.get(0).getCol007() != null && list.get(0).getCol007().intValue() == 1) ? "是" : "否");
90
91 Map<Integer, DoubleSummaryStatistics> collect = list.stream()
92 .collect(Collectors.groupingBy(TaDriveScoreDetails::getCol038, Collectors.summarizingDouble(TaDriveScoreDetails::getCol008)));
93
94 model.setReminder_penalty(collect.get(ScoreType.UrgeScore.code) != null ? collect.get(ScoreType.UrgeScore.code).getSum() + "" : "");
95 model.setVoice_penalty(collect.get(ScoreType.TelVoiceScore.code) != null ? collect.get(ScoreType.TelVoiceScore.code).getSum() + "" : "");
96 model.setRefuse_penalty(
97 collect.get(ScoreType.RefuseOrderScore.code) != null ? collect.get(ScoreType.RefuseOrderScore.code).getSum() + "" : "");
98 model.setBelate_penalty(
99 collect.get(ScoreType.BeLateVoiceScore.code) != null ? collect.get(ScoreType.BeLateVoiceScore.code).getSum() + "" : "");
100 model.setTimeout_penalty(
101 collect.get(ScoreType.TimeOutVoiceScore.code) != null ? collect.get(ScoreType.TimeOutVoiceScore.code).getSum() + "" : "");
102
103 listModel.add(model);
104 }
105 return listModel;
106 }
3.String concatenation in loop using + operator
a.Method concatenates strings using + in a loop
The method seems to be building a String using concatenation in a loop. In each iteration, the String is converted to a StringBuffer/StringBuilder, appended to, and converted back to a String. This can lead to a cost quadratic in the number of iterations, as the growing string is recopied in each iteration.
Better performance can be obtained by using a StringBuffer (or StringBuilder in Java 1.5) explicitly.
For example:
// This is bad
String s = "";
for (int i = 0; i < field.length; ++i) {
s = s + field[i];
}
// This is better
StringBuffer buf = new StringBuffer();
for (int i = 0; i < field.length; ++i) {
buf.append(field[i]);
}
String s = buf.toString();
loop 里面应该使用 StringBuffer 替换 + 号
1 /**
2 * 返回一个随机数
3 *
4 * @param i
5 * @return
6 */
7 public static String getRandom(int i) {
8 Random jjj = new Random();
9 // int suiJiShu = jjj.nextInt(9);
10 if (i == 0)
11 return "";
12 String jj = "";
13 StringBuffer jj=new StringBuffer();
14 for (int k = 0; k < i; k++) {
15 jj = jj + jjj.nextInt(9);
16 jj.append(jjj.nextInt(9));
17 }
18 return jj;
19 }
4.Questionable Boxing of primitive value
a.Boxed value is unboxed and then immediately reboxed
A boxed value is unboxed and then immediately reboxed.
装箱的值被拆箱,然后立刻重新装箱了(三元运算符两个分支的返回类型保持一致)
1 public final TaCustomerCharacter Create(TaMonthProfit profit) {
2 TaCustomerCharacter customer = new TaCustomerCharacter();
3 customer.setId(Util.CreateDbGUID());
4 customer.setCreateTime(new Date());
5 customer.setLastUpdateTime(new Date());
6 customer.setCompanyName(profit.getCompanyName());
7 customer.setCompanyNo(profit.getCompanyNo());
8 customer.setCol007(profit.getSumProfit());
9 customer.setCol008(profit.getGoodTimeRate() == 0 ? 100 : profit.getGoodTimeRate() );
10 customer.setCol008(profit.getGoodTimeRate() == 0 ? Double.valueOf(100) : profit.getGoodTimeRate() );
11 customer.setCol009(profit.getThisDayRate() == 0 ?100 : profit.getThisDayRate());
12 customer.setCol009(profit.getThisDayRate() == 0 ? Double.valueOf(100) : profit.getThisDayRate());
13 return customer;
14 }
b.Boxing/unboxing to parse a pimitive
A boxed primitive is created from a String, just to extract the unboxed primitive value. It is more efficient to just call the static parseXXX method.
使用 parseXXX 效率会更高点
1 private void GetLogisticsList(Map<String, Object> dic, String url, List<TaLogisticsXd> response) {
2 String res = OpenApi.request(url, dic);
3 if (StringUtils.isNotBlank(res)) {
4 KyeResponse<ResponseResult<LogisticsXDResponseModel>> responseModel = JSONObject.parseObject(res,
5 new TypeReference<Response<ResponseResult<LogisticsXDResponseModel>>>() {
6 });
7 if (responseModel.isFail())
8 return;
9 if (responseModel.getData() == null || responseModel.getData().getRows() == null || responseModel.getData().getRows().size() == 0)
10 return;
11
12 List<LogisticsXDResponseModel> list = JSON.parseArray(JSON.toJSONString(responseModel.getData().getRows()),LogisticsXDResponseModel.class);
13 for (LogisticsXDResponseModel model : list) {
14 response.add(LogisticsXDConverter.ToEntity(model));
15 }
16
17 if (responseModel.getData().getPage() < responseModel.getData().getPageTotal()) {
18 dic.put("page", Integer.valueOf(dic.get("page") + "") + 1); // 下一页递归
19 dic.put("page", Integer.parseInt(dic.get("page").toString()) + 1); // 下一页递归
20 GetLogisticsList(dic, url, response);
21 }
22 }
23 }
c.Methiod allocates a boxed primitive just to call toString
A boxed primitive is allocated just to call toString(). It is more effective to just use the static form of toString which takes the primitive value. So,
Replace...
With this...
new Integer(1).toString()
Integer.toString(1)
new Long(1).toString()
Long.toString(1)
new Float(1.0).toString()
Float.toString(1.0)
new Double(1.0).toString()
Double.toString(1.0)
new Byte(1).toString()
Byte.toString(1)
new Short(1).toString()
Short.toString(1)
new Boolean(true).toString()
Boolean.toString(true)
使用.toString 效率更高
1 if ((new Integer(TaExceptionTask.ExceptionType.Refuse.code)).toString()
2 if ((Integer.toString(TaExceptionTask.ExceptionType.Refuse.code))
3 .equals(verExReq.getExceptionType())) {
4 status = TaExceptionTask.EnumVerifyStatus.NoPenalty;
5 iFlag = 2;
6 logType = 0;
7 }
d.Method invokes inefficient Number constructor;use static valueOf instead
Using new Integer(int) is guaranteed to always result in a new object whereas Integer.valueOf(int) allows caching of values to be done by the compiler, class library, or JVM. Using of cached values avoids object allocation and the code will be faster.
Values between -128 and 127 are guaranteed to have corresponding cached instances and using valueOf is approximately 3.5 times faster than using constructor. For values outside the constant range the performance of both styles is the same.
Unless the class must be compatible with JVMs predating Java 1.5, use either autoboxing or the valueOf() method when creating instances of Long, Integer, Short, Character, and Byte.
使用 new Integer (int) 会产生新的对象,使用静态 Integer.valueOf (int) 会使用缓存避免对象分配,valueOf 更加高效,
1 model.setExceptionStatus(exTask.getExceptionUploadStatus() == 0 ? ""
2 : (new Integer(exTask.getExceptionUploadStatus()))+"");
3 model.setExceptionStatus(exTask.getExceptionUploadStatus() == 0 ? ""
4 : (Integer.toString(exTask.getExceptionUploadStatus())));
5.Inner class could be made static
a.Should be a static inner class
This class is an inner class, but does not use its embedded reference to the object which created it. This reference makes the instances of the class larger, and may keep the reference to the creator object alive longer than necessary. If possible, the class should be made static.
应该是一个静态内部类
1 private static class IntegerToEnum<T extends IntToEnumConverter> implements Converter<String, T> {
2
3 private final T[] values;
4
5 public IntegerToEnum(Class<T> targetType) {
6 values = targetType.getEnumConstants();
7 }
8
9 @Override
10 public T convert(String source) {
11 for (T t : values) {
12 if (((BaseEnum) t).getValue() == Integer.parseInt(source)) {
13 return t;
14 }
15 }
16 return null;
17 }
18 }
6.Unread field should be static
a.Unread field: should this field be static
This class contains an instance final field that is initialized to a compile-time static value. Consider making the field static.
未读取的属性:这个属性是否应该是 static 的?
1 private final static String defaultMapperName = "Converter";
7.Unread field
a.Unread field
This field is never read. Consider removing it from the class.
未使用的属性,建议移除
七 Malicious code vulnerability (如果公开会被恶意攻击的代码)
1.Mutable static field
a.Field isn''t final but should be
This static field public but not final, and could be changed by malicious code or by accident from another package. The field could be made final to avoid this vulnerability.
应该使用 final 修饰
b.Public static method may expose internal representation
A public static method returns a reference to an array that is part of the static state of the class. Any code that calls this method can freely modify the underlying array. One fix is to return a copy of the array.
Public static 方法可能因为返回了一个数组而暴露内部实现,可返回数组克隆
1 private static TaTask.EnumStatus[] privateNoAllowRedo;
2 public static TaTask.EnumStatus[] getNoAllowRedo()
3 {
4 return privateNoAllowRedo.clone();
5 }
c.Field should be package protected
A mutable static field could be changed by malicious code or by accident. The field could be made package protected to avoid this vulnerability.
属性应该是 package protected
d.Field is a mutable collection
A mutable collection instance is assigned to a final static field, thus can be changed by malicious code or by accident from another package. Consider wrapping this field into Collections.unmodifiableSet/List/Map/etc. to avoid this vulnerability.
如何设置一个 static 不可变集合,以及非静态的 setter 调用静态的 setter 方法给静态成员变量赋值。
1 public static final java.util.HashMap<String, Integer> ProvinceDicData = new java.util.HashMap<String, Integer>();
2 static {
3 ProvinceDicData.put("津", 101);
4 ProvinceDicData.put("冀", 102);
5 ProvinceDicData.put("晋", 103);
6 ProvinceDicData.put("蒙", 104);
7 ProvinceDicData.put("辽", 105);
8 ProvinceDicData.put("吉", 106);
9 ProvinceDicData.put("黑", 107);
10 ProvinceDicData.put("沪", 108);
11 ProvinceDicData.put("苏", 109);
12 ProvinceDicData.put("浙", 110);
13 ProvinceDicData.put("皖", 111);
14 ProvinceDicData.put("闽", 112);
15 ProvinceDicData.put("赣", 113);
16 ProvinceDicData.put("鲁", 114);
17 ProvinceDicData.put("豫", 115);
18 ProvinceDicData.put("鄂", 116);
19 ProvinceDicData.put("湘", 117);
20 ProvinceDicData.put("粤", 118);
21 ProvinceDicData.put("桂", 119);
22 ProvinceDicData.put("琼", 120);
23 ProvinceDicData.put("渝", 121);
24 ProvinceDicData.put("川", 122);
25 ProvinceDicData.put("贵", 123);
26 ProvinceDicData.put("滇", 124);
27 ProvinceDicData.put("藏", 125);
28 ProvinceDicData.put("陕", 126);
29 ProvinceDicData.put("甘", 127);
30 ProvinceDicData.put("青", 128);
31 ProvinceDicData.put("宁", 129);
32 ProvinceDicData.put("新", 130);
33 ProvinceDicData.put("台", 131);
34 ProvinceDicData.put("港", 132);
35 ProvinceDicData.put("澳", 133);
36 ProvinceDicData.put("京", 134);
37 ProvinceDicData.put("云", 135);
38 ProvinceDicData.put("蜀", 136);
39 ProvinceDicData.put("黔", 137);
40 ProvinceDicData.put("秦", 138);
41 ProvinceDicData.put("陇", 139);
42 }
43 public static java.util.Map<String, Integer> ProvinceDicData;
44 public void setProvinceDicData(java.util.Map<String, Integer> map){this.setProvinceDicDataValue(map);}
45 public static void setProvinceDicDataValue(java.util.Map<String, Integer> map)
46 {
47 Const.ProvinceDicData=map;
48 }
49 {
50 java.util.Map<String,Integer> map= Maps.newHashMap();
51 map.put("津", 101);
52 map.put("冀", 102);
53 map.put("晋", 103);
54 map.put("蒙", 104);
55 map.put("辽", 105);
56 map.put("吉", 106);
57 map.put("黑", 107);
58 map.put("沪", 108);
59 map.put("苏", 109);
60 map.put("浙", 110);
61 map.put("皖", 111);
62 map.put("闽", 112);
63 map.put("赣", 113);
64 map.put("鲁", 114);
65 map.put("豫", 115);
66 map.put("鄂", 116);
67 map.put("湘", 117);
68 map.put("粤", 118);
69 map.put("桂", 119);
70 map.put("琼", 120);
71 map.put("渝", 121);
72 map.put("川", 122);
73 map.put("贵", 123);
74 map.put("滇", 124);
75 map.put("藏", 125);
76 map.put("陕", 126);
77 map.put("甘", 127);
78 map.put("青", 128);
79 map.put("宁", 129);
80 map.put("新", 130);
81 map.put("台", 131);
82 map.put("港", 132);
83 map.put("澳", 133);
84 map.put("京", 134);
85 map.put("云", 135);
86 map.put("蜀", 136);
87 map.put("黔", 137);
88 map.put("秦", 138);
89 map.put("陇", 139);
90 this.setProvinceDicData(Collections.unmodifiableMap(map));
91 }
e.Field is a mutable collection which should be package protected
A mutable collection instance is assigned to a final static field, thus can be changed by malicious code or by accident from another package. The field could be made package protected to avoid this vulnerability. Alternatively you may wrap this field into Collections.unmodifiableSet/List/Map/etc. to avoid this vulnerability.
与 d 一致处理
2.Storing reference to mutable object
a.May expose internal representation by incorporating reference to mutable object(严重)
This code stores a reference to an externally mutable object into the internal representation of the object. If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Storing a copy of the object is better approach in many situations.
此代码将对外部可变对象的引用存储到对象的内部表示中。即外部代码值改变会引起对象值改变,涉及到引用传递值的问题。
测试代码:
1 LogisticsXDDispatchMessage2 logisticsXDDispatchMessage2=new LogisticsXDDispatchMessage2();
2 java.util.Date dt= new java.util.Date();
3 logisticsXDDispatchMessage2.setOrderTime(dt);
4 System.out.printf(logisticsXDDispatchMessage2.getOrderTime().toString()+"%n");
5 dt.setMonth(1);
6 System.out.printf(logisticsXDDispatchMessage2.getOrderTime().toString());
输出:
1 Fri Apr 19 16:01:18 CST 2019
2 Tue Feb 19 16:01:18 CST 2019
1 public class LogisticsXDDispatchMessage2 implements Serializable {
2 @JsonFormat(pattern="yyyy-MM-dd HH:mm:dd")
3 private Date orderTime;
4 public void setOrderTime(Date orderTime) {
5 this.orderTime = (Date) orderTime.clone();
6 }
7 public Date getOrderTime() {
8 return (Date) orderTime.clone();
9 }
10 }
3.Method returning array may expose internal representation
a.May expose internal representation by returning reference to mutable object
Returning a reference to a mutable object value stored in one of the object''s fields exposes the internal representation of the object. If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Returning a new copy of the object is better approach in many situations.
同 2 处理方式一致
参考:https://my.oschina.net/bairrfhoinn/blog/156200
Debian 11.2 发布,修复 Bug 及安全性问题
Debian 11.2 发布了,作为 Debian 11 “Bullseye” 的第二个版本,它带来了一系列的 bug 修复和安全问题的完善,其中最为引人注目的更新项,是对沸沸扬扬的 “Log4j 漏洞” 问题的修复:DSA-5020 、DSA-5022 。
除此之外,此版本还有大量安全相关内容,如对 curl 的 “从 curl-config 中删除 - file-prefix-map
,以修复 libcurl4-gnutls-dev 在 multiarch 下的可协同安装性”,如 wget 的” 修复 wget ,以处理 32 位系统上超过 2GB 的下载”,以及其他...
完整版的更新列表可在公告原文中查看。
findbugs
findbugs 错误总结
本篇是从别人那找到的,为了让我回头查看 findbugs 错误怎么解决而保存的
有很多问题其实挺隐晦的,比如第三条。还有人会使用 == 来判断常量字符串和 String 类型是否相等,这个就是基础不牢的缘故了。
记得把 findbugs 尽量清零哦。
1. NP_NULL_ON_SOME_PATH_EXCEPTION
类型
必改项
描述
A reference value which is null on some exception control path is dereferenced here. This may lead to aNullPointerException when the code is executed. Note that because FindBugs currently does not prune infeasible exception paths, this may be a false warning.
代码调用时,遇到异常分支,可能造成一个对象没有获得赋值依旧保持 NULL 空指针。接下来如果对这个对象有引用,可能造成 NullPointerException 空指针异常。
案例
private voidtest_NP_NULL_ON_SOME_PATH_EXCEPTION(String name, String
pass){
User user = null;
int nport = 10;
try{
user = checkUser(name, pass);
if (user == null){
System.out.println(" 密码错误 ");
close();
return ;
}
}
catch (SQLException e){
e.printStackTrace();
}
user.setPort(nport); // 这端代码有 NP_NULL_ON_SOME_PATH_EXCEPTION
}
代码分析:这里 User 对象是在 try 块中赋值的, 但是由于 checkUser 方法赋值失败造成异常,导致 User 对象为空后, 直接转入异常处理模块执行 e.printStackTrace(); 此时并没有返回,接下来执行 user.setPort(nport) 时, 必然造成空指针。
案例二:
md = null;
try {
md = MessageDigest.getInstance("SHA-256");
md.update(bt);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();// script1
}
byte[] digest = md.digest();// script2
解决方法
案例一:根据代码逻辑实际情况采取解决方法, 在异常情况下考虑好分支路径
案例二:bug 出现在 script2 处,在 script1 处处理相应的 exception 即可,如 throw 或 return;
2. NP_NULL_ON_SOME_PATH
类型
必改项
描述
There is a branch of statement that,if executed, guarantees that a null value will be dereferenced, which would generate aNullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can''t ever be executed; deciding that is beyond the ability of FindBugs.
对象可能没有重新赋值
案例
如在 JDBC 编程时候,在关闭 ResultSet 时候 (rs.close()),经常会出现这个 bug,
解决方法
解决办法很容易想到,判断是否为 null 或
使用 try...catch...finally。
3. EC_UNRELATED_CLASS_AND_INTERFACE
类型
必改项
描述
This method calls equals(Object) on two references, one of which is a class and the other an interface, where neither the class nor any of its non-abstract subclasses implement the interface. Therefore, the objects being compared are unlikely to be members of the same class at runtime (unless some application classes were not analyzed, or dynamic class loading can occur at runtime). According to the contract of equals(), objects of different classes should always compare as unequal; therefore, according to the contract defined by java.lang.Object.equals(Object), the result of this comparison will always be false at runtime.
使用 equals 方法比较不相关的类和接口
案例
StringBuilder builder = new StringBuilder("nihao");
String string = "nihao";
builder.equals(string);
解决方法
调用 equals() 比较不同的类型。
此方法调用相当于两个不同的类类型的引用,没有共同的子类(对象)。
因此,所比较的对象是不太可能在运行时相同的类成员(除非一些
应用类没有分析或动态类加载可以发生在运行时)。据
equals() 的规则,不同类的对象应始终比较不平等,因此,根据
由 java.lang.Object.equals 定义的合同(对象),FALSE 将永远是比较的结果
在运行时错误。
4. UG_SYNC_SET_UNSYNC_GET
类型
必改项
描述
This class contains similarly-named get and set methods where the set method is synchronized and the get method is not. This may result in incorrect behavior at runtime, as callers of the get method will not necessarily see a consistent state for the object. The get method should be made synchronized.
这个类包含类似命名的 get 和 set 方法。在 set 方法是同步方法和 get 方法是非同步方法。这可能会导致在运行时的不正确行为,因为调用的 get 方法不一定返回对象一致状态。 GET 方法应该同步。
案例
解决方法
5. DLS_DEAD_LOCAL_STORE
类型
必改项
描述
This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.
Note that Sun''s javac compiler often generates dead stores for final local variables. Because FindBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.
该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。
案例
案例二:
String abc = "abc";
String xyz = new String("");
xyz = abc;
System.out.println(xyz);
解决方法
删除未使用的本地变量
案例二:
因为 String xyz = new String("");
这一句执行 3 个动作:
1) 创建一个引用 xyz
2) 创建一个 String 对象
3) 把 String 的引用赋值给 xyz
其中,后面两个动作是多余的,因为后面的程序中你没有使用这个新建的 String 对象,而是重新给 xyz 赋值,
xyz = abc; 所以,只需要 String xyz = abc; 就可以了
6. RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE
类型
选改项
描述
A value is checked here to see whether it is null, but this value can''t be null because it was previously dereferenced and if it were null a null pointer exception would have occurred at the earlier dereference. Essentially, this code and the previous dereference disagree as to whether this value is allowed to be null. Either the check is redundant or the previous dereference is erroneous.
案例
出现该 bug 有两种情况:多余的 null 检查;前边没有 null 值检查的。
比如:我们经常会这个使用 ActionForm,
String clazzId = request.getParameter("clazzId");// script1
studentForm.setClazzID(clazzId);// script2
往往会在 script2 会出现该错误,因为在 script1 处未检查 clazzId 是否为 null 才导致的。
修改为:
if(clazzId != null) {
studentForm.setClazzID(clazzId);
}
解决方法
在设置使用 clazzId 之前先判断其是否为 null。
7. ES_COMPARING_STRINGS_WITH_EQ
类型
必改项
描述
This code comparesjava.lang.String objects for reference equality using the == or != operators. Unless both strings are either constants in a source file, or have been interned using the String.intern() method, the same string value may be represented by two different String objects. Consider using theequals(Object) method instead.
用 == 或者!= 去比较 String 类型的对象
案例
String str1 = "java";
String str2 = "java";
System.out.print(str1==str2);
成果:true(二者都为常量)
String str1 = new String("java");
String str2 = new String("java");
System.out.print(str1==str2);
成果:false(二者为对象)
String str1 = "java";
String str2 = "blog";
String s = str1+str2;
System.out.print(s=="javablog");
成果:false(s 不为常量,为对象)
String s1 = "java";
String s2 = new String("java");
System.out.print(s1.intern()==s2.intern());
成果:true
解决方法
String 对象进行比较的时候:只有两种情况可以使用 == or !=,这两种情况是;仅当两个字符串在源文件中都是常量或者是调用 String.intern() 方法,使用 String 的规范化表示形式来进行比较 , 如果不是这两中情况的话推荐使用.equals(object) 方式
8. NP_NULL_PARAM_DEREF
类型
必改项
描述
This method call passes a null value for a nonnull method parameter. Either the parameter is annotated as a parameter that should always be nonnull, or analysis has shown that it will always be dereferenced.
这种方法调用传递一个空值给非空参数。,要这个参明确注释它是非空参数,要么经过分析得出它总是会被引用不可能为空。
案例
int FunctionOne(int x,int y=0,int z=0,int w=0);
我们要给 z 传递整型值 8,作如下调用:
FunctionOne(8);
显然,编译器无法确定这个 8 到底要传递给哪个参数。为了达到我们的目的,必须这样调用:
FunctionOne(0,0,8);
这是 x 被传递了 0,y 被传递了 0,z 被传递了 8
解决方法
我们可以赋予函数参数默认值。
所谓默认值就是在调用时,可以不写某些参数的值,编译器会自动把默认值传递给调用语句中。默认值一般在函数声明中设置;
9. UWF_UNWRITTEN_FIELD
类型
必改项
描述
This field is never written. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.
此字段是永远不会写入值。所有读取将返回默认值。检查错误(如果它被初始化?),如果它确实没有用就删除掉。
案例
解决方法
10. NP_TOSTRING_COULD_RETURN_NULL
类型
必改项
描述
This toString method seems to return null in some circumstances. A liberal reading of the spec could be interpreted as allowing this, but it is probably a bad idea and could cause other code to break. Return the empty string or some other appropriate string rather than null.
toString 方法可能返回 null
案例
解决方法
11. MF_CLASS_MASKS_FIELD
类型
必改项
描述
This class defines a field with the same name as a visible instance field in a superclass. This is confusing, and may indicate an error if methods update or access one of the fields when they wanted the other.
子类中定义了和父类中同名的字段。在调用时会出错
案例
解决方法
12. NS_DANGEROUS_NON_SHORT_CIRCUIT
类型
必改项
描述
This code seems to be using non-short-circuit logic (e.g., & or |) rather than short-circuit logic (&& or ||). In addition, it seem possible that, depending on the value of the left hand side, you might not want to evaluate the right hand side (because it would have side effects, could cause an exception or could be expensive.
Non-short-circuit logic causes both sides of the expression to be evaluated even when the result can be inferred from knowing the left-hand side. This can be less efficient and can result in errors if the left-hand side guards cases when evaluating the right-hand side can generate an error.
See theJava Language Specification for details
代码中使用(& or |)代替(&& or ||)操作,这会造成潜在的危险
案例
缺陷详解:解释一下短路与非短路的区别:
(1)短路运算(short-circuit)
逻辑与(&&):如果左操作数结果为 true,则继续计算右操作数;如果左操作数结果为 false
,则对右操作数的运算已经没有必要,直接返回结果 false,忽略右操作运算。
逻辑或(||):如果左操作数结果为 false,则继续计算右操作数;如果左操作数结果为 true
,则对右操作数的运算已经没有必要,直接返回结果 true,忽略右操作运算。
正确地使用短路运算符,就可以写出节省时间、提高效率的代码。
(2)非短路运算(non-short-circuit)
逻辑与(&)、逻辑或(|):不管左操作数的运算结果如何,都一律计算右边的操作数。
我们回放的代码使用的是非短路与(&),也就是不管左边的 sr !=null
的结果如何,都一律运算右边的 sr.getInt(0) == 0,那如果遇到 sr 为 null
值的情况,则一样也会调用到 sr.getInt(0),显然就会出现空指针异常。
解决方法
解决这个问题的最好选择是改用短路运算与(&&)。
SysDataSet sds = con.csCommonSP("P_KMS_GETORIGINALFILETREE");
SysRecord sr = sds != null ? sds.getParamSet() : null;
rs = (sr != null&& sr.getInt(0) == 0) ? sds.getResultSet() :null;
13. HE_EQUALS_USE_HASHCODE
类型
必改项
描述
This class overrides equals(Object), but does not override hashCode(), and inherits the implementation of hashCode() from java.lang.Object (which returns the identity hash code, an arbitrary value assigned to the object by the VM). Therefore, the class is very likely to violate the invariant that equal objects must have equal hashcodes.
If you don''t think instances of this class will ever be inserted into a HashMap/HashTable, the recommended hashCode implementation to use is:
public int hashCode() {
assert false : "hashCode not designed";
return 42; // any arbitrary constant will do
}
一个类覆写了 equals 方法,没有覆写 hashCode 方法,使用了 Object 对象的 hashCode 方法
案例
解决方法
14. NP_EQUALS_SHOULD_HANDLE_NULL_ARGUMENT
类型
必改项
描述
This implementation of equals(Object) violates the contract defined by java.lang.Object.equals() because it does not check for null being passed as the argument. All equals() methods should return false if passed a null value.
变量调用 equals 方法时没有进行是否为 null 的判断
案例
解决方法
15. SE_BAD_FIELD
类型
必改项
描述
This Serializable class defines a non-primitive instance field which is neither transient, Serializable, orjava.lang.Object, and does not appear to implement theExternalizable interface or thereadObject() andwriteObject() methods. Objects of this class will not be deserialized correctly if a non-Serializable object is stored in this field.
序列化的类定义了一个非原生实例对象,这个对象是不可序列化的或非 java 对象,而且没有添加 transient 关键字,没有实现 Externalizable 接口或没有添加 readObject() 和 writeObject() 方法,那么这个类的对象将不能正确的反序列化。
案例
示例代码:
publicclassMytest implements Serializable {
private ThreadmThread;
protected FileOutputStreamoutputStream ;
// 这两个变量会提示 defines non-transient non-serializable instance field finoutStream
private Stringstr;
private Stringstr1;
privateinti;
}
解决方法
解决方法:
1:给对象加上 transient 关键字,对该象将不会被序列化保存和恢复。
publicclassMytest implements Serializable{
privatetransient ThreadmThread;
protectedtransient FileOutputStreamoutputStream;
private Stringstr;
private Stringstr1;
privateinti;
}
2:实现 Externalizable 接口代替 Serializable 接口,对序列化过程进行完全自主控制。Externalizable 没有默认序列化机制,我们需要在 writeExternal() 方法中将希望被序列化的对象的信息写入,在 readExternal() 中将其恢复,并且 writeObject() 方法与 readObject() 方法中保存和恢复对象的顺序必须相同。
publicclass Mytestimplements Externalizable{
private ThreadmThread;
protected FileOutputStreamfoutputStream;
private Stringstr;
private Stringstr1;
privateinti;
@Override
publicvoid readExternal(ObjectInput arg0)throws IOException,
ClassNotFoundException {
str=(String) arg0.readObject();
str1=(String) arg0.readObject();
i= arg0.readInt();
}
@Override
publicvoid writeExternal(ObjectOutput arg0)throws IOException{
arg0.writeObject(str);
arg0.writeObject(str1);
arg0.writeInt(i);
}
}
3:添加 writeObject() 和 readObject() 方法替代 Externalizable,对序列化过程进行自主控制。注意是 “添加” 不是 “复写” 或 “实现”,类型必须为 private,同样 writeObject() 方法与 readObject() 方法中保存和恢复对象的顺序必须相同。
publicclassMytest implements Serializable{
private ThreadmThread;
protected FileOutputStreamfoutputStream;
private Stringstr;
private Stringstr1;
privateinti;
privatevoid writeObject(ObjectOutputStream outputStream)throws IOException {
outputStream.writeObject(str);
outputStream.writeObject(str1);
outputStream.writeInt(i);
}
privatevoid readObject(ObjectInputStream inputStream)throws IOException,ClassNotFoundException {
str=(String) inputStream.readObject();
str1=(String) inputStream.readObject();
i= inputStream.readInt();
}
}
16. NP_UNWRITTEN_FIELD
类型
必改项
描述
The program is dereferencing a field that does not seem to ever have a non-null value written to it. Unless the field is initialized via some mechanism not seen by the analysis, dereferencing this value will generate a null pointer exception.
程序中引用一变量,没有一个可见的机制将一个非空的值赋给它,引用时需要对其进行判断(是否有一不可见的机制对其进行了初始化)不然会空指针异常。
案例
privatestaticArrayList<String> paramList =null;
publicArrayList checkValue(String str1) {
paramList.clear();
returnparamList;
}
// 调用 clear() 只是清除 list 内容并不会使 list 报空指针异常,但是 list 为 null 时,就会报空指针异常了。
解决方法
引用前进行判空
privatestatic ArrayList<String>paramList =null;
publicArrayList checkValue(String str1) {
if (null!=paramList) {
paramList.clear();
}
returnparamList;
}
17. UWF_NULL_FIELD
类型
必改项
描述
All writes to this field are of the constant value null, and thus all reads of the field will return null. Check for errors, or remove it if it is useless.
字段的值总是为 null 值,所有读取该字段的值都为 null。检查错误,如果它确实没有用就删除掉。
案例
privatestatic ArrayList<String>paramList =null;
public ArrayList<String> returnList(ArrayList mList) {
returnmList;
}
注:程序中无其函数对 paramList 进行赋值,或一直赋 null 值。
解决方法
1、对 paramList 进行正确赋值。
2、如果 paramList 没有用就删掉。
18. IM_BAD_CHECK_FOR_ODD
类型
必改项
描述
The code uses x % 2 == 1 to check to see if a value is odd, but this won''t work for negative numbers (e.g., (-5) % 2 == -1). If this code is intending to check for oddness, consider using x & 1 == 1, or x % 2 != 0.
如果使用代码 x % 2 == 1 来检查值是否为奇数,对于负数是无效的,应该使用 x&1==1 或 x%2!=0。
案例
publicboolean isOddness(int value){
boolean result =false;
if ((value % 2) ==1) {
result = true;
}
return result;
}
分析:如果传进来的 value 是负数则此函数返回的结果是错误的。
解决方法
publicboolean isOddness(int value){
boolean result =false;
if ((value & 1) ==1) {
result = true;
}
return result;
}
19. NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE
类型
必改项
描述
There is a branch of statement that,if executed, guarantees that a null value will be dereferenced, which would generate aNullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can''t ever be executed; deciding that is beyond the ability of FindBugs. Due to the fact that this value had been previously tested for nullness, this is a definite possibility.
有一个分支如果进入的话,里面的某些变量可能会是空指针
案例
publicstaticvoid main(String[] args) {
String s1 = null;
String s2 = "";
doCompare(s1, s2);
}
publicstaticint doCompare(String s1, String s2) {
int result;
if (s1 ==null && s2 == null) {
result = 0;
} elseif (s1 ==null && s2 != null) {
result = -1;
} elseif (s1 !=null && s2 == null) {
result = 1;
} else {// s1 != null && s2 != null
result = s1.compareTo(s2);
// 这里 s1 可能发生空指针异常,但是此语句不会执行。
}
return result;
}
解决方法
publicstaticint doCompare(String s1, String s2) {
int result;
if (s1 ==null && s2 == null) {
result = 0;
} elseif (s1 ==null) {
assert s2 !=null;
result = -1;
} elseif (s2 ==null) {
assert s1 !=null;
result = 1;
} else {
result = s1.compareTo(s2);
}
return result;
}
20. RV_EXCEPTION_NOT_THROWN
类型
必改项
描述
This code creates an exception (or error) object, but doesn''t do anything with it. For example, something like
if (x < 0)
new IllegalArgumentException("x must be nonnegative");
It was probably the intent of the programmer to throw the created exception:
if (x < 0)
throw new IllegalArgumentException("x must be nonnegative");
此代码创建一个异常(或错误)的对象,但不会用它做任何事情。例如:if (x < 0)
new IllegalArgumentException("x must be nonnegative");
这可能是程序员的意图抛出创建的异常:
if (x < 0)
throw new IllegalArgumentException("x must be nonnegative");
案例
privatevoid test(){
new IllegalArgumentException("x must be nonnegative");
}
解决方法
1、打印异常调用栈。
privatevoid test(){
if(x<0){
new IllegalArgumentException("x must be nonnegative "). printStackTrace();
}
}
2、抛出异常。
privatevoid test(){
if(x<0){
throw new IllegalArgumentException("x must be nonnegative ");
}
}
21. DL_SYNCHRONIZATION_ON_BOOLEAN
类型
必改项
描述
The code synchronizes on a boxed primitive constant, such as an Boolean.
private static Boolean inited = Boolean.FALSE;
...
synchronized(inited) {
if (!inited) {
init();
inited = Boolean.TRUE;
}
}
...
Since there normally exist only two Boolean objects, this code could be synchronizing on the same object as other, unrelated code, leading to unresponsiveness and possible deadlock
该代码同步一个封装的原始常量,例如一个 Boolean 类型。
private static Boolean inited = Boolean.FALSE;
...
synchronized(inited) {
if (!inited) {
init();
inited = Boolean.TRUE;
}
}
...
由于通常只存在两个布尔对象,此代码可能是同步的其他无关的代码中相同的对象,这时会导致反应迟钝和可能死锁
案例
解决方法
22. ES_COMPARING_PARAMETER_STRING_WITH_EQ
类型
必改项
描述
This code compares ajava.lang.String parameter for reference equality using the == or != operators. Requiring callers to pass only String constants or interned strings to a method is unnecessarily fragile, and rarely leads to measurable performance gains. Consider using theequals(Object) method instead.
用 == 或者 != 方法去比较 String 类型的参数
案例
解决方法
23. JLM_JSR166_UTILCONCURRENT_MONITORENTER
类型
必改项
描述
This method performs synchronization an object that is an instance of a class from the java.util.concurrent package (or its subclasses). Instances of these classes have their own concurrency control mechanisms that are orthogonal to the synchronization provided by the Java keyword synchronized. For example, synchronizing on an AtomicBoolean will not prevent other threads from modifying the AtomicBoolean.
Such code may be correct, but should be carefully reviewed and documented, and may confuse people who have to maintain the code at a later date.
案例
解决方法
24. DL_SYNCHRONIZATION_ON_SHARED_CONSTANT
类型
必改项
描述
The code synchronizes on interned String.
private static String LOCK = "LOCK";
...
synchronized(LOCK) { ...}
...
Constant Strings are interned and shared across all other classes loaded by the JVM. Thus, this could is locking on something that other code might also be locking. This could result in very strange and hard to diagnose blocking and deadlock behavior. See http://www.javalobby.org/java/forums/t96352.html andhttp://jira.codehaus.org/browse/JETTY-352.
See CERTCON08-J. Do not synchronize on objects that may be reused for more information.
同步 String 类型的常量时,由于它被 JVM 中多个其他的对象所共有,这样在其他代码中会引起死锁。
案例
解决方法
25. SP_SPIN_ON_FIELD
类型
必改项
描述
This method spins in a loop which reads a field. The compiler may legally hoist the read out of the loop, turning the code into an infinite loop. The class should be changed so it uses proper synchronization (including wait and notify calls).
方法无限循环读取一个字段。编译器可合法悬挂宣读循环,变成一个无限循环的代码。这个类应该改变,所以使用适当的同步(包括等待和通知要求)
案例
解决方法
26. RpC_REPEATED_CONDITIONAL_TEST
类型
必改项
描述
The code contains a conditional test is performed twice, one right after the other (e.g.,x == 0 || x == 0). Perhaps the second occurrence is intended to be something else (e.g.,x == 0 || y == 0).
该代码包含对同一个条件试验了两次,两边完全一样例如:(如 X == 0 | | x == 0)。可能第二次出现是打算判断别的不同条件(如 X == 0 | | y== 0)。
案例
解决方法
27. NP_GUARANTEED_DEREF
类型
必改项
描述
There is a statement or branch that if executed guarantees that a value is null at this point, and that value that is guaranteed to be dereferenced (except on forward paths involving runtime exceptions).
Note that a check such as if (x == null) throw new NullPointerException();x.
在正常的 null 判断分支上,对象去除引用操作是受保护的不允许的
案例
public void test() {
String var = "";
int index = 2;
if (index == -1) {
var = String.class.getName();
if (var.length() == 0) {
var = null;
}
} else {
var = Integer.class.getName();
if (var.length() == 0) {
var = null;
}
}
if (var == null) {// FINBUGS reports on this line NP_GUARANTEED_DEREF
/*
* There is a statement or branch that if executed guarantees that a value
* is null at this point, and that value that is guaranteed to be
* dereferenced (except on forward paths involving runtime exceptions).
*/
throw new NullPointerException("NULL");
}
}
解决方法
据说改为 throw new RuntimeException 就会消除警告
去掉 throw new NullPointerException 也可以
28. UR_UNINIT_READ
类型
必改项
描述
This constructor reads a field which has not yet been assigned a value. This is often caused when the programmer mistakenly uses the field instead of one of the constructor''s parameters.
此构造方法中使用了一个尚未赋值的字段或属性。
案例
String a;
public FindBugsTest(String b) {
String abc = a; // UR_UNINIT_READ , 将 b 误写为 a
System.out.println(abc);
}
解决方法
使用函数的参数或初始化的字段
29. NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
类型
必改项
描述
The return value from a method is dereferenced without a null check, and the return value of that method is one that should generally be checked for null. This may lead to aNullPointerException when the code is executed.
方法的返回值没有进行是否为空的检查就重新赋值,这样可能会出现空指针异常。
案例
publicvoid caller(int a) {
String c = called(a);
if (c.equals("")) { //c maybe null
} elseif (c.equals("")) {
}
}
解决方法
增加对返回值是否为空的判断
30. IL_INFINITE_RECURSIVE_LOOP
类型
必改项
描述
This method unconditionally invokes itself. This would seem to indicate an infinite recursive loop that will result in a stack overflow.
案例
public void foo() {
foo(); // IL_INFINITE_RECURSIVE_LOOP
//...
}
解决方法
避免函数的递归调用,或加上结束递归的条件判断
31. IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_
OUTER_METHOD
类型
必改项
描述
An inner class is invoking a method that could be resolved to either a inherited method or a method defined in an outer class. By the Java semantics, it will be resolved to invoke the inherited method, but this may not be want you intend. If you really intend to invoke the inherited method, invoke it by invoking the method on super (e.g., invoke super.foo(17)), and thus it will be clear to other readers of your code and to FindBugs that you want to invoke the inherited method, not the method in the outer class.
案例
public void onOK() {
}
protected class parentClass {
public void onOK() {
}
}
protected class childClass extends parentClass {
public void callOnOK() {
onOK(); //IA_AMBIGUOUS_INVOCATION_OF_INHERITED_OR_OUTER_METHOD, should be super.onOK
}
}
解决方法
如果要引用外部类对象,可以加上 “outclass.this”。
如果要引用父类的 onOK 方法,请使用 super.onOK()。
32. IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN
类型
必改项
描述
The initial value of this parameter is ignored, and the parameter is overwritten here. This often indicates a mistaken belief that the write to the parameter will be conveyed back to the caller.
传入参数的值被忽略,但是对传入值进行了修改,并返回给了调用者
案例
publicvoid foo(String p) {
p = "abc"; // IP_PARAMETER_IS_DEAD_BUT_OVERWRITTEN
}
解决方法
不要将函数的参数作为工作变量
33. FE_FLOATING_POINT_EQUALITY
类型
必改项
描述
This operation compares two floating point values for equality. Because floating point calculations may involve rounding, calculated float and double values may not be accurate. For values that must be precise, such as monetary values, consider using a fixed-precision type such as BigDecimal. For values that need not be precise, consider comparing for equality within some range, for example:if ( Math.abs(x - y) < .0000001 ). See the Java Language Specification, section 4.2.4.
此操作比较两个浮点值是否相等。由于浮点运算可能会涉及到舍入,计算 float 和 double 值可能不准确。如果要求值必须准确,如货币值,可以考虑使用固定精度类型,如 BigDecimal 类型的值来比较
案例
解决方法
34. NP_ALWAYS_NULL
类型
必改项
描述
A null pointer is dereferenced here. This will lead to aNullPointerException when the code is executed.
对象赋为 null 值后没有被重新赋值
案例
解决方法
35. DLS_DEAD_LOCAL_STORE_OF_NULL
类型
必改项
描述
The code stores null into a local variable, and the stored value is not read. This store may have been introduced to assist the garbage collector, but as of Java SE 6.0, this is no longer needed or useful.
把一个本地变量赋值为 null 值,并且再也没有对这个变量做任何的操作。这样可能是为了垃圾回收,而是 Java SE 6.0,这已不再需要
案例
解决方法
36. SF_DEAD_STORE_DUE_TO_SWITCH_FALLTHROUGH
类型
必改项
描述
A value stored in the previous switch case is overwritten here due to a switch fall through. It is likely that you forgot to put a break or return at the end of the previous case.
在 swtich 中先前的 case 值因为 swtich 执行失败而被覆写,这就像是忘记使用 break 推出或者没有使用 return 语句放回先前的值一样。
案例
解决方法
37. INT_BAD_COMPARISON_WITH_SIGNED_BYTE
类型
必改项
描述
Signed bytes can only have a value in the range -128 to 127. Comparing a signed byte with a value outside that range is vacuous and likely to be incorrect. To convert a signed byteb to an unsigned value in the range 0..255, use0xff & b
比较有符合数,要先把有符号数转换为无符合数再进行比较
案例
解决方法
38. NP_DEREFERENCE_OF_READLINE_VALUE
类型
必改项
描述
The result of invoking readLine() is dereferenced without checking to see if the result is null. If there are no more lines of text to read, readLine() will return null and dereferencing that will generate a null pointer exception.
对 readLine() 的结果值没有进行判空操作就去重新赋值,这样的操作可以会抛出空指针异常。
案例
解决方法
39. SA_FIELD_DOUBLE_ASSIGNMENT
类型
必改项
描述
This method contains a double assignment of a field; e.g.
int x,y;
public void foo() {
x = x = 17;
}
Assigning to a field twice is useless, and may indicate a logic error or typo.
方法中的字段包含了双重任务,例如:
int x;
public void foo() {
x = x = 17;
}
这种为变量赋值是无用的,并可能表明一个逻辑错误或拼写错误。
案例
解决方法
40. DMI_INVOKING_TOSTRING_ON_ARRAY
类型
必改项
描述
The code invokes toString on an array, which will generate a fairly useless result such as [C@16f0472. Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array. See Programming Puzzlers, chapter 3, puzzle 12.
该代码调用上数组的 toString()方法,产生的结果形如 [@16f0472 并不能显示数组的真实内容。考虑使用 Arrays.toString 方法来转换成可读的字符串,提供该数组的内容数组
案例
解决方法
41. EC_UNRELATED_TYPES
类型
必改项
描述
This method calls equals(Object) on two references of different class types with no common subclasses. Therefore, the objects being compared are unlikely to be members of the same class at runtime (unless some application classes were not analyzed, or dynamic class loading can occur at runtime). According to the contract of equals(), objects of different classes should always compare as unequal; therefore, according to the contract defined by java.lang.Object.equals(Object), the result of this comparison will always be false at runtime.
调用 equals 方法比较不同类型的类
案例
解决方法
42. BC_IMPOSSIBLE_CAST
类型
必改项
描述
This cast will always throw a ClassCastException. FindBugs tracks type information from instanceof checks, and also uses more precise information about the types of values returned from methods and loaded from fields. Thus, it may have more precise information that just the declared type of a variable, and can use this to determine that a cast will always throw an exception at runtime.
不可能的类转换,执行时会抛出 ClassCastException
案例
解决方法
43. ICAST_INT_CAST_TO_FLOAT_PASSED_TO_ROUND
类型
必改项
描述
This code converts an int value to a float precision floating point number and then passing the result to the Math.round() function, which returns the int/long closest to the argument. This operation should always be a no-op, since the converting an integer to a float should give a number with no fractional part. It is likely that the operation that generated the value to be passed to Math.round was intended to be performed using floating point arithmetic.
int 类型的值转换为 float 类型之后调用了 Math.round 方法
案例
解决方法
44. RV_RETURN_VALUE_IGNORED
类型
必改项
描述
The return value of this method should be checked. One common cause of this warning is to invoke a method on an immutable object, thinking that it updates the object. For example, in the following code fragment,
String dateString = getHeaderField(name);
dateString.trim();
the programmer seems to be thinking that the trim() method will update the String referenced by dateString. But since Strings are immutable, the trim() function returns a new String value, which is being ignored here. The code should be corrected to:
String dateString = getHeaderField(name);
dateString = dateString.trim();
该方法的返回值应该进行检查。这种警告通常出现在调用一个不可变对象的方法,认为它更新了对象的值。例如:String dateString = getHeaderField(name);
dateString.trim();
程序员似乎以为 trim()方法将更新 dateString 引用的字符串。但由于字符串是不可改变的,trim()函数返回一个新字符串值,在这里它是被忽略了。该代码应更正:
String dateString = getHeaderField(name);
dateString = dateString.trim();
案例
解决方法
45. SF_SWITCH_FALLTHROUGH
类型
必改项
描述
This method contains a switch statement where one case branch will fall through to the next case. Usually you need to end this case with a break or return.
Switch 语句中一个分支执行后又执行了下一个分支。通常 case 后面要跟 break 或者 return 语句来跳出。
案例
int main(int argc, char* argv[])
{
printf("Hello World!/n");
int num_of_operands = 2;
//fall through 的设计可以把代码设计得很简约,
// 以下的这个操作数处理是一个很好的例子,它可以很简约的去处理每一个操作数
// 当然不得不说 switch 将 fall through 设计为默认操作是引起许多 bug 的原因
//session 1:
switch(num_of_operands){
case 2://process_operand(operator->operand_2);
case 1://process_operand(operator->operand_1);
default:;
}
//session 2: 即使是 default 没有 break,一样会出现 fall through 现象
num_of_operands = 2;
switch(num_of_operands){
case 1:
printf("case 1 fall through/n");
default:
printf("default fall through/n");
//num_of_operands = 10;
case 3:
printf("case 2 fall through/n");
}
//conclusion : 在使用 switch 时需要注意,如果是一般应用,请别忘了加上 break
return 0;
}
解决方法
在使用 switch 时需要注意,如果是一般应用,请别忘了加上 break
46. DE_MIGHT_IGNORE
类型
必改项
描述
This method might ignore an exception. In general, exceptions should be handled or reported in some way, or they should be thrown out of the method.
方法可能忽略异常
案例
try{}catch(Exception ex){}
解决方法
方法有可能抛异常或者忽略异常,需要对异常进行处理 , 即需要在 catch 体中对异常进行处理
47. VA_FORMAT_STRING_EXTRA_ARGUMENTS_PASSED
类型
比改项
描述
A format-string method with a variable number of arguments is called, but more arguments are passed than are actually used by the format string. This won''t cause a runtime exception, but the code may be silently omitting information that was intended to be included in the formatted string.
使用 String 的 format 方法时有非法的参数也经过了格式化操作。
案例
这个错误很简单,是使用 String.format 的时候出了问题,format 里面的参数没有被全部用上。
看下面一段代码:
public void test(){
String str1 = "123";
String str2 = "456";
String str3 = String.format("{0} {1}" , str1 ,str2);
System.out.println(str3);
}
输出的结果是:{0} {1}
解决方法
这个 Bug 描述就是这种问题,str1 和 str2 根本没有被用上!{0}{1} 这种 Format 格式是.NET 上面的用法,java 里面应该是 %s %s。
这个是一个代码逻辑问题,可能是你写代码时不小心导致的,它在这段代码里不会导致异常,但往往会很可能导致其他地方异常,那时候你可能会百思不得其解。
48. RE_POSSIBLE_UNINTENDED_PATTERN
类型
必改项
描述
A String function is being invoked and "." is being passed to a parameter that takes a regular expression as an argument. Is this what you intended? For example s.replaceAll(".", "/") will return a String in which every character has been replaced by a / character, and s.split(".")always returns a zero length array of String.
案例
if(version != null && (!version.equalsIgnoreCase("")) && version.split(".").length < 4){
this.m_txfSoftVersion.setVersion(version);
}
String 的 split 方法传递的参数是正则表达式,正则表达式本身用到的字符需要转义,如:句点符号 ".",美元符号 "$",乘方符号 "^",大括号 "{}",方括号 "[]",圆括号 "()",竖线 "|",星号 "*",加号 "+",问号 "?" 等等,这些需要在前面加上 "\\" 转义符。
解决方法
在前面加上 "\\" 转义符
49. SE_BAD_FIELD_INNER_CLASS
类型
必改项
描述
This Serializable class is an inner class of a non-serializable class. Thus, attempts to serialize it will also attempt to associate instance of the outer class with which it is associated, leading to a runtime error.
If possible, making the inner class a static inner class should solve the problem. Making the outer class serializable might also work, but that would mean serializing an instance of the inner class would always also serialize the instance of the outer class, which it often not what you really want.
案例
解决方法
50. RV_01_TO_INT
类型
必改项
描述
A random value from 0 to 1 is being coerced to the integer value 0. You probably want to multiple the random value by something else before coercing it to an integer, or use theRandom.nextInt(n) method.
从 0 到 1 随机值被强制为整数值 0。在强制得到一个整数之前,你可能想得到多个随机值。或使用 Random.nextInt(n)的方法。
案例
解决方法
51. UW_UNCOND_WAIT
类型
必改项
描述
This method contains a call tojava.lang.Object.wait() which is not guarded by conditional control flow. The code should verify that condition it intends to wait for is not already satisfied before calling wait; any previous notifications will be ignored.
方法中包含调用 java.lang.Object.wait(),而却没有放到条件流程控制中。该代码应确认条件尚未满足之前等待 ; 先前任何通知将被忽略。
案例
public class Test
{
void clueless() throws Exception
{
synchronized(this)
{
this.wait(); // VIOLATION
}
}
}
该检测模式寻找在进入同步块时无条件地 wait(),与 wait 相关的条件判断在无锁(不在同步块内)情况下进行的,有可能导致其它线程的 notification 被忽略。
解决方法
多线程错误 - 无条件等待
将 wait() 放到条件控制流中:If we are not enabled, then waitif (!enabled) { /* 条件判断不在同步块内 */
try {
synchronized (lock) { /*if (!enabled) 应该在这里 */
lock.wait();
...
52. UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS
类型
必改项
描述
This anonymous class defined a method that is not directly invoked and does not override a method in a superclass. Since methods in other classes cannot directly invoke methods declared in an anonymous class, it seems that this method is uncallable. The method might simply be dead code, but it is also possible that the method is intended to override a method declared in a superclass, and due to an typo or other error the method does not, in fact, override the method it is intended to.
在匿名类中定义了一个既没有覆写超类中方法也不能直接调用的方法。因为在其他类的方法不能直接引用匿名类声明的方法,似乎这种方法不能被调用,这种方法可能只是没有任何作用的代码,但也可能覆写超类中声明。
案例
For example, in the following code, it is impossible to invoke the initalValue method (because the name is misspelled and as a result is doesn''t override a method in ThreadLocal).
private static ThreadLocal serialNum = new ThreadLocal() {
protected synchronized Object initalValue() {
return new Integer(nextSerialNum++);
}
};
解决方法
错误用法 - 匿名内部类中定义的不可调用的方法
Added check for uncallable method of an anonymous inner class.
53. EQ_SELF_USE_OBJECT
类型
必改项
描述
This class defines a covariant version of theequals() method, but inherits the normalequals(Object) method defined in the basejava.lang.Object class. The class should probably define aboolean equals(Object) method.
类中定义了一组 equals 方法,但是都是继承的 java.lang.Object class 中的 equals(Object) 方法
案例
public class Point {
private static double version = 1.0;
private transient double distance;
private int x, y;
/* public boolean equals(Object other) {
if (other == this) return true;
if (other == null) return false;
if (getClass() != other.getClass()) return false;
Point point = (Point)other;
return (x == point.x && y == point.y);
} */
}
Point p1,p2;
if(p1.equals(p2)) return ture;
Note:Regardless of which class contains the equals() method, the signature must always declare an Object argument type. Since Java''s libraries look for one with an Object argument, if the signature is not correct, then the java.lang.Object method will be called instead, leading to incorrect behavior.
此处我们想比较的仅是 x 和 y,而由于代码中未重写 equals() 方法,调用了 Object.equals(Object) 方法,对 distance 与 version 也进行了比较。
解决方法
错误用法 - 协变 equals() 方法定义,继承了 Object.equals(Object)
类中增加 public boolean equals(Object) 方法的定义(见上例注释部分)。
54. REC_CATCH_EXCEPTION
类型
必改项
描述
This method uses a try-catch block that catches Exception objects, but Exception is not thrown within the try block, and RuntimeException is not explicitly caught. It is a common bug pattern to say try { ... } catch (Exception e) { something } as a shorthand for catching a number of types of exception each of whose catch blocks is identical, but this construct also accidentally catches RuntimeException as well, masking potential bugs.
在 try/catch 块中捕获异常,但是异常没有在 try 语句中抛出而 RuntimeException 又没有明确的被捕获
案例
public void addInstance(String className) {
try {
Class clazz = Class.forName(className);
objectSet.add(clazz.newInstance());
}
catch (IllegalAccessException e) {
logger.log("Exception in addInstance", e);
}
catch (InstantiationException e) {
logger.log("Exception in addInstance", e);
}
catch (ClassNotFoundException e) {
logger.log("Exception in addInstance", e);
}
}
下面将上述代码中三个捕获块合并成捕获 Exception 的单独捕获块,因为每个捕获块的捕获恢复操作是相同的,这样便造成了未经检查的异常将被记录。
public void addInstance(String className) {
try {
Class clazz = Class.forName(className);
objectSet.add(clazz.newInstance());
}
/* catch (RuntimeException e) {
throw e;
} */
catch (Exception e) {
logger.log("Exception in newInstance", e);
}
}
解决方法
错误用法 - 捕获了没有抛出的异常
因为 RuntimeException 扩展了 Exception,代码中增加捕获 RuntimeException,并在捕获 Exception 之前重新将其抛出。
55. RU_INVOKE_RUN
类型
必改项
描述
This method explicitly invokesrun() on an object. In general, classes implement theRunnable interface because they are going to have theirrun() method invoked in a new thread, in which caseThread.start() is the right method to call.
这种方法显式调用一个对象的 run()。一般来说,类是实现 Runnable 接口的,因为在一个新的线程他们将有自己的 run()方法,在这种情况下 Thread.start()方法调用是正确的。
案例
public static void main(final String[] args) {
System.out.println("Main thread: " + Thread.currentThread().getId());
final FooThread thread = new FooThread();
thread.run();
//thread.start();
}
public static class FooThread extends Thread
{
@Override
public void run() {
System.out.println("I''m executing from thread " + Thread.currentThread().getId());
super.run();
}
}
解决方法
多线程错误 - 在线程中调用了 run()
run() 方法只是类的一个普通方法而已,如果直接调用 run 方法,程序中依然只有主线程这一个线程。启动一个新的线程,我们不是直接调用 Thread 的子类对象的 run 方法,而是调用 Thread 子类对象的 start(从 Thread 类中继承的)方法,Thread 类对象的 start 方法将产生一个新的线程,并在该线程上运行该 Thread 类对象中的 run 方法,根据面向对象的多态性,在该线程上实际运行的是 Thread 子类(也就是我们编写的那个类)对象中的 run 方法。
56. NP_SYNC_AND_NULL_CHECK_FIELD
类型
必改项
描述
Since the field is synchronized on, it seems not likely to be null. If it is null and then synchronized on a NullPointerException will be thrown and the check would be pointless. Better to synchronize on another field.
如果代码块是同步的,那么久不可能为空。如果是空,同步时就会抛出 NullPointerException 异常。最好是在另一个代码块中进行同步。
案例
解决方法
57. DLS_DEAD_STORE_OF_CLASS_LITERAL
类型
必改项
描述
This instruction assigns a class literal to a variable and then never uses it.The behavior of this differs in Java 1.4 and in Java 5. In Java 1.4 and earlier, a reference to Foo.class would force the static initializer for Foo to be executed, if it has not been executed already. In Java 5 and later, it does not.
See Sun''sarticle on Java SE compatibility for more details and examples, and suggestions on how to force class initialization in Java 5.
以类的字面名称方式为一个字段赋值后再也没有去使用它,在 1.4jdk 中它会自动调用静态的初始化方法,而在 jdk1.5 中却不会去执行。
案例
解决方法
58. INT_BAD_REM_BY_1
类型
必改项
描述
Any expression (exp % 1) is guaranteed to always return zero. Did you mean (exp & 1) or (exp % 2) instead?
案例
解决方法
59. DLS_DEAD_LOCAL_STORE_SHADOWS_FIELD
类型
必改项
描述
This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used. There is a field with the same name as the local variable. Did you mean to assign to that variable instead?
案例
解决方法
60. ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD
类型
选改项
描述
This instance method writes to a static field. This is tricky to get correct if multiple instances are being manipulated, and generally bad practice.
案例
解决方法
61. SWL_SLEEP_WITH_LOCK_HELD
类型
选改项
描述
This method calls Thread.sleep() with a lock held. This may result in very poor performance and scalability, or a deadlock, since other threads may be waiting to acquire the lock. It is a much better idea to call wait() on the lock, which releases the lock and allows other threads to run.
当持有对象时调用 Thread.sleep()。这可能会导致很差的性能和可扩展性,或陷入死锁,因为其他线程可能正在等待获得锁。调用 wait()是一个更好的主意,释放对象的持有以允许其他线程运行。
案例
解决方法
62. LI_LAZY_INIT_STATIC
类型
选改项
描述
This method contains an unsynchronized lazy initialization of a non-volatile static field. Because the compiler or processor may reorder instructions, threads are not guaranteed to see a completely initialized object, if the method can be called by multiple threads. You can make the field volatile to correct the problem. For more information, see theJava Memory Model web site.
静态域不正确的延迟初始化。这种方法包含了一个不同步延迟初始化的非 volatile 静态字段。因为编译器或处理器可能会重新排列指令,如果该方法可以被多个线程调用,线程不能保证看到一个完全初始化的对象。可以让字段可变来解决此问题
案例
解决方法
63. NM_SAME_SIMPLE_NAME_AS_SUPERCLASS
类型
选改项
描述
This class has a simple name that is identical to that of its superclass, except that its superclass is in a different package (e.g.,alpha.Foo extendsbeta.Foo). This can be exceptionally confusing, create lots of situations in which you have to look at import statements to resolve references and creates many opportunities to accidently define methods that do not override methods in their superclasses.
继承同一父类的子类不能使用相同的名称,即使它们位于不同的包中
案例
解决方法
64. LI_LAZY_INIT_UPDATE_STATIC
类型
选改项
描述
This method contains an unsynchronized lazy initialization of a static field. After the field is set, the object stored into that location is further updated or accessed. The setting of the field is visible to other threads as soon as it is set. If the futher accesses in the method that set the field serve to initialize the object, then you have avery serious multithreading bug, unless something else prevents any other thread from accessing the stored object until it is fully initialized.
Even if you feel confident that the method is never called by multiple threads, it might be better to not set the static field until the value you are setting it to is fully populated/initialized.
这种方法包含一个不同步延迟初始化的静态字段。之后为字段赋值,对象存储到该位置后进一步更新或访问。字段后尽快让其他线程能够访问。如果该方法的进一步访问该字段为初始化对象提供服务,然后你有一个非常严重的多线程 bug,除非别的东西阻止任何其他线程访问存储的对象,直到它完全初始化。
即使你有信心,该方法是永远不会被多个线程调用时,在它的值还没有被充分初始化或移动,不把它设定为 static 字段时它可能会更好。
案例
解决方法
65. GC_UNRELATED_TYPES
类型
选改项
描述
This call to a generic collection method contains an argument with an incompatible class from that of the collection''s parameter (i.e., the type of the argument is neither a supertype nor a subtype of the corresponding generic type argument). Therefore, it is unlikely that the collection contains any objects that are equal to the method argument used here. Most likely, the wrong value is being passed to the method.
In general, instances of two unrelated classes are not equal. For example, if the Foo and Bar classes are not related by subtyping, then an instance of Foo should not be equal to an instance of Bar. Among other issues, doing so will likely result in an equals method that is not symmetrical. For example, if you define the Foo class so that a Foo can be equal to a String, your equals method isn''t symmetrical since a String can only be equal to a String.
In rare cases, people do define nonsymmetrical equals methods and still manage to make their code work. Although none of the APIs document or guarantee it, it is typically the case that if you check if a Collection<String> contains a Foo, the equals method of argument (e.g., the equals method of the Foo class) used to perform the equality checks.
案例
Foo<A, B> foo;
foo.remove(a, Collections<B>.emptySet()); //This generated a false positive because it thinks that the second parameter should be of type B, not Set<B>
class Foo<X, Y> extends Bar<X, Set<Y>>{
...
}
class Bar<T, S> extends ConcurrentHashMap<T, S> {
@Override
public boolean remove(Object key, Object value) {
...
}
}
解决方法
66. SC_START_IN_CTOR
类型
选改项
描述
The constructor starts a thread. This is likely to be wrong if the class is ever extended/subclassed, since the thread will be started before the subclass constructor is started
在构造函数中启动一个线程。如果类曾经被子类扩展过,那么这很可能是错的,因为线程将在子类构造之前开始启动。
案例
解决方法
67. EQ_ALWAYS_FALSE
类型
选该项
描述
This class defines an equals method that always returns false. This means that an object is not equal to itself, and it is impossible to create useful Maps or Sets of this class. More fundamentally, it means that equals is not reflexive, one of the requirements of the equals method.
The likely intended semantics are object identity: that an object is equal to itself. This is the behavior inherited from class Object. If you need to override an equals inherited from a different superclass, you can use use:
public boolean equals(Object o) { return this == o; }
使用 equals 方法返回值总是 false
案例
解决方法
68. RC_REF_COMPARISON
类型
选改项
描述
This method compares two reference values using the == or != operator, where the correct way to compare instances of this type is generally with the equals() method. It is possible to create distinct instances that are equal but do not compare as == since they are different objects. Examples of classes which should generally not be compared by reference are java.lang.Integer, java.lang.Float, etc.
比较两个对象值是否相等时应该采用 equals 方法,而不是 == 方法
案例
解决方法
69. IJU_ASSERT_METHOD_INVOKED_FROM_RUN_METHOD
类型
选改项
描述
A JUnit assertion is performed in a run method. Failed JUnit assertions just result in exceptions being thrown. Thus, if this exception occurs in a thread other than the thread that invokes the test method, the exception will terminate the thread but not result in the test failing.
在 JUnit 中的断言在 run 方法中不会被告知
案例
解决方法
70. STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE
类型
选改项
描述
As the JavaDoc states, DateFormats are inherently unsafe for multithreaded use. The detector has found a call to an instance of DateFormat that has been obtained via a static field. This looks suspicous.
For more information on this seeSun Bug #6231579 andSun Bug #6178997.
在官方的 JavaDoc,DateFormats 多线程使用本事就是不安全的。探测器发现调用一个 DateFormat 的实例将会获得一个静态对象。
myString = DateFormat.getDateInstance().format(myDate);
案例
解决方法
71. STCAL_STATIC_SIMPLE_DATE_FORMAT_INSTANCE
类型
选改项
描述
As the JavaDoc states, DateFormats are inherently unsafe for multithreaded use. Sharing a single instance across thread boundaries without proper synchronization will result in erratic behavior of the application.
You may also experience serialization problems.
Using an instance field is recommended.
For more information on this seeSun Bug #6231579 andSun Bug #6178997.
DateFormat 在多线程中本身就是不安全的,如果在线程范围中共享一个 DateFormat 的实例而不使用一个同步的方法在应用中就会出现一些奇怪的行为。
案例
解决方法
72. AT_OPERATION_SEQUENCE_ON_CONCURRENT_ABSTR
ACTION
类型
选改项
描述
This code contains a sequence of calls to a concurrent abstraction (such as a concurrent hash map). These calls will not be executed atomically.
案例
解决方法
73. BC_UNCONFIRMED_CAST
类型
选改项
描述
This cast is unchecked, and not all instances of the type casted from can be cast to the type it is being cast to. Check that your program logic ensures that this cast will not fail.
强制类型转换操作没有经过验证,而且不是所有的此种类型装换过的类都可以再强制类型转换为原类型。在代码中需要进行逻辑判断以保证可以进行这样的操作。
案例
解决方法
74. RV_ABSOLUTE_VALUE_OF_RANDOM_INT
类型
选改项
描述
This code generates a random signed integer and then computes the absolute value of that random integer. If the number returned by the random number generator isInteger.MIN_VALUE, then the result will be negative as well (sinceMath.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE). (Same problem arised for long values as well).
此代码生成一个随机的符号整数,然后计算该随机整数的绝对值。如果随机数生成数绝对值为 Integer.MIN_VALUE 的,那么结果将是负数(因为 Math.abs(Integer.MIN_VALUE 的)== Integer.MIN_VALUE 的)。
案例
public intgetAbsRandom() {
Random random = new Random();
int raw = random.nextInt();
returnMath.abs(raw);
}
解决方法
对产生的随机数做判断,是否为 Integer.MIN_VALUE 特殊情况
75. NN_NAKED_NOTIFY
类型
选改项
描述
A call to notify() or notifyAll() was made without any (apparent) accompanying modification to mutable object state. In general, calling a notify method on a monitor is done because some condition another thread is waiting for has become true. However, for the condition to be meaningful, it must involve a heap object that is visible to both threads.
This bug does not necessarily indicate an error, since the change to mutable object state may have taken place in a method which then called the method containing the notification.
赤裸的通知
案例
protectedvoid notifyExchange(MessageExchangeImpl me, Object lock, String from) {
if (LOG.isDebugEnabled()) {
LOG.debug("Notifying exchange " + me.getExchangeId() + "(" + Integer.toHexString(me.hashCode()) + ") in " +this + " from "+ from);
}
&nb sp; synchronized (lock) {
lock.notify();
}
}
解决方法
76. BC_IMPOSSIBLE_INSTANCEOF
类型
选改项
描述
This instanceof test will always return false. Although this is safe, make sure it isn''t an indication of some misunderstanding or some other logic error.
采用 instaneof 方法进行比较时总是返回 false。前提是保证它不是由于某些逻辑错误造成的。
案例
publicclass Person {
publicclass Sunextends Person
{
…….
}
public boolean isPerson(){
Person obj = new Person();
if(obj instanceof Sun){
returntrue;
}
returnfalse;
}
解决方法
防止这类错误出现
77. DMI_RANDOM_USED_ONLY_ONCE
类型
选改项
描述
This code creates a java.util.Random object, uses it to generate one random number, and then discards the Random object. This produces mediocre quality random numbers and is inefficient. If possible, rewrite the code so that the Random object is created once and saved, and each time a new random number is required invoke a method on the existing Random object to obtain it.
If it is important that the generated Random numbers not be guessable, youmust not create a new Random for each random number; the values are too easily guessable. You should strongly consider using a java.security.SecureRandom instead (and avoid allocating a new SecureRandom for each random number needed).
随机创建对象只使用过一次就抛弃
案例
publicint getRandom(int seed){
return new Random(seed).nextInt();
}
解决方法
findbugs 建议使用 SecureRandom
publicint getRandom(byte[] seed){
returnnew SecureRandom(seed).nextInt();
}
78. NP_GUARANTEED_DEREF_ON_EXCEPTION_PATH
类型
选改项
描述
There is a statement or branch on an exception path that if executed guarantees that a value is null at this point, and that value that is guaranteed to be dereferenced (except on forward paths involving runtime exceptions).
案例
解决方法
79. WA_NOT_IN_LOOP
类型
选改项
描述
This method contains a call to java.lang.Object.wait() which is not in a loop. If the monitor is used for multiple conditions, the condition the caller intended to wait for might not be the one that actually occurred.
这种方法包含调用 java.lang.Object.wait(),而这并不是一个循环。如果监视器用于多个条件,打算调用 wait() 方法的条件可能不是实际发生的。
案例
protectedvoid waitForExchange(MessageExchangeImpl me, Object lock,long timeout, String from)throws InterruptedException {
// If the channel is closed while here, we must abort
if (LOG.isDebugEnabled()) {
LOG.debug("Waiting for exchange " + me.getExchangeId() +" (" + Integer.toHexString(me.hashCode()) +") to be answered in "
+ this + " from " + from);
}
Thread th = Thread.currentThread();
try {
waiters.put(th, Boolean.TRUE);
lock.wait(timeout);
} finally {
waiters.remove(th);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Notified: " + me.getExchangeId() +"(" + Integer.toHexString(me.hashCode()) +") in " + this +" from " + from);
}
}
解决方法
整理的行业规则:
80. OBL_UNSATISFIED_OBLIGATION
类型
必改项
描述
This method may fail to clean up (close, dispose of) a stream, database object, or other resource requiring an explicit cleanup operation.
In general, if a method opens a stream or other resource, the method should use a try/finally block to ensure that the stream or resource is cleaned up before the method returns.
This bug pattern is essentially the same as the OS_OPEN_STREAM and ODR_OPEN_DATABASE_RESOURCE bug patterns, but is based on a different (and hopefully better) static analysis technique. We are interested is getting feedback about the usefulness of this bug pattern. To send feedback, either:
- send email to findbugs@cs.umd.edu
- file a bug report: http://findbugs.sourceforge.net/reportingBugs.html
In particular, the false-positive suppression heuristics for this bug pattern have not been extensively tuned, so reports about false positives are helpful to us.
See Weimer and Necula, Finding and Preventing Run-Time Error Handling Mistakes, for a description of the analysis technique.
这种方法可能无法清除(关闭,处置)一个流,数据库对象,或其他资源需要一个明确的清理行动。
一般来说,如果一个方法打开一个流或其他资源,该方法应该使用 try / finally 块来确保在方法返回之前流或资源已经被清除了。这种错误模式基本上和 OS_OPEN_STREAM 和 ODR_OPEN_DATABASE_RESOURCE 错误模式相同,但是是在不同在静态分析技术。我们正为这个错误模式的效用收集反馈意见。
案例
解决方法
81. IC_SUPERCLASS_USES_SUBCLASS_DURING_INITIALIZATION
类型
必改项
描述
During the initialization of a class, the class makes an active use of a subclass. That subclass will not yet be initialized at the time of this use. For example, in the following code,foo will be null.
public class CircularClassInitialization {
static class InnerClassSingleton extends CircularClassInitialization {
static InnerClassSingleton singleton = new InnerClassSingleton();
}
static CircularClassInitialization foo = InnerClassSingleton.singleton;
}
子类在父类未初始化之前使用父类对象实例
案例
解决方法
82. IMSE_DONT_CATCH_IMSE
类型
必改项
描述
IllegalMonitorStateException is generally only thrown in case of a design flaw in your code (calling wait or notify on an object you do not hold a lock on).
捕捉违法的监控状态异常,例如当没有获取到对象锁时使用其 wait 和 notify 方法
案例
解决方法
83. IL_INFINITE_LOOP
类型
必改项
描述
This loop doesn''t seem to have a way to terminate (other than by perhaps throwing an exception).
方法的自调用引起的死循环
案例
解决方法
84. NP_CLOSING_NULL
类型
必改项
描述
close() is being invoked on a value that is always null. If this statement is executed, a null pointer exception will occur. But the big risk here you never close something that should be closed.
一个为空的对象调用 close 方法
案例
解决方法
85. NP_NONNULL_PARAM_VIOLATION
类型
必改项
描述
This method passes a null value as the parameter of a method which must be nonnull. Either this parameter has been explicitly marked as @Nonnull, or analysis has determined that this parameter is always dereferenced.
方法中为 null 的参数没有被重新赋值
案例
解决方法
86. NP_NONNULL_RETURN_VIOLATION
类型
必改项
描述
This method may return a null value, but the method (or a superclass method which it overrides) is declared to return @NonNull.
方法声明了返回值不能为空,但是方法中有可能返回 null
案例
void test(){
String ss = null;
sya(ss);
}
public void sya(String ad){
ad.getBytes();
}
解决方法
87. NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS
类型
必改项
描述
A possibly-null value is passed at a call site where all known target methods require the parameter to be nonnull. Either the parameter is annotated as a parameter that should always be nonnull, or analysis has shown that it will always be dereferenced.
方法参数中声明为 nonnull 类型的参数为 null
案例
解决方法
88. NM_BAD_EQUAL
类型
必改项
描述
This class defines a methodequal(Object). This method does not override theequals(Object) method injava.lang.Object, which is probably what was intended.
类中定义了一个 equal 方法但是却不是覆写的 Object 对象的 equals 方法
案例
解决方法
89. SA_LOCAL_SELF_COMPUTATION
类型
必改项
描述
This method performs a nonsensical computation of a local variable with another reference to the same variable (e.g., x&x or x-x). Because of the nature of the computation, this operation doesn''t seem to make sense, and may indicate a typo or a logic error. Double check the computation.
此方法对同一变量执行了荒谬的计算(如 x&x 或 x-x)操作。由于计算的性质,这一行动似乎没有意义,并可能表明错误或逻辑错误。
案例
解决方法
90. UR_UNINIT_READ_CALLED_FROM_SUPER_CONSTRUCTOR
类型
必改项
描述
This method is invoked in the constructor of of the superclass. At this point, the fields of the class have not yet initialized.
To make this more concrete, consider the following classes:
When a B is constructed, the constructor for the A class is invokedbefore the constructor for B sets value. Thus, when the constructor for A invokes getValue, an uninitialized value is read for value
方法被超类的构造函数调用时,在当前类中的字段或属性还没有被初始化
案例
abstract class A {
int hashCode;
abstract Object getValue();
A() {
hashCode = getValue().hashCode();
}
}
class B extends A {
Object value;
B(Object v) {
this.value = v;
}
Object getValue() {
return value;
}
}
当 B 是创建时,A 的构造函数将在 B 为 value 赋值之前触发,然而在 A 的初始化方法调用 getValue 方法时 value 这个变量还没有被初始化。
解决方法
91. DMI_INVOKING_TOSTRING_ON_ANONYMOUS_ARRAY
类型
必改项
描述
The code invokes toString on an (anonymous) array. Calling toString on an array generates a fairly useless result such as [C@16f0472. Consider using Arrays.toString to convert the array into a readable String that gives the contents of the array. See Programming Puzzlers, chapter 3, puzzle 12.
该代码调用上匿名数组的 toString()方法,产生的结果形如 [@16f0472 并没有实际的意义。考虑使用 Arrays.toString 方法来转换成可读的字符串,提供该数组的内容数组。
案例
String[] a = { "a" };
System.out.println(a.toString());
解决方法
// 正确的使用为
System.out.println(Arrays.toString(a));
92. UWF_UNWRITTEN_FIELD
类型
必改项
描述
This field is never written. All reads of it will return the default value. Check for errors (should it have been initialized?), or remove it if it is useless.
此字段是永远不会写入值。所有读取将返回默认值。检查错误(如果它被初始化?),如果它确实没有用就删除掉。
案例
解决方法
93. DM_STRING_VOID_CTOR
类型
必改项
描述
Creating a newjava.lang.String object using the no-argument constructor wastes memory because the object so created will be functionally indistinguishable from the empty string constant "". Java guarantees that identical string constants will be represented by the sameString object. Therefore, you should just use the empty string constant directly.
使用没有参数的构造方法去创建新的 String 对象是浪费内存空间的,因为这样创建会和空字符串 “” 混淆。Java 中保证完成相同的构造方法会产生描绘相同的 String 对象。所以你只要使用空字符串来创建就可以了。
案例
解决方法
94. SBSC_USE_STRINGBUFFER_CONCATENATION
类型
必改项
描述
The method seems to be building a String using concatenation in a loop. In each iteration, the String is converted to a StringBuffer/StringBuilder, appended to, and converted back to a String. This can lead to a cost quadratic in the number of iterations, as the growing string is recopied in each iteration.
Better performance can be obtained by using a StringBuffer (or StringBuilder in Java 1.5) explicitly.
For example:
在循环中构建一个 String 对象时从性能上讲使用 StringBuffer 来代替 String 对象
案例
// This is bad
String s = "";
for (int i = 0; i < field.length; ++i) {
s = s + field[i];
}
解决方法
// This is better
StringBuffer buf = new StringBuffer();
for (int i = 0; i < field.length; ++i) {
buf.append(field[i]);
}
String s = buf.toString();
95. BC_BAD_CAST_TO_CONCRETE_COLLECTION
类型
必改项
描述
This code casts an abstract collection (such as a Collection, List, or Set) to a specific concrete implementation (such as an ArrayList or HashSet). This might not be correct, and it may make your code fragile, since it makes it harder to switch to other concrete implementations at a future point. Unless you have a particular reason to do so, just use the abstract collection class.
代码把抽象的集合(如 List,Set,或 Collection)强制转换为具体落实类型(如一个 ArrayList 或 HashSet)。这可能不正确,也可能使您的代码很脆弱,因为它使得难以在今后的切换指向其他具体实现。除非你有特别理由这样做,否则只需要使用抽象的集合类。
案例
解决方法
96. DLS_DEAD_LOCAL_STORE
类型
必改项
描述
This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.
Note that Sun''s javac compiler often generates dead stores for final local variables. Because FindBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.
该指令为局部变量赋值,但在其后的没有对她做任何使用。通常,这表明一个错误,因为值从未使用过。
案例
解决方法
97. NS_NON_SHORT_CIRCUIT
类型
必改项
描述
This code seems to be using non-short-circuit logic (e.g., & or |) rather than short-circuit logic (&& or ||). Non-short-circuit logic causes both sides of the expression to be evaluated even when the result can be inferred from knowing the left-hand side. This can be less efficient and can result in errors if the left-hand side guards cases when evaluating the right-hand side can generate an error.
See the Java Language Specification for details
代码中使用(& or |)代替(&& or ||)操作,会引起不安全的操作
案例
解决方法
98. RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE
类型
必改项
描述
This method contains a redundant check of a known non-null value against the constant null.
方法中对不为空的值进行为空的判断
案例
解决方法
99. RI_REDUNDANT_INTERFACES
类型
必改项
描述
This class declares that it implements an interface that is also implemented by a superclass. This is redundant because once a superclass implements an interface, all subclasses by default also implement this interface. It may point out that the inheritance hierarchy has changed since this class was created, and consideration should be given to the ownership of the interface''s implementation.
子类和父类都实现了同一个接口,这种定义是多余的。
案例
解决方法
100. SA_LOCAL_DOUBLE_ASSIGNMENT
类型
必改项
描述
This method contains a double assignment of a local variable; e.g.
public void foo() {
int x,y;
x = x = 17;
}
Assigning the same value to a variable twice is useless, and may indicate a logic error or typo.
为一个局部变量两次赋值,这样是没有意义的
案例
解决方法
101. SA_LOCAL_SELF_ASSIGNMENT
类型
必改项
描述
This method contains a self assignment of a local variable; e.g.
public void foo() {
int x = 3;
x = x;
}
Such assignments are useless, and may indicate a logic error or typo
局部变量使用自身给自己赋值
案例
解决方法
102. SF_SWITCH_NO_DEFAULT
类型
必改项
描述
This method contains a switch statement where default case is missing. Usually you need to provide a default case.
Switch 没有默认情况下执行的 case 语句
案例
解决方法
103. UCF_USELESS_CONTROL_FLOW
类型
必改项
描述
This method contains a useless control flow statement, where control flow continues onto the same place regardless of whether or not the branch is taken. For example, this is caused by having an empty statement block for an if statement:
if (argv.length == 0) {
// TODO: handle this case
}
没有任何作用的条件语句
案例
解决方法
104. UCF_USELESS_CONTROL_FLOW_NEXT_LINE
类型
必改项
描述
This method contains a useless control flow statement in which control flow follows to the same or following line regardless of whether or not the branch is taken. Often, this is caused by inadvertently using an empty statement as the body of an if statement, e.g.:
无效的条件控制语句
案例
if (argv.length == 1);
System.out.println("Hello, " + argv[0]);
无效的条件控制语句,注意 if (argv.length == 1); 以 “;” 结尾,下面的语句无论是否满足都会运行。
解决方法
105. NP_BOOLEAN_RETURN_NULL
类型
必改项
描述
A method that returns either Boolean.TRUE, Boolean.FALSE or null is an accident waiting to happen. This method can be invoked as though it returned a value of type boolean, and the compiler will insert automatic unboxing of the Boolean value. If a null value is returned, this will result in a NullPointerException.
返回值为 boolean 类型的方法直接返回 null,这样会导致空指针异常
案例
解决方法
106. SI_INSTANCE_BEFORE_FINALS_ASSIGNED
类型
必改项
描述
The class''s static initializer creates an instance of the class before all of the static final fields are assigned.
在所有的 static final 字段赋值之前去使用静态初始化的方法创建一个类的实例。
案例
解决方法
107. VA_FORMAT_STRING_BAD_ARGUMENT
类型
必改项
描述
The format string placeholder is incompatible with the corresponding argument. For example, System.out.println("%d\n", "hello");
The %d placeholder requires a numeric argument, but a string value is passed instead. A runtime exception will occur when this statement is executed.
错误使用参数类型来格式化字符串
案例
解决方法
108. MF_METHOD_MASKS_FIELD
类型
必改项
描述
This method defines a local variable with the same name as a field in this class or a superclass. This may cause the method to read an uninitialized value from the field, leave the field uninitialized, or both.
在方法中定义的局部变量和类变量或者父类变量同名,从而引起字段混淆。
案例
解决方法
109. NP_ARGUMENT_MIGHT_BE_NULL
类型
必改项
描述
A parameter to this method has been identified as a value that should always be checked to see whether or not it is null, but it is being dereferenced without a preceding null check.
方法没有判断参数是否为空
案例
解决方法
110. MWN_MISMATCHED_NOTIFY
类型
必改项
描述
This method calls Object.notify() or Object.notifyAll() without obviously holding a lock on the object. Calling notify() or notifyAll() without a lock held will result in anIllegalMonitorStateException being thrown.
此方法调用 Object.notify()或 Object.notifyAll()而没有获取到该对象的对象锁。调用 notify()或 notifyAll()而没有持有该对象的对象锁,将导致 IllegalMonitorStateException 异常。
案例
解决方法
111. MWN_MISMATCHED_WAIT
类型
必改项
描述
This method calls Object.wait() without obviously holding a lock on the object. Calling wait() without a lock held will result in anIllegalMonitorStateException being thrown.
此方法调用 Object.wait() 而没有获取到该对象的对象锁。调用 wait()而没有持有该对象的对象锁,将导致 IllegalMonitorStateException 异常。
案例
解决方法
112. UL_UNRELEASED_LOCK
类型
必改项
描述
This method acquires a JSR-166 (java.util.concurrent) lock, but does not release it on all paths out of the method. In general, the correct idiom for using a JSR-166 lock is:
Lock l = ...;
l.lock();
try {
// do something
} finally {
l.unlock();
}
方法获得了当前的对象所,但是在方法中始终没有释放它
案例
Lock l = ...;
l.lock();
try {
// do something
} finally {
l.unlock();
}
解决方法
FindBugs 2.0.1 RC3 发布

FindBugs 2.0.1 发布了第三个 RC 版本,下载地址:findbugs-2.0.1-rc3.zip (8.3 MB)
FindBugs 是一个能静态分析源代码中可能会出现 Bug 的 Eclipse 插件工具。
我们今天的关于findbugs和数据库密码安全性问题和数据库中的访问密钥和安全锁的分享就到这里,谢谢您的阅读,如果想了解更多关于2.findbugs 总结、Debian 11.2 发布,修复 Bug 及安全性问题、findbugs、FindBugs 2.0.1 RC3 发布的相关信息,可以在本站进行搜索。
本文标签: