java中double強(qiáng)制轉(zhuǎn)換int引發(fā)的OOM問(wèn)題記錄
問(wèn)題代碼
最近出現(xiàn)了一次OOM問(wèn)題,問(wèn)題代碼如下
public void prcess(double total, int step) {
int num = (int) Math.floor(total / step);
while (num-- > 0) {
doSomething(); // 普通方法,占用內(nèi)存不大
}
}根據(jù)單步步長(zhǎng)step將total值劃分后,然后進(jìn)行處理。然后日志中發(fā)現(xiàn)堆棧在doSomething()時(shí)報(bào)錯(cuò)OOM,拋出java.lang.OutOfMemoryError。確認(rèn)過(guò)doSomething()方法不會(huì)占用過(guò)大的內(nèi)存,那為何會(huì)發(fā)生問(wèn)題?
排查過(guò)程
懷疑num過(guò)大導(dǎo)致,查看入?yún)otal為合理值,但是step是取配置值,配置未配置時(shí)默認(rèn)為0,則問(wèn)題代碼為int num = (int) Math.floor(total / step);,這里step為0,Math.floor(total / step) = Infinity,強(qiáng)制轉(zhuǎn)為int后得到值為2147483647。一直在處理此處的邏輯導(dǎo)致內(nèi)存增長(zhǎng),進(jìn)而發(fā)生OOM
double特殊值與強(qiáng)制轉(zhuǎn)換
java語(yǔ)言中浮點(diǎn)運(yùn)算存在兩個(gè)值:NaN與Infinity
NaN
Not-a-Number,非數(shù)字值,數(shù)學(xué)上0/0是無(wú)意義的,java在浮點(diǎn)運(yùn)算中實(shí)現(xiàn)了NaN,定義為0.0/0.0。NaN有如下幾個(gè)特點(diǎn):
NaN與任何數(shù)字都不相等,NaN與其本身也不相等
System.out.println(Double.NaN == Double.NaN); // false System.out.println(Double.NaN == 0.0/0.0); // false System.out.println(Double.NaN == 0.0); // false
使用Double.isNaN或Float.isNaN確認(rèn)是否為NaN
System.out.println(Double.isNaN(0.0/0.0)); // true System.out.println(Float.isNaN(0.0f/0.0f)); // true
NaN與任何數(shù)字比較都是false
System.out.println(Double.NaN > 0.0); // false System.out.println(Double.NaN < 0.0); // false
Infinity
無(wú)限,分為正無(wú)限與負(fù)限小,定義為一個(gè)非0數(shù)字除以0。
有如下幾個(gè)特點(diǎn):
正無(wú)限與負(fù)無(wú)限定義
public static final double POSITIVE_INFINITY = 1.0 / 0.0; public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
無(wú)限與任何非無(wú)限非0數(shù)字運(yùn)算仍為無(wú)限
System.out.println(Double.POSITIVE_INFINITY + Double.MAX_VALUE); // Infinity System.out.println(Double.POSITIVE_INFINITY - Double.MAX_VALUE); // Infinity System.out.println(Double.POSITIVE_INFINITY * Double.MAX_VALUE); // Infinity System.out.println(Double.POSITIVE_INFINITY / Double.MAX_VALUE); // Infinity System.out.println(Double.NEGATIVE_INFINITY + Double.MIN_VALUE); // -Infinity System.out.println(Double.NEGATIVE_INFINITY - Double.MIN_VALUE); // -Infinity System.out.println(Double.NEGATIVE_INFINITY * Double.MIN_VALUE); // -Infinity System.out.println(Double.NEGATIVE_INFINITY / Double.MIN_VALUE); // -Infinity
無(wú)限與0運(yùn)算為無(wú)限或NaN
System.out.println(Double.POSITIVE_INFINITY / 0); // Infinity System.out.println(Double.POSITIVE_INFINITY * 0); // NaN System.out.println(Double.NEGATIVE_INFINITY / 0); // -Infinity System.out.println(Double.NEGATIVE_INFINITY * 0); // NaN
負(fù)無(wú)限與正無(wú)限運(yùn)算為無(wú)限或NaN
System.out.println(Double.POSITIVE_INFINITY + Double.NEGATIVE_INFINITY); // NaN System.out.println(Double.POSITIVE_INFINITY - Double.NEGATIVE_INFINITY); // Infinity System.out.println(Double.NEGATIVE_INFINITY + Double.POSITIVE_INFINITY); // NaN System.out.println(Double.NEGATIVE_INFINITY - Double.POSITIVE_INFINITY); // -Infinity System.out.println(Double.POSITIVE_INFINITY * Double.NEGATIVE_INFINITY); // -Infinity System.out.println(Double.POSITIVE_INFINITY / Double.NEGATIVE_INFINITY); // NaN System.out.println(Double.NEGATIVE_INFINITY * Double.POSITIVE_INFINITY); // -Infinity System.out.println(Double.NEGATIVE_INFINITY / Double.POSITIVE_INFINITY); // NaN
無(wú)限強(qiáng)制轉(zhuǎn)換為整形會(huì)有精度丟失
System.out.println((int)Double.POSITIVE_INFINITY); // Integer.MAX_VALUE System.out.println((int)Double.NEGATIVE_INFINITY); // Integer.MIN_VALUE System.out.println((long) Double.POSITIVE_INFINITY); // Long.MAX_VALUE System.out.println((long)Double.NEGATIVE_INFINITY); // Long.MIN_VALUE
到此這篇關(guān)于java中double強(qiáng)制轉(zhuǎn)換int引發(fā)的OOM問(wèn)題的文章就介紹到這了,更多相關(guān)java強(qiáng)制轉(zhuǎn)換double轉(zhuǎn)int內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于java編譯過(guò)程中的bug說(shuō)明
本篇文章是對(duì)java編譯過(guò)程中的bug進(jìn)行了詳細(xì)的說(shuō)明介紹,需要的朋友參考下2013-05-05
JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng)
這篇文章主要為大家詳細(xì)介紹了JAVA使用隨機(jī)數(shù)實(shí)現(xiàn)概率抽獎(jiǎng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
Spring Schedule Task動(dòng)態(tài)改寫(xiě)Cron配置方式
這篇文章主要介紹了Spring Schedule Task動(dòng)態(tài)改寫(xiě)Cron配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
數(shù)據(jù)定位在java購(gòu)物車系統(tǒng)中的應(yīng)用
實(shí)現(xiàn)"加入購(gòu)物車"功能,數(shù)據(jù)定位至關(guān)重要,它通過(guò)用戶ID和商品ID等標(biāo)識(shí)符實(shí)現(xiàn)快速查詢和數(shù)據(jù)一致性,主鍵、外鍵和聯(lián)合索引等數(shù)據(jù)庫(kù)技術(shù),以及Redis緩存和并發(fā)控制策略如樂(lè)觀鎖或分布式鎖,共同保障了購(gòu)物車系統(tǒng)的查詢效率和數(shù)據(jù)安全,這些機(jī)制對(duì)高并發(fā)和大數(shù)據(jù)量的場(chǎng)景尤為重要2024-10-10
SpringBoot整合ShardingSphere5.x實(shí)現(xiàn)數(shù)據(jù)加解密功能(最新推薦)
這篇文章主要介紹了SpringBoot整合ShardingSphere5.x實(shí)現(xiàn)數(shù)據(jù)加解密功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06

