「java整除溢出」java 溢出
今天给各位分享java整除溢出的知识,其中也会对java 溢出进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、java 数据溢出处理
- 2、java 算出溢出处理
- 3、如何检查和解决java虚拟机内存溢出的问题
- 4、java那个整数运算符不会存在溢出行为
- 5、java栈内存溢出怎么解决
- 6、java数据溢出怎么处理?
java 数据溢出处理
int 类型在 Java 中是“有符号”的。所谓“有符号”就是有正负。在计算机中用二进制表示所有的信息,这个符号的区别就看首位。
首位如果是 0,就是正的,1 就是负的。正与负的区别也因此就在于取反加一。这不仅在 Java,在任何语言中都是这样的。
所谓数值溢出就会出现这个现象。Java 中的 int 总共就 32 位,正数上限的情况首位也只能是 0,其他位都可以是 1(就是 2^31-1 的情况)。但是如果正数过大了,例如 2^31,计算机不得不把首位变成 1,并且很快就忘了这是溢出情况,把它按照正常的方式输出了,于是就成了负的。其实也不能怪它,它没有办法自动处理超过溢出的情况,因为 32 位是固定的,它不能因为溢出而临时扩展到 33 位之类的。
以上是负数的情况。溢出变成 0 的话道理也一样。你想如果一个数大到最后 32 位都是 0 了,那计算机只能把它认作 0。这种情况有很多,例如 2^32 就是一共 33 位,首位 1,后面 32 位都是 0。
java 算出溢出处理
帅哥。。。
System.out.println("int的最小值="+Integer.MIN_VALUE);
System.out.println("int的最大值="+Integer.MAX_VALUE);
查看下java中int表示的最大值和最小值,我看跟你写的不一样。。。
有不懂的再问,你现在b存的数没有溢出。。。。
如何检查和解决java虚拟机内存溢出的问题
一,jvm内存区域
1, 程序计数器
一块很小的内存空间,作用是当前线程所执行的字节码的行号指示器。
2, java栈
与程序计数器一样,java栈(虚拟机栈)也是线程私有的,其生命周期与线程相同。通常存放基本数据类型,对象引用(一个指向对象起始地址的引用指针或一个代表对象的句柄),reeturnAddress类型(指向一条字节码指令的地址)
栈区域有两种异常类型:如果线程请求的栈深度大于虚拟机所允许的深度,将抛StrackOverflowError异常;如果虚拟机栈可以动态扩展(大部分虚拟机都可动态扩展),当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常。
3, 本地方法栈
与虚拟机栈作用很相似,区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则是为虚拟机用到的Native方法服务。和虚拟机栈一样可能抛出StackOverflowError和OutOfMemoryError异常。
4, java堆
java
Heap是jvm所管理的内存中最大的区域。JavaHeap是被所有线程共享的一块内存区域,在虚拟机启动时创建。主要存放对象实例。JavaHeap
是垃圾收集器管理的主要区域,其可细分为新生代和老年代。如果在堆中没有内存完成实例分配,并且也无法再扩展时,会抛出OutOfMemoryError
异常。
5, 方法区
与javaHeap一样是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息、常量、静态变量、及时编译器编译后的代码等数据。当方法区无法满足内
存分配的需求时,将抛出OutOfMemoryError异常。方法同时包含常听说的运行时常量池,用于存放编译期生成的各种字面量和符号引用。
6, 直接内存
直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,是jvm外部的内存区域,这部分区域也可能导致OutOfMemoryError异常。
二,jvm参数
-Xss(StackSpace)栈空间
-Xms ,-Xmx(heap memory
space)堆空间:Heap是大家最为熟悉的区域,他是jvm用来存储对象实例的区域,Heap在32位的系统中最大为2G,其大小通过-Xms和
-Xmx来控制,-Xms为jvm启动时申请的最小Heap内存,默认为物理内存的1/64,但小于1G,-Xmx为jvm可申请的最大的Heap内存,
默认为物理内存的1/4,一般也小于1G,默认当空余堆内存小于40%时,jvm会最大Heap的大小到-Xmx指定大小,可通过
-XX:MinHeapFreeRatio来指定这个比例,当空余堆内存大于70%时,JVM会将Heap的大小往-Xms指定的大小调整,可通过
-XX:MaxHeapFreeRatio来指定这个比例,但通常为了避免频繁调整HeapSize的大小,将-Xms和-Xmx的值设为相同。
-XX:PermSize -XX:MaxPermSize :方法区持久代大小: 方法区域也是全局共享的,在一定的条件下它也会被 GC ,当方法区域需要使用的内存超过其允许的大小时,会抛出 OutOfMemory 的错误信息。
三,常见内存溢出错误解决办法
1, OutOfMemoryError异常
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能,
Java Heap 溢出
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。
出现这种异常,一般手段是先通过内存映像分析工具(如Eclipse Memory
Analyzer)对dump出来的堆转存快照进行分析,重点是确认内存中的对象是否是必要的,先分清是因为内存泄漏(Memory
Leak)还是内存溢出(Memory Overflow)。
如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。于是就能找到泄漏对象时通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收。
如果不存在泄漏,那就应该检查虚拟机的参数(-Xmx与-Xms)的设置是否适当。
2, 虚拟机栈和本地方法栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常
这里需要注意当栈的大小越大可分配的线程数就越少。
3, 运行时常量池溢出
异常信息:java.lang.OutOfMemoryError:PermGen space
如果要向运行时常量池中添加内容,最简单的做法就是使用String.intern()这个Native方法。该方法的作用是:如果池中已经包含一个等于
此String的字符串,则返回代表池中这个字符串的String对象;否则,将此String对象包含的字符串添加到常量池中,并且返回此String
对象的引用。由于常量池分配在方法区内,我们可以通过-XX:PermSize和-XX:MaxPermSize限制方法区的大小,从而间接限制其中常量
池的容量。
4, 方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。
异常信息:java.lang.OutOfMemoryError:PermGen space
方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,判定条件是很苛刻的。在经常动态生成大量Class的应用中,要特别注意这点。
java那个整数运算符不会存在溢出行为
数溢出
Java-随便学学-整数溢出问题

