首页 > 其他分享 >JVM虚拟机

JVM虚拟机

时间:2024-09-03 10:25:11浏览次数:3  
标签:对象 虚拟机 Address Person 内存 JVM address 拷贝

JVM虚拟机

一.简述JVM虚拟机的内存结构

JVM内存结构大致分为五个部分,分别为方法区、堆、虚拟机栈、程序计数器、本地方法栈。如下图:

1.程序计数器:

程序计数器主要作用是记录下一条要执行的二进制字节码指令地址。属于线程私有,不会出现内存溢出。

2.虚拟机栈:

  • 定义:虚拟机栈内部是一个个的栈帧,每一个栈帧对应着一个方法的调用。栈是线程私有的,每个线程在创建的时候,都会创建一个虚拟机栈。
  • 特性:正是因为java是基于栈设计的,才实现类跨平台的特性。
  • 生命周期:栈的生命周期与线程一致。
  • 保存数据:栈中会保存方法调用的栈帧,栈帧中包括局部变量表,操作数栈,动态链接,方法返回地址等。
  • 垃圾回收:栈内存不会涉及垃圾回收。因为方法在执行完毕后,会被弹出栈空间。
  • 内存溢出:栈是可能内存溢出的,一般是递归操作没有正确推出,因为栈帧过多会导致栈内存溢出;或者栈帧过大,也会导致内存溢出。
  • 局部变量是否线程安全:如果没有逃离方法的作用域,那么就是线程安全的。如果变量引用了对象,并且逃离了方法作用域,那么要考虑线程安全问题。

3.本地方法栈

  • 定义:JVM使用C/C++编写的,java代码通过本地方法native间接的调用实现,如clone(),hashCode();查看java源码用native修饰的;当调用native方法时,所需内存就是在本地方法栈分配。
  • 说明:调用了本地方法后,内存是不受虚拟机控制的。
  • 调用:当线程调用Java方法时,虚拟机会创建一个新的栈帧并压入Java栈。然而当他调用的是本地方法时,虚拟机会保持Java栈不变,不再在线程的Java栈中压入新的栈帧,虚拟机只是简单的动态连接并直接调用指定的本地方法。

4.堆

  • 定义:堆是被所有线程共享的一块内存区域。通过new关键字创建的对象,都会使用堆内存。该内存区域唯一的目的,就是存放对象实例。
  • 垃圾回收:是GC垃圾回收的重点区域。
  • 说明:堆空间细分,还会分为老年代,新生代;新生代还可以分为Eden区,From Surivor区,ToSurivor区。

5.方法区(元空间)

  • 定义:存储每个类的构造信息,譬如运行时的常量池,字段,方法数据以及方法和构造方法的代码,包含一些在类和实例初始化和接口初始化时候使用的特殊方法。
  • 运行时常量池:常量池就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型,字面量等信息。常量池是*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址。
  • 位置:jdk1.8之前,直接使用的是堆内存;1.8之后使用的是操作系统内存。
  • 作用:常量池 的作用是避免频繁的创建和销毁相同的对象,节省内存空间,节省运行时时间。比如:需要已存在的字符串,直接从常量池中取即可。

6.直接内存

常用于NIO操作,用于数据缓冲区,内存不受JVM内存管理,分配回收成本高,但是读写性能高。

二.Java中,堆和栈之间的区别

  • 分配方式:堆内存是动态分配的,是由Java虚拟机JVM自动管理。栈内存是静态分配的,由编译器自动管理。
  • 存储内容:堆内存用于存储对象实例和数组等引用类型数据。栈内存用于存储方法调用,局部变量和方法参数等基本类型数据。
  • 内存管理:堆内存的分配和回收是由Java虚拟机JVM的垃圾回收机制负责的。栈内存的分配和释放是由编译器自动处理,当一个方法执行后,它所占用的栈内存会自动被释放。
  • 空间大小:堆内存的空间较大,可以动态扩展。栈内存的空间较小,大小是固定的。
  • 存储速度:堆内存的分配速度较慢,因为需要在运行时动态分配内存空间。栈内存的分配速度较快,因为它使用指针来定位数据。

三.简述J啊v啊中对象的深拷贝和浅拷贝

