第五章 堆内存

news2024/12/27 8:56:47

文章目录

  • 前言
  • 一、🚘 本地方法
    • 1、什么是本地方法
    • 2、为什么使用 Native Method
  • 二、🚄 本地方法栈
  • 三、🚥 堆内存
    • 1、-Xms10m -Xmx10m 设置堆内存的大小
    • 2、内存细分
    • 3、设置堆空间的大小与OOM
      • jps 查看Java程序进程
      • jstat -gc 进程号 查看堆内存参数
      • -XX:+PrintGCDetails 设置虚拟机参数,将堆内存情况打印到控制台
    • OutOfMemoryError 内存溢出
    • 4、年轻代与老年代
      • 新生代与老年代的参数设置(一般不会调)
      • -XX:-UseAdaptiveSizePolicy 关闭年轻代中伊甸园区和幸存者区的自适应比例
      • -XX:SurvivorRatio=8 设置年轻代中伊甸园区和幸存者区的内存比例
      • -Xmn:设置新生代的空间的大小。 (一般不设置)
    • 5、图解对象分配过程
    • 6、对象分配的特殊情况
    • 7、常用的调优工具
  • 四、🚒 GC垃圾回收
    • 1、MinorGC / MajorGC / FullGC 的对比
    • 2、测试垃圾回收
  • 五、堆空间的其他细节及总结
    • 1、堆空间的分代思想
    • 2、总结内存分配策略
    • 3、为对象分配内存 TLAB (伊甸园区)
    • 4、小结堆空间的参数设置
    • 5、堆是分配对象的唯一选择吗 ?
      • 逃逸分析
      • 栈上分配
      • 同步策略
      • 标量替换


前言


一、🚘 本地方法

1、什么是本地方法

在这里插入图片描述

package com.atguigu.java;

/**
 * @author shkstart
 * @create 2020 下午 8:53
 */
public class IHaveNatives {
    
    // 被 native 关键字修饰的就是本地方法,有方法体,但是不是Java代码实现的, 
    //native 关键字不能 和 abstract 关键字一起使用
    public native void Native1(int x);

    public native static long Native2();

    private native synchronized float Native3(Object o);

    native void Native4(int[] ary) throws Exception;

}


2、为什么使用 Native Method

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、🚄 本地方法栈

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、🚥 堆内存

在这里插入图片描述
在这里插入图片描述

1、-Xms10m -Xmx10m 设置堆内存的大小

测试 将下面两个类的堆空间大小分别设置 10mb 和 20 mb

package com.atguigu.java;

/**
 * -Xms10m -Xmx10m
 *
 * @author shkstart  shkstart@126.com
 * @create 2020  16:41
 */
public class HeapDemo {
    public static void main(String[] args) {
        System.out.println("start...");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("end...");
    }

}

package com.atguigu.java;

/**
 * -Xms20m -Xmx20m
 * @author shkstart  shkstart@126.com
 * @create 2020  16:42
 */
public class HeapDemo1 {
    public static void main(String[] args) {
        System.out.println("start...");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("end...");
    }
}

在这里插入图片描述

在这里插入图片描述

把上面两个代码跑起来,然后去JDK的安装目录找到,虚拟机监控运行起来。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、内存细分

堆内存从逻辑上划分是三部分,年轻代,老年代,元空间。但是实际上元空间更偏向于方法区,所以堆空间我们还是看年轻代和老年代两部分。

在这里插入图片描述

3、设置堆空间的大小与OOM

在这里插入图片描述

package com.atguigu.java;

/**
 * 1. 设置堆空间大小的参数
 * -Xms 用来设置堆空间(年轻代+老年代)的初始内存大小
 *      -X 是jvm的运行参数
 *      ms 是memory start
 * -Xmx 用来设置堆空间(年轻代+老年代)的最大内存大小
 *
 * 2. 默认堆空间的大小
 *    初始内存大小:物理电脑内存大小 / 64
 *             最大内存大小:物理电脑内存大小 / 4
 * 3. 手动设置:-Xms600m -Xmx600m
 *     开发中建议将初始堆内存和最大的堆内存设置成相同的值。
 *
 * 4. 查看设置的参数:方式一: jps   /  jstat -gc 进程id
 *                  方式二:-XX:+PrintGCDetails
 * @author shkstart  shkstart@126.com
 * @create 2020  20:15
 */
