• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

除了程序计数器之外,虚拟机中还有其他几个运行时区域,其中可能会发生OutOfMemoryError异常。

Java堆溢出

将Idea堆的大小设置为20MB,这是不可扩展的(-Xms参数设置为与maximum -Xmx参数相同,以避免自动扩展)

suaetmrqapq4371.png

-verbose : GC-xms 20m-xmx20 m-xmn 10m-XX: printgc details-XX: survivorratio=8

运行以下代码:

包内存;

导入Java . util . ArrayList;

导入Java . util . list;

公共级鞋袜{

静态类OOMObject {

}

公共静态void main(String[] args){

listoom object list=new ArrayList();

while (true){

list . add(new oom object());

}

}

}

引发的错误:

线程“main”Java . lang . out of memory error : Java堆空间中出现异常

位于Java . base/Java . util . arrays . copy of(arrays . Java :3512)

位于Java . base/Java . util . arrays . copy of(arrays . Java :3481)

位于Java . base/Java . util . ArrayList . grow(ArrayList . Java :237)

位于Java . base/Java . util . ArrayList . grow(ArrayList . Java :244)

位于Java . base/Java . util . ArrayList . add(ArrayList . Java :454)

位于Java . base/Java . util . ArrayList . add(ArrayList . Java :467)

在记忆中。hee poom . main(hee poom . Java :14)

解决这个异常的重点是确认内存中的对象是否必要,也就是区分是内存泄漏还是内存溢出。

内存泄漏:一个程序申请内存后,无法释放申请的内存空间,内存溢出将是多次内存泄漏的结果。

内存溢出:当程序申请内存时,申请人没有足够的内存。

如果是内存泄漏,可以通过工具进一步检查泄漏对象到GC根的引用链。然后我们就可以发现泄露的对象是如何与GC Root关联的,这使得垃圾收集器无法自动收集它们。

如果没有泄漏,就要检查虚拟机堆参数(-Xmx和-Xms),对比机器的物理内存看是否可以放大,检查代码看是否有些对象的生命周期太长,持有时间太长,尽量减少长时间运行时的内存消耗。

虚拟机栈和本地方法栈溢出

如果线程请求的堆栈深度大于虚拟机允许的最大深度,则会引发StackOverflowError异常。

如果虚拟机在扩展堆栈时无法申请足够的内存,它会抛出OutOfMemoryError异常。

包内存;

公共类JavaVmStackSOF {

private int stack length=1;

public void stackLeak(){

stackLength

stack leak();

}

/**

*-xs 180K-设置每个线程分配180k内存

* @param args

* @throws可投掷的

*/

公共静态void main(String[] args)抛出Throwable{

JavaVmStackSOF oom=new JavaVmStackSOF();

尝试{

oom . stack leak();

}catch(可投掷e){

system . out . println(' stack length : ' oom . stack length);

扔e;

}

}

}

re>

运行结果:

Exception in thread "main" java.lang.StackOverflowError
stack length:1554
    at memory.JavaVmStackSOF.stackLeak(JavaVmStackSOF.java:7)
package memory;
public class JavaVMStackOOM {
   private void dontStop(){
       while (true){
       }
   }
   public  void  stackLeakByThread(){
       while (true){
           Thread thread = new Thread(new Runnable() {
               @Override
               public void run() {
                   dontStop();
               }
           });
           thread.start();
       }
   }
   /**
    * -Xss2M -设置每个线程分配2M内存
    * 最终会耗尽所有内存,导致没有足够的内存创建线程而抛出异常:OutOfMemoryError
    * @param args
    * @throws Throwable
    */
   public static void main(String[] args) throws Throwable{
       JavaVMStackOOM oom = new JavaVMStackOOM();
       oom.stackLeakByThread();
   }
}

运行结果

Exceptuib in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

运行时常量池溢出
运行时常量池属于方法区,因此可以通过以下方式模拟:
java7可以通过设置:-XX:PermSize=10M -XX:MaxPermSize=10M 来限定方法区。
java8之后永久代被移除,-XX:PermSize、-XX:MaxPermSize已经被移除;可以使用:-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M (元空间代替)
类型信息、字段、方法、常量保存在元空间。

package main.java.loadclass;
import java.util.ArrayList;
import java.util.List;
public class RuntimeConstantPoolOOM {
            /**
     * JAVA7 下运行
     * @param args
     */
    public static void main(String[] args){
        //使用LIST保持着常量池引用,避免Full GC 回收常量池行为
        List<String> list = new ArrayList<>();
        //10MB的PermSize在integer范围内足够产生OOM了
        int i = 0;
        while (true){
            list.add(String.valueOf(i++).intern());
        }
    }
}

抛出以下异常:java.lang.OutOfMemoryError:PermGen space

方法区溢出
方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。一个类如果被垃圾回收器回收掉,判定条件非常苛刻,在经常动态生成大量Class的应用中,需要特别注意类的回收状态。

本机直接内存溢出
DirectMemory容量可通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆的最大值(-Xmx指定)一样。
DirectByteBuffer是Java用于实现堆外内存的一个重要类,我们可以通过该类实现堆外内存的创建、使用和销毁。DirectByteBuffer跑出内存溢出异常时并没有真正整整向操作系统申请分配内存,而是通过计算得知内存无法分配,手动跑出异常。
使用Unsafe类的allocateMemory方法是真正分配内存。

package main.java.loadclass;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;
    /**
     * -Xmx20M -XX:MaxDirectMemorySize=10M
     * @param args
     * @throws Exception
     */
    public  static  void main(String[] args) throws Exception{
        Field unsefeField = Unsafe.class.getDeclaredFields()[0];
        unsefeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsefeField.get(null);
        while (true){
            unsafe.allocateMemory(_1MB);
        }
    }
}

返回结果:

Exception in thread "main" java.lang.OutOfMemoryError
    at java.base/jdk.internal.misc.Unsafe.allocateMemory(Unsafe.java:616)
    at jdk.unsupported/sun.misc.Unsafe.allocateMemory(Unsafe.java:462)
    at main.java.loadclass.DirectMemoryOOM.main(DirectMemoryOOM.java:16)

ar55rytvwka4372.png

 

Link to comment
Share on other sites