1.浅拷贝:

浅拷贝是指在对一个对象进行拷贝时,只拷贝对象本身和其中的基本数据类型,而不拷贝对象内部的引用类型。因此,在浅拷贝的对象中,引用类型的变量指向的依旧是原始对象中的引用。
在Java中,实现浅拷贝可以使用Object类的clone()方法,或者手动重写类的clone()方法。下面是一个示例:

class Person implements Cloneable {
    private String name;
    private Address address;
    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Address {
    private String city;
    public Address(String city) {
        this.city = city;
    }
}
public class Test {
    public static void main(String[] args) throws Exception {
        Address address = new Address("Beijing");
        Person person1 = new Person("Tom", address);
        Person person2 = (Person) person1.clone();
        System.out.println(person1 == person2); // false
        System.out.println(person1.getAddress() == person2.getAddress()); // true
    }
}

在上述代码中,我们定义了一个Person类和Address类。Person类中包含一个引用类型的成员变量address。使用Object类的clone()方法进行拷贝,并且在Person类中实现了Cloneable接口,并重写了clone()方法,使得Person类可以进行拷贝。
在main函数中,我们创建了一个Person对象person1,其中包含一个Address对象。接着,我们使用person1的clone()方法创建了一个新的Person对象person2,并使用“”判断person1和person2是否是同一对象。结果为false,证明两个对象是不同的。接下来,我们使用“”判断person1和person2中的address是否是同一对象,结果为true,即两个对象的address成员变量指向的是同一个地址。
总的来说,浅拷贝只是将原始对象的引用类型成员变量复制到新的对象中,因此新对象中的引用类型成员变量与原始对象中的成员变量指向同一对象。如果原始对象中的引用类型成员变量发生变化,新对象中的引用类型成员变量也会随之变化。

2.深拷贝:

深拷贝是指在对一个对象进行拷贝时,不仅拷贝对象本身和其中的基本数据类型,同时也拷贝对象内部的引用类型。因此,在深拷贝的对象中,引用类型的变量指向的是全新的对象。
在Java中,实现深拷贝的方式比较多,可以使用对象的序列化、手动编写clone()方法等。下面是一个使用对象序列化来实现深拷贝的例子:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test {
    public static void main(String[] args) throws Exception {
        Address address = new Address("Beijing");
        Person person1 = new Person("Tom", address);
        Person person2 = (Person) deepCopy(person1);
        System.out.println(person1 == person2); // false
        System.out.println(person1.getAddress() == person2.getAddress()); // false
    }
    private static Object deepCopy(Object obj) throws Exception {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(obj);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }
}
class Person implements Serializable {
    private String name;
    private Address address;
     public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }
    public Address getAddress() {
        return address;
    }
}
class Address implements Serializable {
    private String city;
     public Address(String city) {
        this.city = city;
    }
}

在上述代码中,我们定义了一个Person类和Address类,并且让它们都实现了Serializable接口。在main函数中,我们创建了一个Person对象person1,其中包含一个Address对象。接着,我们使用deepCopy()方法创建了一个新的Person对象person2,并使用“”判断person1和person2是否是同一对象。结果为false,证明两个对象是不同的。接下来,我们使用“”判断person1和person2中的address是否是同一对象,结果为false,即两个对象的address成员变量指向的是不同的地址。
在上述代码中,我们使用了一个deepCopy()方法来实现对象的深拷贝。该方法使用对象的序列化和反序列化来实现深拷贝。首先,将原始对象序列化成字节数组,然后再将字节数组反序列化成新的对象。这样可以保证复制出的新对象与原始对象完全独立,不会相互影响。

3.总结:

浅拷贝和深拷贝是Java中常用的两种对象拷贝方式。浅拷贝只会复制对象的本身和内部的基本数据类型,而深拷贝会将对象内部所有的基本数据类型和引用类型都复制一份。使用clone()方法个重写clone()方法可以实现拷贝,使用对象序列化或手动赋值可以实现深拷贝。在实现对象拷贝时需要根据具体情况选择合适的拷贝方式,以保证复制出的新的对象能够满足应用需求。

