==和equals
不久前,由於線上RPC框架切換,我們就發生了一點小問題。
本來,線上的接口是這樣定義的:
然后,接口查詢中使用到了一個枚舉類型,根據id獲取枚舉值,只不過這里使用的是==號來判斷。
調用方的寫法:
本來,這個代碼在線上跑了兩年了,一點問題沒有,怎么就突然不行了呢?
但是,切換框架之后,這個接口報錯了,當時我也看了這個地方半天,猜測是這里的問題,但是想了想貌似又不應該啊。
結果最后發現,原來的RPC框架傳輸中使用的是valueOf,從緩存中取值,加上自動裝箱拆箱,判斷可以通過。但是,新的框架使用的是new Byte(),所以這個老代碼就永遠無法通過了,因為這是一個新的對象。
看看這個測試的結果。
后面,通過安裝Alibaba Java Coding Guidelines
插件統一掃描所有代碼,還又發現了一個坑爹的問題。
這個寫法又不太一樣,這個枚舉只是單純的把code成員變量定義成了byte
基礎類型,不是包裝類型。這樣,代碼用==判斷又都OK了。
想象一下,因為是基礎數據類型,拆箱后==判斷當然是通過的。
還有更奇葩的寫法,成員變量是Byte
包裝類型,getEnumByCode(byte code)
這里用的又是基礎類型,當然,這種寫法也能判斷通過。
所以,心累... ...
最后,我想再補充一下關於基礎數據類型緩存的知識。能用==判斷的原因也都是依賴於緩存的原因。
數據類型 | 包裝類型 | 緩存類型 | 緩存值范圍 |
---|---|---|---|
byte | Byte | ByteCache | -128~127 |
short | Short | ShortCache | -128~127 |
int | Integer | IntegerCache | -128~127 |
long | Long | LongCache | -128~127 |
char | Character | CharacterCache | 0~127 |
最后,奉勸大家一句,千萬,千萬,在項目中判斷包裝數據類型都用equals
,因為就算這段代碼你很確信現在是對的,然而鬼都不知道后面會發生什么!不要抱有僥幸心理。
日志打滿
項目技改上線后不久,發現接口成功率直接跌0(跌0的告警監控必須得有,不然死都不知道怎么死的)。排查了很久,看其他都是正常的,最后發現GC耗時狂增,登錄服務器一看,居然是硬盤被打滿了。
然后果斷去看日志,因為我們的硬盤實際上很小,先懷疑日志,果不其然,日志炸了。通過ls -lht
查看文件大小。
通過rm -rf
刪除后發現硬盤空間並沒有釋放。正常情況下是不會出現這個問題的,但是如果文件被鎖定或者有另外的進程在向文件寫數據的話就會有問題了。
在Linux中,一個文件在文件系統中存放包含兩個部分:
-
指針部分:指針位於文件系統的meta-data中,在將數據刪除后,這個指針就從meta-data中清除了。
-
數據部分:而數據部分存儲在磁盤中。
像上面的情況,雖然我們刪除了service.log
,但是由於進程鎖定,指針部分沒有從meta-data中刪除,所以也就看到存儲空間沒有釋放的問題。
解決辦法有兩種:
-
使用
lsof -n |grep delete
查看什么進程在寫service.log,通過命令發現是我們的java進程在一直寫文件,然后通過后台工具直接重啟應用,重啟之后發現恢復正常。 -
清空日志文件,執行命令
echo "">/service.log