小白日记[StackOverflowError与OutOfMemoryError]

小白一枚,请多指教

小白今日任务:熟悉StackOverflowError与OutOfMemoryError

1、重现StackOverflowError

找到StackOverflowError源码

package java.lang;

/**
 * Thrown when a stack overflow occurs because an application
 * recurses too deeply.
 *
 * @author unascribed
 * @since   JDK1.0
 */
public
class StackOverflowError extends VirtualMachineError {

根据源码注释可以知道产生StackOverflowError原因是 because an application recurses too deeply,翻译过来也就是递归层数过深,知道原因之后就可以写一个很简单的demo,如下

public static void main(String[] args) {
        main(null);
}

"如愿以偿"的得到了我们想要的StackOverflowError

Exception in thread "main" java.lang.StackOverflowError

2、探索StackOverflowError

1)源码中只是轻描淡写的一句because an application recurses too deeply 会造成StackOverflowError,那到底递归的临界点在哪里呢?

既然是栈内存溢出,想找到临界点,我们就得找寻栈内存的大小,参考oracle官方文档给出的关于HotSpot的表格:

 可以看到"0 means use default stack size",也就是说在不做任何设置的情况下,就使用默认的栈内存,也就是如果是主流64位系统栈内存默认是1024KB(用户可以通过-Xss设置栈内存大小)

2)知道了栈内存后,那到底深度递归做了什么会”压死“栈内存呢?

首先要知道栈内存中都存储着什么?通过查阅资料,知道每次调用方法都会产生”栈帧“压入栈内存中,”栈帧“的大小取决于方法的参数、局部变量和算法,可以简单地把专业名词”栈帧“理解为方法,在深度递归中,大量的方法压入了栈内存并且短时间无法得到释放,加上默认的栈内存只有可怜的1M,很快就会消耗完栈内存,造成异常

3、重现OutOfMemoryError

同样我们也找到OutOfMemoryError的源码

package java.lang;

/**
 * Thrown when the Java Virtual Machine cannot allocate an object
 * because it is out of memory, and no more memory could be made
 * available by the garbage collector.
 *
 * {@code OutOfMemoryError} objects may be constructed by the virtual
 * machine as if {@linkplain Throwable#Throwable(String, Throwable,
 * boolean, boolean) suppression were disabled and/or the stack trace was not
 * writable}.
 *
 * @author  unascribed
 * @since   JDK1.0
 */
public class OutOfMemoryError extends VirtualMachineError {

可以很直接的看到"no more memory could be made","cannot allocate an object"这些语句,表示JVM已经无法为对象分配内存而造成异常

为了最快速度Full GC报错,可以调整下JVM内存大小,如下在IDEA中调整运行时JVM内存为10M

 接下来,占满10M我们只要制造一个超过10M的对象即可,如下新建一个11M的byte数组

 public static void main(String[] args) {
        byte[] bytesArray = new byte[11 * 1024 * 1024];
 }

"如愿以偿"的得到了我们想要的OutOfMemoryError

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

4、探索OutOfMemoryError

1)我们也如法炮制的找一下堆内存默认的临界值,堆内存大小我们可以借助api查询,如下为源码部分截取

   /**
     * Returns the total amount of memory in the Java virtual machine.
     * The value returned by this method may vary over time, depending on
     * the host environment.
     * <p>
     * Note that the amount of memory required to hold an object of any
     * given type may be implementation-dependent.
     *
     * @return  the total amount of memory currently available for current
     *          and future objects, measured in bytes.
     */
    public native long totalMemory();

    /**
     * Returns the maximum amount of memory that the Java virtual machine will
     * attempt to use.  If there is no inherent limit then the value {@link
     * java.lang.Long#MAX_VALUE} will be returned.
     *
     * @return  the maximum amount of memory that the virtual machine will
     *          attempt to use, measured in bytes
     * @since 1.4
     */
    public native long maxMemory();

根据源码的注释,totalMemory可以获取当前程序运行JVM使用的内存,maxMemory可以获取JVM可以使用的最大内存,

默认情况下JVM最大会占用系统内存的四分之一,因为JVM大部分内存都分配给堆使用,所以我们可以粗略的认为查询结果即为堆内存,JVM的调优就是在堆内存的分配上面下功夫

2)引入到JVM,这次的探索也就差不多了,漫漫JAVA路的开头,JVM还是有点遥远的东西,希望有一天JVM探索可以出现在我的日记里,希望那时已不是小白,仅此以记,与君共勉^^

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值