public class HeapSpaceInitial {
    public static void main(String[] args) {

        //返回Java虚拟机中的堆内存总量
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        //返回Java虚拟机试图使用的最大堆内存量
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;

        System.out.println("-Xms : " + initialMemory + "M");
        System.out.println("-Xmx : " + maxMemory + "M");

//        System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");
//        System.out.println("系统内存大小为:" + maxMemory * 4.0 / 1024 + "G");

        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

jps 查看Java程序进程

在这里插入图片描述

jstat -gc 进程号 查看堆内存参数

在这里插入图片描述

-XX:+PrintGCDetails 设置虚拟机参数,将堆内存情况打印到控制台

OutOfMemoryError 内存溢出

设置堆大小

在这里插入图片描述

执行程序

package com.atguigu.java;

import java.util.ArrayList;
import java.util.Random;

/**
 * -Xms600m -Xmx600m
 * @author shkstart  shkstart@126.com
 * @create 2020  21:12
 */
public class OOMTest {
    public static void main(String[] args) {
        ArrayList<Picture> list = new ArrayList<>();
        while(true){
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            list.add(new Picture(new Random().nextInt(1024 * 1024)));
        }
    }
}

class Picture{
    private byte[] pixels;

    public Picture(int length) {
        this.pixels = new byte[length];
    }
}

堆内存拉满
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、年轻代与老年代

在这里插入图片描述

新生代与老年代的参数设置(一般不会调)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

-XX:-UseAdaptiveSizePolicy 关闭年轻代中伊甸园区和幸存者区的自适应比例

-XX:SurvivorRatio=8 设置年轻代中伊甸园区和幸存者区的内存比例

在这里插入图片描述
在这里插入图片描述

-Xmn:设置新生代的空间的大小。 (一般不设置)

5、图解对象分配过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

伊甸园区满了会进行垃圾回收,幸存者放入 01 区,当幸存者过多时,01 区装不下仍然不会进行垃圾回收,而是直接让多出的幸存者进入老年代。

6、对象分配的特殊情况

在这里插入图片描述

7、常用的调优工具

在这里插入图片描述

四、🚒 GC垃圾回收

1、MinorGC / MajorGC / FullGC 的对比

对于程序的调优,我们更多关注的是尽量减少 垃圾回收的次数,因为每次垃圾回都会让用户线程停止工作。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2、测试垃圾回收

字符串常量池以前在方法区,现在在堆空间

package com.atguigu.java1;

import java.util.ArrayList;
import java.util.List;

/**
 * 测试MinorGC 、 MajorGC、FullGC
 * -Xms9m -Xmx9m -XX:+PrintGCDetails
 * @author shkstart  shkstart@126.com
 * @create 2020  14:19
 */
public class GCTest {
    public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "atguigu.com";
            while (true) {
                list.add(a);
                a = a + a;
                i++;
            }

        } catch (Throwable t) {
            t.printStackTrace();
            System.out.println("遍历次数为:" + i);
        }
    }
}


五、堆空间的其他细节及总结

1、堆空间的分代思想

在这里插入图片描述
在这里插入图片描述

2、总结内存分配策略

在这里插入图片描述
在这里插入图片描述


package com.atguigu.java1;

/** 测试:大对象直接进入老年代
 * -Xms60m -Xmx60m -XX:NewRatio=2 -XX:SurvivorRatio=8 -XX:+PrintGCDetails
 * @author shkstart  shkstart@126.com
 * @create 2020  21:48
 */
public class YoungOldAreaTest {
    public static void main(String[] args) {
        byte[] buffer = new byte[1024 * 1024 * 20];//20m

    }
}

3、为对象分配内存 TLAB (伊甸园区)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、小结堆空间的参数设置

在这里插入图片描述
在这里插入图片描述

5、堆是分配对象的唯一选择吗 ?

在这里插入图片描述

逃逸分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

package com.atguigu.java2;

/**
 * 逃逸分析
 *
 *  如何快速的判断是否发生了逃逸分析,大家就看new的对象实体是否有可能在方法外被调用。
 * @author shkstart
 * @create 2020 下午 4:00
 */
public class EscapeAnalysis {

    public EscapeAnalysis obj;

    /*
    方法返回EscapeAnalysis对象,发生逃逸
     */
    public EscapeAnalysis getInstance(){
        return obj == null? new EscapeAnalysis() : obj;
    }
    /*
    为成员属性赋值,发生逃逸
     */
    public void setObj(){
        this.obj = new EscapeAnalysis();
    }
    //思考:如果当前的obj引用声明为static的?仍然会发生逃逸。

    /*
    对象的作用域仅在当前方法中有效,没有发生逃逸
     */
    public void useEscapeAnalysis(){
        EscapeAnalysis e = new EscapeAnalysis();
    }
    /*
    引用成员变量的值,发生逃逸
     */
    public void useEscapeAnalysis1(){
        EscapeAnalysis e = getInstance();
        //getInstance().xxx()同样会发生逃逸
    }
}

在这里插入图片描述
在这里插入图片描述

栈上分配

在这里插入图片描述

package com.atguigu.java2;