标签:对象,虚拟机,Address,Person,内存,JVM,address,拷贝
From: https://www.cnblogs.com/chenlei210162701002/p/18394075

相关文章

  • JVM/垃圾回收
    Java的垃圾回收模型一、介绍分为栈、堆、本地方法栈、程序计数器、方法区栈区:主要用来存储局部变量和对象地址栈区不仅存储局部变量和对象地址,还存储方法调用的上下文信息。堆区:分为很多个区域,可以存储对象的具体数据等Java虚拟机中内存最大的一块,是被所有线程......
  • 虚拟机安装、配置与使用
    虚拟机安装步骤1下载VMWare略步骤2下载镜像文件下载网址中科大镜像源官网注:上述网址中科大源收录的主要时x86(AMD/Intel)版本的虚拟机镜像源,其他架构如Arm可移步官网。创建虚拟机文件名称如ubuntu-22.04.4-desktop-amd.iso下载的镜像是软件,是实现操作系统的软件。创......
  • JVM分区
    Java虚拟机(JVM)在执行Java程序时,将其运行时数据划分到若干不同的内存区域。这些内存区域的管理对Java应用程序的性能和稳定性有着重要影响。JVM的内存区域主要包括以下几部分:1.方法区(MethodArea)用途:存储每一个类的结构信息,例如运行时常量池、字段和方法数据、构造函数和普通方......
  • JVM入门
    JVM入门本文的目的就是认识JVM认识JVM要从什么方面开始入手呢?我们可以先试着问问自己,如果没有JVM会怎么样?为社么要有JVM?接下来,我就先从Java的跨平台特性开始说起Java的跨平台特性Java设计的初衷就是为了解决一个问题:程序员编写一次程序,就可以在任何提供Java运行时环境的机器上面运......
  • Red Hat 9 — Red Hat 9.4Linux系统 虚拟机安装【保姆级教程】
    Mac分享吧文章目录效果一、下载软件二、安装软件与配置1、安装2、配置三、查看基本信息安装完成!!!效果一、下载软件下载软件地址:www.macfxb.cn二、安装软件与配置1、安装2、配置三、查看基本信息安装完成!!!......
  • Java虚拟机(JVM)性能调优实战指南
    Java虚拟机(JVM)性能调优实战指南大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!Java虚拟机(JVM)作为Java程序运行的基础,其性能直接影响到Java应用的执行效率。性能调优是Java开发中的一项重要技能,它可以帮助我们提高应用的响应速度和处理能力。本文将......
  • VMware虚拟机安装Debian12
    一、安装环境准备二、虚拟机前置配置三、修改硬件配置四、首次开启虚拟机的初始化配置五、首次进入系统界面的配置六、Debian12换源操作一、安装环境准备虚拟机VMware版本:16真机系统:WIN10X64真机内存:16G镜像下载地址①网易开源镜像站:Indexof/debian-cd/12.5.0/amd......
  • JAVA之JVM入门
    Java虚拟机(JVM)是Java平台的核心部分之一,它为Java程序提供了运行环境。一、历史背景1.SunClassicVM发布时间:1996年重要功能:Java1.0的默认JVM。支持基本的字节码执行。简单的垃圾回收机制。2.HotSpotVM发布时间:1999年重要功能:JDK1.3开始成为默认JVM。引入了......
  • Windows Server 2019 OVF, updated Aug 2024 (sysin) - VMware 虚拟机模板
    WindowsServer2019OVF,updatedAug2024(sysin)-VMware虚拟机模板2024年8月版本更新,现在自动运行sysprep,支持ESXiHostClient部署请访问原文链接:https://sysin.org/blog/windows-server-2019-ovf/,查看最新版。原创作品,转载请保留出处。现在都是自动sysprep的......
  • 【JVM】执行引擎、JIT、逃逸分析(一)
    执行引擎、JIT、逃逸分析JVM中的执行引擎是什么?在Java虚拟机(JVM)中,执行引擎(ExecutionEngine)是负责执行Java字节码的核心组件。执行引擎的作用是将Java字节码转换成计算机可以执行的机器码,并实际执行这些机器码。以下是JVM执行引擎的主要职责和组成部分:主要职责:1.......