是谁在学习
0.开头
这次的问题基于上一篇的变量值互换程序,也就是不引入第三个变量的互换。
1.整数溢出究竟是什么?
首先,以int为例,我们知道int由32位二进制数据表示,其中最高位表示正负号,1表示负数,0表示正数,所以int的取值范围是[-2 ^ 31 , 2 ^ 31-1].并且其中1000 0000 0000 0000 0000 0000 0000 0000表示的是-2 ^ 31,全0则表示0。
然后,设想一种情况,两个int类型相加超过了int所能表示的范围会发生什么?
public class Temp {
public static void main(String[]args){
int a = 2147483647;
int b = a+1;//a+1理论上等于2147483648,也就是2的31次方
int c = a+2;//a+2理论上等于2147483649,也就是2的31次方+1
//实际输出
System.out.println("b="+b);
System.out.println("c="+c);
}
}
登录后复制
b=-2147483648
c=-2147483647
登录后复制
a+1理论上等于2147483648,也就是2的31次方;
a+2理论上等于2147483649,也就是2的31次方+1;
实际输出却变成了负数,难道是计算机出错了吗?
实际上,计算没有错,我们可以看一下a,b,c对应的二进制形式;
System.out.println("a的二进制形式:"+Integer.toBinaryString(a));
System.out.println("b的二进制形式:"+Integer.toBinaryString(b));
System.out.println("c的二进制形式:"+Integer.toBinaryString(c));
登录后复制
a的二进制形式:1111111111111111111111111111111
b的二进制形式:10000000000000000000000000000000
c的二进制形式:10000000000000000000000000000001
登录后复制
根据二进制的表现,我们可以看出,其实计算机并没有算错,只不过在int表示的数字当中,首位被当做了符号(正负号),所以计算结果才会出现问题。
2.为什么计算溢出了没有影响数值转化结果?
我们看一下这个变量数值互换程序:
public class ValueExchange {
public static void main(String[]args){
int a1 = 2147483646;
int b1 = 2147483647;
a1 = a1+b1;
System.out.println("a1中间值为:"+a1);
b1 = a1-b1;
a1 = a1-b1;
System.out.println("a1="+a1);
System.out.println("b1="+b1);
}
}
登录后复制
a1中间值为:-3
a1=2147483647
b1=2147483646
登录后复制
这个程序显然在a1=a1+b1;这行出现了溢出问题;那么问题来了,为什么它没有造成最后的互换结果出错呢?
之前我们提到,在实际计算的时候,计算机并没有出错,只不过是首位被当成了符号而已。我们打印一下a1的中间值:
a1中间值二进制形式为:11111111111111111111111111111101
登录后复制
这个数值如果用long类型表示,实际的值:
System.out.println("a1中间值二进制形式转化为long类型:"+Long.parseLong(Integer.toBinaryString(a1),2));
登录后复制
结果是
a1中间值二进制形式转化为long类型:4294967293
登录后复制
正好是a1+b1(2147483646+2147483647)的理论值,所以这里我们说计算机的计算并没有出错。
下面的两行给b1和a1重新赋值的代码一定也是这种情况,而且在计算之后,刚好他们的值在int能够表示的范围里,所以才导致最终结果没有问题。
此处的小结论:在变量值互换的方法中,如果计算过程没有问题,而最后的结果极有可能还是正确的。
3.其他情况?
你们或许注意到了,我在上面的结论中,并没有肯定的表示计算一定不会出现问题。我们将上面的程序进行修改:
将a1和b1的值都变成负数,也就是二进制形式的首位都变成了1。
为什么要这样做修改?是因为之前讨论的情况当中,两个正数int值相加的时候,结果不可能出现33位,也就是首位都是0的两个数,是不会因为最高位进位导致进一步溢出的。所以既然计算是不会出问题的,那么这样修改,是为了让结果进一步溢出,让int直接丢失掉真实的最高位。
public class Temp {
public static void main(String[]args){
int a1 = -2147483646;
int b1 = -2147483647;
a1 = a1+b1;
System.out.println("a1中间值为:"+a1);
System.out.println("a1中间值二进制形式为:"+Integer.toBinaryString(a1));
System.out.println
("a1中间值二进制形式转化为long类型:"+Long.parseLong(Integer.toBinaryString(a1),2));
b1 = a1-b1;
a1 = a1-b1;
System.out.println("a1="+a1);
System.out.println("b1="+b1);
}
}
登录后复制
果然,我们发现,a1的形式已经不是a1+b1(-2147483646-2147483647)的理论值了,原因正如我的修改目的所说,最高位(结果33位)丢了。
a1中间值为:3
a1中间值二进制形式为:11
a1中间值二进制形式转化为long类型:3
a1=-2147483647
b1=-2147483646
登录后复制
但是最后的交换结果还是没有问题,这又是为什么呢?真是纳了闷了??
这时,我们发现a1 = a1+b1;这句的分析是没有问题的,也就是结果为3的这一步;
出现问题的地方在下一步b1 = a1-b1;这一步再一次发生了溢出这里的溢出使得最后结果又转了回来,转到了正确答案上!惊了!
java栈内存溢出怎么解决
第一对所有的代码包括页面中的java代码都进行一遍彻底的回顾检查,
1.对那些静态(static)的对象要特别留神,特别是类型为Map,List,Set的,静态的变量会一直驻存在内存中,生命周期比较长,不会被垃圾器回收。
2.对于代码,要审查是否生成了大量的冗余的对象,还有一些逻辑业务处理的类,
算法是否过于复杂,调整算法,对于代码认真审查,再仔细重构一遍代码,能提高代码质量,提高程序运行稳定性。
3.Java中的内存溢出大都是因为栈中的变量太多了。其实内存有的是。建议不用的尽量设成null以便回收,多用局部变量,少用成员变量。
1),变量所包含的对象体积较大,占用内存较多。
2),变量所包含的对象生命周期较长。
3),变量所包含的对象数据稳定。
4),该类的对象实例有对该变量所包含的对象的共享需求。
4.在我的程序中对静态变量的优化后,使程序占用内存量至少提升了5k-10k。所以也不容忽视。
第二还有就是String类相关的东西:
1.字符串累加的时候一定要用StringBuffer的append方法,不要使用+操作符连接两个字符串。差别很大。而且在循环或某些重复执行的动作中不要去创建String对象,因为String对象是要用StringBuffer对象来处理的,一个String对象应该是产生了 3个对象(大概是这样:))。
2.字符串length()方法来取得字符串长度的时候不要把length放到循环中,可以在循环外面对其取值。(包括vector的size方法)。特别是循环次数多的时候,尽量把length放到循环外面。
int size = xmlVector.size();
for (int i = 2; i size; i++) {
。。。
}
3 写代码的时候处理内存溢出
try{
//do sth
....
}catch (outofmemoryerror e){//可以用一个共通函数来执行.
system.out.print (“no memory! ”);
system.gc();
//do sth again
....
}
4.对于频繁申请内存和释放内存的操作,还是自己控制一下比较好,但是System.gc()的方法不一定适用,最好使用finallize强制执行或者写自己的finallize方法。 Java 中并不保证每次调用该方法就一定能够启动垃圾收集,它只不过会向JVM发出这样一个申请,到底是否真正执行垃圾收集,一切都是个未知数。
java数据溢出怎么处理?
这是常见的错误,下标越界. for(int i=0;i=aa.length();i++)这句i=aa.length()有问题,改为iaa.length();
java整除溢出的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java 溢出、java整除溢出的信息别忘了在本站进行查找喔。