/**
 * 栈上分配测试
 * -Xmx1G -Xms1G  -XX:+PrintGCDetails -XX:-DoEscapeAnalysis(关闭逃逸分析)  -XX:-DoEscapeAnalysis(开启逃逸分析)
 * @author shkstart  shkstart@126.com
 * @create 2020  10:31
 */
public class StackAllocation {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        for (int i = 0; i < 10000000; i++) {
            alloc();
        }
        // 查看执行时间
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为: " + (end - start) + " ms");
        // 为了方便查看堆内存中对象个数,线程sleep
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
    }

    private static void alloc() {
        User user = new User();//未发生逃逸
    }

    static class User {

    }
}

同步策略

在这里插入图片描述
在这里插入图片描述

package com.atguigu.java2;

/**
 * 同步省略说明
 * @author shkstart  shkstart@126.com
 * @create 2020  11:07
 */
public class SynchronizedTest {
    public void f() {
        Object hollis = new Object();
        synchronized(hollis) {
            System.out.println(hollis);
        }
    }
}

标量替换

在这里插入图片描述
在这里插入图片描述

package com.atguigu.java2;

/**
 * 标量替换测试
 *  -Xmx100m -Xms100m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-EliminateAllocations
 * @author shkstart  shkstart@126.com
 * @create 2020  12:01
 */
public class ScalarReplace {
    public static class User {
        public int id;
        public String name;
    }

    public static void alloc() {
        User u = new User();//未发生逃逸
        u.id = 5;
        u.name = "www.atguigu.com";
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            alloc();
        }
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为: " + (end - start) + " ms");
    }
}

/*
class Customer{
    String name;
    int id;
    Account acct;

}

class Account{
    double balance;
}


 */

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/602909.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMake构建大型C/C++项目:跨平台设计与高级应用

CMake构建大型C/C项目&#xff1a;跨平台设计与高级应用 一、跨平台设计&#xff08;Cross-Platform Design&#xff09;1.1 跨平台设计原理&#xff08;Principles of Cross-Platform Design&#xff09;1.2 跨平台设计1.2.1 CMake的跨平台特性1.2.2 使用CMake进行跨编译1.2.3…

华为OD机试真题B卷 Java 实现【水仙花数】,附详细解题思路

一、题目描述 所谓水仙花数&#xff0c;是指一个n位的正整数&#xff0c;其各位数字的n次方和等于该数本身。 例如153是水仙花数&#xff0c;153是一个3位数&#xff0c;并且153 1^3 5^3 3^3。 二、输入描述 第一行输入一个整数n&#xff0c;表示一个n位的正整数。n在3到…

【计算机组成原理·笔记】系统总线概念

系统总线概念 各部件之间为了通信&#xff0c;单独连线&#xff0c;太复杂&#xff0c;于是诞生了总线的概念 基本概念 是一组能为多个部分分时共享的公共信息传送路线 总线分类 按传送方式 串行&#xff1a;在总线上1位1位的传输和接收并行&#xff1a;多位在总线上传输…

电脑计算机提示msvcp120.dll丢失该怎么修复

首先&#xff0c;让我们了解一下msvcp120.dll是什么&#xff0c;以及它的作用。msvcp120.dll是一个系统文件。它的作用是提供微软Visual C运行库的函数&#xff0c;以便应用程序可以使用这些函数来实现所需的功能。当您在运行某个程序时&#xff0c;如果发现出现了msvcp120.dll…

【备战秋招】每日一题:4月1日美团春招(二批)第五题:题面+题目思路 + C++/python/js/Go/java带注释

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&…

面试专题:JAVA虚拟机(1)

关于Java虚拟机&#xff0c;在面试的时候一般会问的大多就是①Java内存区域、②虚拟机垃圾算法、③虚拟机垃圾收集 器、④JVM内存管理、⑤JVM调优、⑥Java类加载机制这些问题了。推荐书籍《深入理解Java虚拟机&#xff1a;JVM高级特性 与最佳实践&#xff08;第二版》、《…

嵌入式Linux驱动开发 04:基于设备树的驱动开发

文章目录 目的基础说明开发准备设备树调整驱动程序与测试总结设备树文件内容 目的 前面文章 《嵌入式Linux驱动开发 03&#xff1a;平台&#xff08;platform&#xff09;总线驱动模型》 引入了资源和驱动分离的概念&#xff0c;这篇文章将在前面基础上更进一步&#xff0c;引…

内网或者没有公网IP,如何轻松通过公网访问?

很多网友都面临一个普遍的问题&#xff0c;就是作为家庭宽带用户没有公网IP&#xff0c;即没有IP v4的公网IP&#xff0c;我们天天盼着有一天IP v6能够普及。IP v4一共有2的32次方个地址&#xff0c;约43亿&#xff0c;中国仅为7000多万个&#xff0c;IP v6一共有2的128次方个地…

