Java面试题冲刺第二十七天–JVM2

Java面试题冲刺第二十七天--JVM2

1. 内存模型

Java内存模型主要分为两种:

  • 堆内存:存放我们new出来的对象以及数组等,这部分内存可以动态申请或释放。一般情况下,堆内存比较大。
  • 栈内存:存放基本类型的变量以及对象的引用变量(指针),这些变量会随着程序的运行而申请或释放。栈的空间比较小,一般情况下,栈的大小是在程序启动的时候就固定下来。

2. JVM内存模型

JVM内存模型主要分为五种:

  • 方法区(JDK7及以前称为永久代):存放静态变量、类信息等,这部分内存可以动态申请或释放。运行时类的情况是在方法区中存储。
  • 堆内存:同上。
  • 虚拟机栈:与线程相关的数据存储在虚拟机栈中,包括方法调用的局部变量、返回值等数据。这个是栈内存的一部分。
  • 本地方法栈:较少使用,主要是为了支持本地(native)方法。
  • PC寄存器:记录当前线程执行的代码行号,也就是JVM中的“程序计数器”。

3. GC算法

  • 新生代GC:一般采用复制算法。
  • 老年代GC:一般采用标记-清除算法。

在JDK 1.2之后,Java默认使用的是能够自动适应应用程序所需的并行垃圾收集器(Parallel Collector)——也称之为吞吐量优先收集器(The throughput collector)。

4. 分代收集

对于JVM的“分代收集”策略,一般分为以下几步:

  • 对于新生代开辟一段内存,称之为“Eden”空间;
  • 运行过程中,将对象放入Eden空间;
  • 当Eden空间满时,将其中存活的对象,复制到其他内存空间,称之为“Survivor”空间中;
  • 当“Survivor”空间也满时,将存活下来的对象放入老年代空间;
  • 老年代也满,就会触发Full GC,也就是对整个堆都进行清理。

5. 示例说明

示例1

public class Test {
    private static int count = 0;
    public static void main(String[] args) {
        checkMemory();
    }
    private static void checkMemory(){
        while (true){
            new Thread(() -> {
                byte[] array = new byte[1024 * 1024];
                try {
                    Thread.sleep(1000);
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            System.out.println("count=" + count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

这段代码实现了不断开启新的线程进行内存分配操作。在输出中,你会看到类似如下的内容:

count=985
count=987
count=999
Exception in thread "Thread-2" java.lang.OutOfMemoryError: Java heap space

这是因为每当开启一个新线程时,都会在堆内存中占用一定空间。由于没有使用相关手段对线程进行回收,最终导致堆内存耗尽。

示例2

public class Test {
    private static int count = 0;
    public static void main(String[] args) {
        while (true){
            new Thread(() -> {
                byte[] array = new byte[1024 * 1024];
                try {
                    Thread.sleep(1000);
                    count++;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
            System.out.println("count=" + count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

这段代码与示例1非常相似,唯一的区别就是while循环在main方法中而不是checkMemory方法中。在输出中,你会看到类似如下的内容:

count=390
count=411
count=422
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

这是因为main方法一直处于运行状态,并在其中使用while循环不断加入新线程,最终导致堆内存耗尽。

阅读剩余 60%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java面试题冲刺第二十七天–JVM2 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • Java+Ajax实现的用户名重复检验功能实例详解

    下面是关于“Java+Ajax实现的用户名重复检验功能实例详解”的完整攻略。 1. 概述 本篇攻略主要介绍如何使用Java和Ajax技术实现一个用户名重复检验功能。在用户填写用户名时,系统会自动检测该用户名是否已经被占用,如果已经被占用,则会提示用户重新填写。 2. 实现步骤 2.1 创建数据库 使用MySQL数据库,创建一个名为user的表,表中包含如下字…

    Java 2023年6月15日
    00
  • SpringBoot 创建web项目并部署到外部Tomcat

    下面是关于SpringBoot创建Web项目并部署到外部Tomcat的攻略。 1. 创建SpringBoot项目 首先,我们需要创建一个SpringBoot Web项目。在这里,我们可以使用Spring Initializr,它是一个基于Web的Spring Boot项目生成器,可以快速构建Spring Boot项目。 具体来说,可以按照以下步骤创建Spri…

    Java 2023年5月19日
    00
  • 详解Maven安装教程及是否安装成功

    下面是详细讲解“详解Maven安装教程及是否安装成功”的完整攻略。 1. 安装JDK 在安装Maven之前,需要先安装JDK,因为Maven是基于Java的,所以JDK必须先安装好。可以在Oracle官网下载JDK,安装过程中需要注意选择合适的版本。 2. 下载Maven 从Maven官网下载Maven,下载页面中有两个版本分别为源码版本和二进制版本。如果你…

    Java 2023年5月20日
    00
  • springboot实现全局异常处理及自定义异常类

    一、背景简介 在SpringBoot的应用开发过程中,异常处理显得尤为关键。当系统运行出现意外情况时,能够及时捕获异常、快速定位问题和提供友好的提示信息,是系统健壮性和用户体验的保障。本文将介绍如何使用SpringBoot实现全局异常处理并自定义异常类,帮助开发人员快速高效地处理异常信息。 二、目标 实现全局异常处理,处理系统的所有异常,包括运行时异常和非运…

    Java 2023年5月27日
    00
  • java 中JDBC连接数据库代码和步骤详解及实例代码

    下面是详细讲解 “java 中JDBC连接数据库代码和步骤详解及实例代码” 的攻略: JDBC 连接数据库的步骤 在 Java 中,连接数据库需要以下步骤: 加载数据库驱动程序:通过调用 Class.forName() 方法,加载驱动程序。代码示例: Class.forName("com.mysql.jdbc.Driver"); 创建数据…

    Java 2023年5月19日
    00
  • MyBatis-Plus动态表名的使用

    下面是关于MyBatis-Plus动态表名的使用的完整攻略。 1. 什么是MyBatis-Plus动态表名 MyBatis-Plus是MyBatis的一个增强工具包,提供了许多增强功能,其中之一就是动态表名。动态表名指的是,在一些场景下,我们需要在同一SQL语句中操作多张表,或者需要让表名根据不同的参数而动态变化,此时就可以使用MyBatis-Plus提供的…

    Java 2023年5月20日
    00
  • 一文理解kafka rebalance负载均衡

    一文理解Kafka Rebalance负载均衡 在Kafka中,消费者组(Consumer Group)中的多个消费者(Consumer)会协同消费一个或多个Topic的分区(Partition)。消费者组通过Partition的分配策略来确定每个消费者负责消费哪些分区。当新的消费者加入或退出消费者组时,需要重新进行分区分配,这个过程被称为Rebalance…

    Java 2023年5月20日
    00
  • Java数据库连接池连接Oracle过程详解

    Java数据库连接池连接Oracle过程详解 本文将详细讲解Java数据库连接池连接Oracle的过程,包括连接池的作用、如何配置连接池、连接池连接Oracle的步骤、注意事项等。 连接池的作用 连接池是为了提高系统性能和稳定性而设计的。在Java中,使用连接池可以避免频繁地打开和关闭数据库连接,从而节省系统资源。当一个请求需要访问数据库时,连接池会从连接池…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部