MySQL8.0版本在CentOS系统的配置教程

1.安装MySQL MySQL安装完成后&#xff0c;会自动配置为名称叫做&#xff1a;mysqld的服务&#xff0c;可以被systemctl所管理&#xff0c;我们在进行系统的配置时&#xff0c;主要修改root密码和允许root远程登录。 # 通过grep命令&#xff0c;在/var/log/mysqld.log文件中&a…

iOS开发:__weak __strong解决Block嵌套

Block使用会存在循环引用的问题&#xff0c;多个Block嵌套使用的情况更复杂&#xff0c;还会出现对象nil的问题。 为什么会循环引用&#xff1f; 现在iOS开发都是在ARC引用计数管理模式下的&#xff0c;参考另一篇文章《Block底层原理》&#xff0c;我们知道Block访问外部变量…

文心一言 VS 讯飞星火 VS chatgpt (29)-- 算法导论5.2 1题

一、在 HIRE-ASSISTANT 中&#xff0c;假设应聘者以随机顺序出现&#xff0c;你正好雇用一次的概率是多少&#xff1f;正好雇用 n 次的概率是多少? 文心一言&#xff1a; 讯飞星火&#xff1a; 华为盘古&#xff1a; 在HIRE-ASSISTANT中&#xff0c;假设应聘者以随机顺序出现…

仙境传说RO:从零开始编译服务端开发环境搭建安装Pandas-rAthena

仙境传说RO&#xff1a;从零开始编译服务端开发环境搭建安装Pandas-rAthena 大家好&#xff0c;我是艾西今天跟大家分享下仙境传说RO 开发脚本环境搭建。 Pandas是RO的模拟器实际上是开源的一个叫做rAthenna的一个开源项目 准备工具&#xff1a; Git 2.25.0 Setup建议放入D盘…

【消息队列】| 队列的优势介绍及应用场景

目录 &#x1f981; 前言&#x1f981; 那么MQ的优势在哪里&#xff1f;&#x1f981; 应用场景&#x1f981; 最后 &#x1f981; 前言 消息队列&#xff1a;MQ全称Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于系统…

javaweb课程设计——商城项目

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;项目专栏 &#x1f4e7;如果文章知识点有错误的地方&#xff0c;…

2.2 动态范围的常用计算方法

1. 动态范围的常用计算方法 动态范围(Dynamic Range)指的是输入数据中数值的范围&#xff0c;计算动态范围是为了确定量化时使用的比特位数(还是抽象&#x1f602;)。个人理解:考虑到输入数据可能存在数据分布不均&#xff0c;即有些数据偏离过大。而过大的偏离值&#xff0c;会…

Ansys Zemax | NSC 非序列矢高图用户分析

本文介绍如何使用 NSC 矢高图用户分析功能在非序列模式下测量和显示对象的矢高。了解此功能的基础知识&#xff0c;包括如何设置复杂 CAD 零件的文件以获取特定面的矢高值。&#xff08;联系我们获取文章附件&#xff09; 介绍 OptocStudio 的序列模式具有表面矢高分析功能&…

硬件系统工程师宝典(28)-----关于LDO,应该知道的事

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到BJT配合MOSFET控制电源开关的四种电路以及MOSFET的均流电路。今天我们来讲讲LDO的应用分析。 LDO的结构 LDO&#xff08;Low Dropout R…

Linux内核源码的配置和编译

目录 配置交叉编译工具链 读README 配置内核源码支持当前的硬件平台 驱动配置 内核编译 编译&#xff1a; 问题&#xff1a; 解决问题的方法&#xff1a; 测试内核 配置交叉编译工具链 打开内核源码顶层目录的Makefile&#xff0c; hqUbuntu:~/fs6818_uboot/kernel-3.4.39$ vi …

IP地址、子网划分

目录 一、IP地址1.IP地址表示2.分类IP地址3.无分类编址 CIDR4.特殊IP地址 二、子网划分1.子网、子网掩码、子网划分VLSM2.网络地址、广播地址3.示例1&#xff1a;等分为两个子网3.1 划分前&#xff1a;3.2 划分后&#xff1a; 4.示例2&#xff1a;等分为四个子网3.1 划分前&…

五种经典IO模型详解

目录 同步和异步同步阻塞IO模型基本概念应用场景优缺点 同步非阻塞IO模型基本概念应用场景优缺点 IO多路复用模型信号驱动IO模型回顾复习1.信号2.产生信号的条件3.可重入函数4.为什么中断处理函数不能直接调用不可重入函数5.如何写出可重入的函数 基本概念应用场景优缺点 异步I…