Jvm常见问题

1. 为什么用元空间替换永久代
  • 避免OOM异常:永久代中存放了很多JVM需要的类信息,这些数据大多数是不会被清理的,所以Full GC往往无法回收多少空间。而永久代的空间是有限的,如果经常加载新的类进来或者频繁的创建和删除类,可能会导致OOM异常。而元空间是直接分配在本地内存中,不受JVM内存限制,因此可以更有效地管理堆外内存,避免OOM异常。
  • 支持更大的堆外内存:在永久代中,PermSize和MaxPermSize设置的大小决定了永久代的上限。但是,并不总能知道应该设置为多大合适,因为如果使用默认值很容易遇到OOM错误。而在元空间中,可以根据实际需要进行动态调整,更加灵活和高效。
2. 为什么调整字符串常量池的位置

因为方法区的大小是有限制的,而且方法区的GC回收效率太低,当字符串常量池中存储的字符串数量不断增加时,会导致方法区内存不足,从而导致OutOfMemoryError异常。调整到了Java堆内中也是为了更好的解决这个问题,通过GC机制自动管理内存分配和回收。

3. 什么是执行引擎

执行引擎是Java虚拟机核心组件之一,主要负责将Java字节码转换为机器指令,并执行这些指令。其主要任务包括:

  • 解释字节码:执行引擎读取字节码并将其转换为机器指令。
  • 执行指令:执行引擎执行生成的机器指令,完成程序的运行。
  • 管理内存:执行引擎负责管理Java虚拟机的内存,包括堆内存和栈内存等。
  • 优化代码:执行引擎可以对代码进行一些优化,以提高程序的性能。
4. 成员变量、局部变量、类变量分别存储在内存的什么地方
  • 成员变量:是定义在类中的变量,它们属于类的实例,也就是说每个对象都有自己的一组成员变量。在Java中,成员变量存储在Java堆中,由Java虚拟机进行管理。
  • 局部变量:是定义在方法中的变量,它们只在方法中使用,并且每次方法调用时都会创建一个新的局部变量。在Java中,局部变量存储在Java栈中,由Java虚拟机进行管理。
  • 类变量:也称为静态变量,它们是定义在类中但不属于任何对象的变量,属于所有对象共享变量,它们的生命周期与类相同。在JDK8之前,类变量是存储在方法区中,JDK8开始,永久代被移除了,取而代之的是元空间,但元空间中存储的主要是.class文件的元数据信息,类变量的存储位置便由方法区转到了堆内存中。
5. 为什么使用堆外内存
  • 提高了Java程序的性能:堆外内存是直接在操作系统的内存中分配的,不受Java虚拟机堆内存的限制,因此可以更快地访问堆外内存中的数据,从而提高Java程序的性能。
  • 减少了Java虚拟机的垃圾回收压力:堆外内存的使用可以减少Java虚拟机堆内存的使用,从而减少垃圾回收的频率和压力,提高Java程序的稳定性和可靠性。
  • 允许使用更大的内存空间:堆外内存不受Java虚拟机堆内存的限制,可以使用更大的内存空间来存储数据,从而支持更大规模的数据处理和计算。
  • 支持更高效的数据传输:使用堆外内存可以避免Java虚拟机堆内存和操作系统内存之间的数据复制和传输,从而提高数据传输的效率。
6. 什么是深拷贝和浅拷贝
  • 浅拷贝(shallowCopy):是指复制对象时,只复制了对象的引用,新对象和原对象共享同一个对象实例。如果原对象发生了改变,新对象也会随之改变。
  • 深拷贝(deepCopy):是指复制对象时,不仅复制了对象的引用,还复制了对象所包含的所有数据。新对象和原对象之间没有任何关系,它们各自拥有自己的数据副本。
7. 堆栈的区别
  1. 物理地址
    • 堆的物理地址分配对对象是不连续的。
    • 栈使用的是数据结构中的栈,先进后出的原则,物理地址分配是连续的。
  2. 内存分配
    • 堆因为是不连续的,所以分配的内存是在 运行期 确认的,因此大小不固定。一般堆大小远远大于栈。
    • 栈是连续的,所以分配的内存大小要在 编译期 就确认,大小是固定的。
  3. 存放的内容
    • 堆存放的是对象的实例和数组。因此该区更关注的是数据的存储。
    • 栈存放:局部变量,操作数栈,返回结果。该区更关注的是程序方法的执行。
  4. 程序的可见度
    • 堆对于整个应用程序都是共享、可见的。
    • 栈只对于线程是可见的。所以也是线程私有。他的生命周期和线程相同。
8. 对象的创建方式有哪些
  1. 使用关键字new创建对象:使用new关键字可以创建一个新的对象,语法如下:
ClassName objectName = new ClassName();
  1. 使用构造函数创建对象:可以通过定义一个构造函数,在创建对象时传入相应的参数,从而创建一个新的对象。语法如下:
ClassName objectName(argument1, argument2, ...) {// 构造函数的代码
}
  1. 使用clone()方法创建对象:clone()方法是Object类中的一个方法,可以用来创建一个新的对象,该对象与原对象具有相同的属性值和状态。语法如下:
ClassName objectName = (ClassName) sourceObject.clone();
  1. 使用反序列化创建对象:可以将对象序列化成字节流,然后再反序列化成新的对象。这种方式可以实现对象的深拷贝,因为序列化和反序列化过程中会将对象的所有数据都复制一份。
FileInputStream fis = new FileInputStream("objectFile");
ObjectInputStream ois = new ObjectInputStream(fis);
ClassName objectName = (ClassName) ois.readObject();
9. 对象创建的主要流程
  1. 加载类:在创建对象之前,需要先加载该对象所属的类。类的加载过程包括将类的字节码文件从磁盘读取到内存中,并进行验证、准备和解析等操作。
  2. 分配内存:在加载类之后,需要为对象分配内存空间。Java使用堆内存来存储对象,堆内存可以动态地分配和回收。
  3. 初始化对象:在分配内存之后,需要对对象进行初始化。对象的初始化包括执行类的构造函数和初始化实例变量。
  4. 返回对象的引用:初始化完成后,Java虚拟机会返回对象的引用,这个引用可以被用于访问对象的属性和方法。
  5. 垃圾回收:当对象不再被引用时,Java虚拟机会将其标记为垃圾对象,并在适当的时候进行垃圾回收。

需要注意的是,对象创建的流程是由Java虚拟机自动完成的,程序员只需要通过new关键字来创建对象即可,不需要手动管理对象的生命周期。

10. 堆内存的分配方式有哪些
  • 指针碰撞:是指从一段连续的内存区域开始依次向后移动。将所有使用中的内存放到一边,空闲的内存放到另一边,中间放着一个指针作为分界点指示器。当需要为某个对象分配内存时,指针会向空闲的内存移动一段与对象大小相等的位置。

指针碰撞的优点是实现简单,适用于内存分配比较均匀的场景。但是,在内存分配不均匀的情况下,指针碰撞会导致内存碎片化,从而影响程序的性能。

  • 空闲列表:是将堆内存空间划分成若干个大小相等的内存块,并维护一个空闲列表,列表中保存着当前可用的内存块。当程序需要分配内存时,JVM会在空闲列表中查找最小的可用内存块分配给对象,并将其从空闲列表中移除,从而实现内存分配。

空闲列表的优点是能够有效地避免内存碎片化,从而提高内存分配的效率。但是,空闲列表的实现比较复杂,需要维护一个空闲列表和一个哈希表,而且需要考虑并发访问的问题。

11. 如何处理并发安全问题

对象的创建在虚拟机中是一个非常频繁的行为,哪怕只是修改一个指针所指向的位置,在并发情况下也是不安全的,可能出现正在给对象 A 分配内存,指针还没来得及修改,对象 B 又同时使用了原来的指针来分配内存的情况。解决这个问题有两种方案:

  1. 锁分段技术:是一种基于锁的内存分配方式,它将堆内存空间划分成若干个大小相等的内存块,并在每个内存块上加锁,从而保证同一时刻只有一个线程能够访问该内存块。当程序需要分配内存时,JVM会在内存块链表中查找第一个大小大于等于所需内存的空闲内存块,并将其头部和尾部的指针指向当前内存块的头部和尾部,从而实现内存分配。

锁分段技术的优点是能够有效地避免内存碎片化,从而提高内存分配的效率,同时也能够保证并发安全。但是,锁分段技术的实现比较复杂,需要维护一个锁数组和一个内存块链表,而且会产生较多的上下文切换和锁竞争。

  1. TLAB技术(Thread Local Allocation Buffer):是一种基于线程本地缓存的内存分配方式,它将堆内存空间划分成若干个大小相等的内存块,并为每个线程维护一个TLAB缓存,缓存中保存着当前线程经常使用的内存块。当程序需要分配内存时,JVM会首先在TLAB缓存中查找是否有可用的内存块,如果有,则直接分配给程序使用,否则才会向堆内存中申请内存块。

TLAB技术的优点是能够有效地避免内存碎片化,并且能够提高内存分配的效率。同时,TLAB技术的实现比较简单,能够减少锁竞争和上下文切换,从而提高程序的性能。但是,TLAB技术需要占用额外的内存空间,并且需要对TLAB缓存进行管理和维护,否则会导致内存泄漏和性能下降。

12. 对象头中包含哪些部分
  • Mark Word(标记字):它是一个用于标记对象的位图,用于记录对象的状态信息,如对象的哈希码、锁信息、GC信息等。
  • Class Pointer(类指针):它指向对象的类元数据信息,包括类名、字段、方法等。
  • Array Length(数组长度):对于数组对象,对象头中会保存数组的长度信息。
  • Hash Code(哈希码):它是对象的哈希值,用于快速定位对象在内存中的位置。
  • GC Information(GC信息):它记录了对象的GC信息,包括对象的年龄、是否可达等。
  • Padding(填充):为了对齐内存,对象头中可能还会包含一些填充字节。
13. 对象的访问定位方式有哪些

Java 程序需要通过 JVM 栈上的引用访问堆中的具体对象。对象的访问方式取决于 JVM 虚拟机的实现。目前主流的访问方式有句柄直接指针两种方式。

  • 句柄方式:是Java中最常用的对象访问方式,它通过引用变量来访问对象。在Java中,对象引用是一个指向对象内存地址的指针,通过引用变量,程序可以获取对象的地址,从而访问对象的属性和方法。
  • 直接指针方式:是指直接通过指针变量来访问对象,而不是通过引用变量。在Java中,对象的地址是不可直接获取的,因此直接指针方式在Java中是不常用的。但是,在一些特殊的场景下,比如实现本地方法时,可能需要使用直接指针方式来访问对象。
14. JRE、JDK、JVM 及 JIT 之间有什么不同?
  • JRE(Java Runtime Environment):是 Java 运行时环境,是 Java 程序运行所必需的最小环境。它包含了 Java 虚拟机(JVM)、Java 类库和支持文件等组件,可以在不同的操作系统上运行 Java 程序。但不包含 Java 开发工具包(JDK)中的开发工具和编译器等组件。
  • JDK(Java Development Kit):是 Java 开发工具包,是 Java 程序员开发 Java 程序所必需的工具集。它包含了 JRE、Java 编译器、Java 调试器、Java 文档生成器、Java 测试工具等组件,可以帮助程序员开发、调试和测试 Java 程序。JDK 中包含的 JRE 与 JRE 相同,但包含了更多的开发工具和编译器等组件。
  • JVM(Java Virtual Machine):是 Java 虚拟机,是 Java 程序运行的环境。它可以将 Java 代码编译成字节码,并解释执行或者将字节码编译成本地代码执行。JVM 是 Java 平台的核心组件,它实现了 Java 语言的核心特性,包括自动内存管理、垃圾回收、多线程等。
  • JIT(Just-In-Time):是 JVM 中的一部分,是一种动态编译技术。它可以将热点代码编译成本地代码,提高程序的执行效率。JIT 可以根据程序运行时的实际情况,动态地生成本地代码,并将其保存在缓存中,以便下次程序运行时直接使用。
15. 什么是内存泄漏

内存泄漏(Memory Leak)是指程序在使用动态分配内存时,由于某些原因未能及时释放已分配的内存,导致这部分内存无法被再次使用,从而浪费了宝贵的系统资源。

通常情况下,内存泄漏是由程序员在编写代码时出现的错误导致的。例如,程序中可能存在未被正确关闭的文件、数据库连接、网络连接等资源,这些资源在使用后应该被及时释放,否则就会导致内存泄漏。

内存泄漏的危害很大,它会导致系统的内存资源逐渐减少,直到最终系统崩溃。因此,程序员在编写代码时应该注意及时释放已分配的内存资源,避免出现内存泄漏问题。

16. 什么是内存溢出

内存溢出(Memory Overflow)是指程序在使用动态分配内存时,申请的内存空间超出了系统可用的内存大小,导致程序无法正常运行。

通常情况下,内存溢出是由程序员在编写代码时出现的错误导致的。例如,程序中可能存在申请的内存空间大小计算错误、数组越界等问题,这些问题都可能导致程序申请的内存空间超出系统可用的内存大小,从而导致内存溢出。

内存溢出的危害很大,它会导致程序崩溃或者系统崩溃,甚至可能会导致数据丢失或者系统安全问题。因此,程序员在编写代码时应该仔细检查内存申请和使用的代码,避免出现内存溢出问题。此外,也可以通过增加系统可用内存大小、优化程序代码等方式来解决内存溢出问题。

17. 简述Java垃圾回收机制

Java垃圾回收机制是一种自动内存管理机制,它可以自动检测不再被程序所使用的对象并将其回收,从而释放内存空间,避免了内存泄漏和内存溢出等问题。

18. 垃圾回收有哪些优点
  • 避免内存泄漏:垃圾回收器能够自动检测不再被程序使用的对象并将其回收,避免了内存泄漏的问题。
  • 减少程序员的负担:垃圾回收器能够自动管理内存空间,程序员不需要手动管理内存,从而减少了程序员的负担。
  • 提高程序的稳定性和可靠性:垃圾回收器能够及时清除不再被程序使用的对象,避免了内存溢出和内存泄漏等问题,从而提高了程序的稳定性和可靠性。
  • 提高程序的运行效率:垃圾回收器能够及时回收不再被程序使用的内存空间,从而提高了程序的运行效率。
19. 能保证 GC 执行吗

不能,虽然可以调用 System.gc() 或者 Runtime.gc(),但是没有办法保证 GC的执行。

20. Java 中都有哪些引用类型
  • 强引用:是指在代码中普遍存在的引用,例如在方法中定义的局部变量、成员变量、静态变量、常量等。当一个对象被强引用时,即使内存不足,垃圾回收器也不会回收该对象,直到该对象的强引用被显式地赋值为 null 或者程序结束。
Object object = new Object();
String str = "StrongReference";
  • 软引用:是一种相对强引用更弱的引用类型,它用来描述那些还有用但是不那么重要的对象。当一个对象被软引用时,它并不会被立即回收,而是等到内存不足时,垃圾回收器才会对其进行回收。
SoftReference<String> softRef = new SoftReference<String>(str);
  • 弱引用:是一种更弱的引用类型,它用来描述那些几乎没有用处的对象。当一个对象被弱引用时,它也不会被立即回收,但是当垃圾回收器下次进行回收时,如果发现该对象还存在弱引用,那么就会将该对象回收。
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
  • 虚引用:是最弱的引用类型,它主要用于跟踪对象被垃圾回收器回收的状态。虚引用不能单独使用,必须和引用队列一起使用,也无法通过虚引用来获取被引用的对象。虚引用在创建时必须提供一个引用队列作为参数,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象后,将这个虚引用加入引用队列,以通知应用程序对象的回收情况。
ReferenceQueue phantomQueue1 = new ReferenceQueue();
PhantomReference<Object> sf1 = new PhantomReference<>(new Object(), phantomQueue);
21. 常见的垃圾回收算法有哪些
  • 引用计数器法:是一种比较简单的垃圾回收算法,它的基本思想是为每个对象维护一个引用计数器,当一个对象被引用时,计数器加1,当一个对象不再被引用时,计数器减1。当一个对象的计数器为0时,说明这个对象已经不再被引用,可以被垃圾回收器回收。引用计数器法实现简单,但是无法解决循环引用的问题,容易导致内存泄漏。
  • 可达性分析算法:是一种更为高效的垃圾回收算法,它的基本思想是通过对对象之间的引用关系进行分析,确定哪些对象是可达的,哪些对象是不可达的。可达的对象是指还存在至少一条引用指向它的对象,不可达的对象是指没有任何引用指向它的对象。当一个对象不再被引用时,它就变成了不可达对象,可以被垃圾回收器回收。可达性分析算法能够有效解决循环引用的问题,但是实现相对复杂,且可能会产生内存碎片。
22. 什么情况下会触发GC

在Java中,GC的触发时机通常由垃圾回收器自行决定,JVM会根据当前的内存使用情况和垃圾回收器的策略,动态地调整垃圾回收器的触发时机。一般来说,垃圾回收器会在以下情况下触发GC:

  • 当堆内存空间不足时,垃圾回收器会触发GC,回收一些无用的对象,释放空间。
  • 当新生成的对象无法分配到堆内存空间时,垃圾回收器会触发GC,回收一些无用的对象,释放空间。
  • 当垃圾回收器检测到某个对象没有被引用时,也会触发GC,回收这个对象。

需要注意的是,垃圾回收器的触发时机对于程序的性能和稳定性都有着重要的影响。如果垃圾回收器的触发时机不当,可能会导致程序出现频繁的Full GC,甚至导致程序崩溃。因此,在实际开发中,需要根据具体情况选择合适的垃圾回收器,并对垃圾回收器的参数进行适当的调整,以达到最佳的性能和稳定性。

23. 什么是Young GC

Young GC(Young Generation Garbage Collection)也称为Minor GC,是指对Java堆中新生代(Young Generation)中的垃圾对象进行回收的垃圾回收过程。当应用程序向堆中申请内存时,如果没有足够的空间,就会触发一次Young GC。Young GC会扫描新生代中的所有对象,将那些已经不再被引用的对象回收掉,并将还存活的对象复制到Survivor区或晋升到老年代中。

Young GC相对于Full GC来说,执行速度更快,因为它只需要扫描和回收新生代中的垃圾对象,而不需要扫描和回收整个堆内存。但是,Young GC的回收效率可能会受到一些因素的影响,例如新生代的大小、Survivor区的大小、对象的年龄等等。如果Young GC的频率过高,就可能会导致应用程序的性能下降,因为它会消耗大量的CPU资源和内存带宽。

为了优化Young GC的效果,可以通过调整JVM参数来改变新生代的大小、Survivor区的大小、对象的年龄阈值等等,以达到更好的垃圾回收效果。

24. 什么是Full GC

Full GC是指Full Garbage Collection的缩写,也称为全局垃圾回收。在Full GC过程中,Java虚拟机会对整个Java堆中的对象进行垃圾回收,包括新生代和老年代中的所有对象,以确保对整个Java堆中的对象进行一次全面的扫描和清理。

Full GC的执行通常会伴随着较长的停顿时间,因为它需要对整个Java堆内存区域进行扫描和清除。为了减少Full GC的执行频率和停顿时间,可以采用一些优化技术,如调整Java堆内存大小、调整垃圾回收器的参数等。

25. 什么情况下会触发Full GC

Full GC通常是在Young GC无法完成对所有垃圾对象的回收时触发的。以下是可能会触发Full GC的情况:

  • 新生代空间不足:当新生代的空间不足时,Young GC无法完成对所有垃圾对象的回收,此时就会触发Full GC。
  • 老年代空间不足:当老年代的空间不足时,Young GC无法完成对所有垃圾对象的回收,此时也会触发Full GC。
  • 系统负载过高:当系统的负载过高时,垃圾回收器可能无法及时完成垃圾回收,此时也可能会触发Full GC。
  • 内存泄漏:如果应用程序存在内存泄漏问题,即一些对象无法被垃圾回收器回收,那么就会导致垃圾回收器无法释放足够的内存空间,最终触发Full GC。
  • 大对象分配:当应用程序分配了大量的大对象时,可能会导致垃圾回收器无法在Young GC中完成对所有垃圾对象的回收,从而触发Full GC。
26. 垃圾收集算法有哪些类型

常见的垃圾收集算法有:复制算法、标记 -清除算法、标记-整理算法、分代算法,我们常用的垃圾回收器一般都采用分代算法。

  • 复制算法:复制算法将堆内存分为两个区域,一部分称为from区域,另一部分称为to区域。当from区域中的对象被垃圾回收时,将存活的对象复制到to区域中,同时清空from区域。这个过程会不断重复,以保证to区域中始终有一定数量的存活对象。
    • 缺点:可用的内存大小缩小为原来的一半,对象存活率高时会频繁进行复制。
    • 优点:按顺序分配内存即可,实现简单、运行高效,不用考虑内存碎片。
  • 标记-清除算法:分为两个阶段:标记阶段和清除阶段。标记阶段会遍历整个堆内存,标记出所有还在使用的对象,并将未标记的对象视为垃圾对象。清除阶段会遍历堆内存,清除所有未被标记的对象。
    • 缺点:标记、清除过程效率低,产生大量不连续的内存碎片,提高了垃圾回收的频率。
    • 优点:实现简单,不需要对象进行移动。
  • 标记-整理算法:标记-整理算法是标记-清除算法的改进版。它在清除阶段时,将存活的对象移动到堆的一端,然后将这个端点移动到下一个空闲的位置。这样可以减少内存碎片,提高内存利用率。
    • 缺点:仍需要进行局部对象移动,一定程度上降低了效率。
    • 优点:解决了标记-清理算法存在的内存碎片问题。
  • 分代算法:分代算法将堆内存分为年轻代和老年代两个区域,分别采用不同的垃圾回收策略。年轻代采用复制算法或标记-整理算法,老年代采用标记-清除算法或标记-整理算法。这样可以根据对象的生命周期来选择合适的垃圾回收策略,提高垃圾回收的效率。
27. JVM有哪些垃圾收集器
  • Serial收集器:Serial收集器是一种单线程的垃圾收集器,它采用标记-清除算法或标记-整理算法进行垃圾回收。Serial收集器适用于小型的应用程序或系统,因为它只能在一个线程上执行垃圾回收,无法利用多核处理器的优势。
  • Parallel收集器:Parallel收集器是一种多线程的垃圾收集器,它采用多个线程并发地进行垃圾回收。Parallel收集器适用于大型的应用程序或系统,因为它可以利用多核处理器的优势,提高垃圾回收的效率。
  • CMS收集器:CMS收集器是一种基于标记-清除算法的垃圾收集器,它采用并发的方式进行垃圾回收。CMS收集器可以避免Full GC的停顿时间,但会产生较长时间的Minor GC停顿时间。
  • G1收集器:G1收集器是一种基于分代算法的垃圾收集器,它采用区域化的方式进行垃圾回收。G1收集器可以避免Full GC的停顿时间,并且具有更好的内存利用率和吞吐量。
  • ZGC收集器:ZGC收集器是一种面向大型应用程序的垃圾收集器,它采用增量式的方式进行垃圾回收。ZGC收集器可以支持更大的堆内存,并且具有更好的响应时间和可伸缩性。
28. JVM常用参数有哪些
  • -Xms和-Xmx:设置JVM的最小和最大堆大小,默认值为物理内存的1/4和1/2。可以通过这两个参数来调整JVM的堆大小,以适应不同的应用程序需求。
  • -XX:MaxPermSize:设置永久代的最大大小,默认值为64MB。可以通过这个参数来调整永久代的大小,以适应需要大量使用反射或动态代理的应用程序。
  • -XX:NewSize和-XX:MaxNewSize:设置新生代的初始大小和最大大小,默认值分别为物理内存的1/4和1/2。可以通过这两个参数来调整新生代的大小,以适应应用程序的内存需求。
  • -XX:SurvivorRatio:设置新生代中eden区和survivor区的比例,默认值为8:1。可以通过这个参数来调整新生代中eden区和survivor区的大小比例,以适应应用程序的内存需求。
  • -XX:+UseConcMarkSweepGC和-XX:+UseG1GC:分别启用CMS和G1垃圾收集器,默认使用Serial垃圾收集器。可以通过这两个参数来选择不同的垃圾收集器,以适应应用程序的内存需求和性能要求。
  • -XX:+PrintGC和-XX:+PrintGCDetails:分别启用垃圾收集的日志输出和详细日志输出,可以通过这两个参数来查看垃圾收集的情况,以便进行优化。
29. linux怎么修改jvm启动参数
  1. 使用命令行参数:可以在启动JVM时,使用命令行参数来设置JVM启动参数。例如:
java -Xms512m -Xmx1024m MyApp
  1. 使用环境变量:可以将JVM启动参数设置为环境变量,在JVM启动时,通过读取环境变量来设置JVM启动参数。例如:
export JAVA_OPTS="-Xms512m -Xmx1024m"
java MyApp
  1. 修改JVM配置文件:可以通过修改JVM的配置文件来设置JVM启动参数。在Linux中,JVM的默认配置文件为$JAVA_HOME/jre/lib/amd64/jvm.cfg。可以通过编辑该文件来设置JVM启动参数。例如:
-Xms512m
-Xmx1024m

无论使用哪种方式,都需要注意JVM启动参数的正确性和合理性。不当的JVM启动参数可能会导致JVM性能下降或者出现其他异常情况。

30. 类加载步骤有哪些

类加载执行过程是Java虚拟机(JVM)中的一个重要概念,它指的是将Java类的字节码文件加载到内存中,并将其转换为Java对象的过程。类加载执行过程主要包括以下几个步骤:

  1. 加载:类加载器根据类的全限定名,在classpath中查找并加载对应的字节码文件。
  2. 验证:在加载字节码文件之前,需要对字节码进行验证,以确保其符合Java虚拟机规范。验证的过程包括检查字节码文件是否符合规范、检查字节码文件中的符号引用是否合法、检查字节码文件是否被篡改等。
  3. 准备:在验证通过后,需要为类的静态变量分配内存,并设置默认初始值。同时,还需要为类中的常量池赋予符号引用,以便在后续的运行过程中使用。注意这里所说的初始值概念,比如一个类变量定义为:public static int v = 80;实际上变量 v 在准备阶段过后的初始值为 0 而不是 80。
  4. 解析:解析指的是将类中的符号引用转换为直接引用的过程。例如,将类中的方法名转换为实际的方法地址。
  5. 初始化:初始化指的是执行类构造器中的代码,以及执行静态代码块中的代码。在初始化阶段,可以使用类中的静态变量和方法。
  6. 使用:类加载完成后,可以通过类的Class对象来获取类的各种信息,并创建该类的实例。

需要注意的是,类加载执行过程是一个递归的过程,每个类都会在其父类加载完成后再进行加载和初始化。同时,类加载器也是一个重要的概念,它负责加载和管理类的加载过程。在实际开发中,需要了解类加载执行过程和类加载器的原理,以便能够更好地进行调试和优化。

31. 类加载器有哪些

Java中的类加载器(ClassLoader)是一个重要的概念,它负责加载和管理Java类的加载过程。常见的Java类加载器包括:

  1. Bootstrap ClassLoader:Java虚拟机自带的类加载器,负责加载JRE/lib/rt.jar中的类。
  2. Extension ClassLoader:扩展类加载器,负责加载JRE/lib/ext目录下的类。
  3. System ClassLoader:系统类加载器,负责加载应用程序的类路径中的类。
  4. Application ClassLoader:应用程序类加载器,负责加载应用程序的类路径中的类和第三方库中的类。
  5. WebappClassLoader:Web应用程序类加载器,负责加载Web应用程序中的类。
  6. ParentClassLoader:父类加载器,用于加载其他类加载器无法加载的类。
32. 什么是双亲委派模型

双亲委派模型指的是当一个类加载器需要加载一个类时,它会首先委派给父类加载器去加载,如果父类加载器可以加载该类,则直接返回;如果父类加载器无法加载该类,则交给自己去加载。在双亲委派模型中,每个类加载器都有一个父类加载器,它们形成了一个类加载器的层次结构。
在这里插入图片描述
在Java中,系统类加载器是最顶层的类加载器,它的父类加载器是Bootstrap ClassLoader。应用程序类加载器和扩展类加载器都是系统类加载器的子类加载器,Web应用程序类加载器是应用程序类加载器的子类加载器。

33. 为什么需要双亲委派模型

通过双亲委派模型,Java可以保证类的加载顺序和安全性。如果多个类加载器同时加载同一个类,那么父类加载器会先加载该类,这样就可以避免类的冲突和重复加载。同时,双亲委派模型也可以保证类加载的安全性,因为只有经过验证的类加载器才能加载类,从而避免了恶意类的加载和执行。

34. JVM 调优的工具

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。第三方有:MAT(MemoryAnalyzerTool)、GChisto。

  • jstat:用于监视 JVM 的各种统计信息,如内存使用情况、垃圾回收情况、类加载情况等。
  • jmap:用于生成 JVM 的内存转储文件,以便分析 JVM 的内存使用情况和对象分布情况。
  • jstack:用于生成 JVM 的线程转储文件,以便分析线程的状态和调用栈信息。
  • jconsole:用于监视 JVM 的运行状况和资源使用情况,并提供图形化界面。
  • jvisualvm:JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的
    变化、gc 变化等。
  • JProfiler:是一款全面的 Java 应用程序性能分析工具,可以监视 JVM 的运行状况、分析内存泄漏和性能瓶颈等问题,并提供详细的报告和分析结果。
  • MAT,Memory Analyzer Tool,一个基于Eclipse的内存分析工具,是一个快速、功能丰富的
    Javaheap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。
  • GChisto,一款专业分析gc日志的工具。
35. 常用的调优命令
  1. CPU指标常见的命令
// 显示系统各个进程的资源使用情况
top
// 查看某个进程中的线程占用情况
top -Hp pid
// 查看当前 Java 进程的线程堆栈信息
jstack pid
  1. JVM 内存指标常见的命令:
// 查看当前的 JVM 参数配置
ps -ef | grep java
// 查看 Java 进程的配置信息,包括系统属性和JVM命令行标志
jinfo pid
// 输出 Java 进程当前的 gc 情况
jstat -gc pid
// 输出 Java 堆详细信息
jmap -heap pid
// 显示堆中对象的统计信息
jmap -histo:live pid
// 生成 Java 堆存储快照dump文件
jmap -F -dump:format=b,file=dumpFile.phrof pid
36. 高CPU占用排查步骤
  1. top :命令找到占用CPU高的进程PID。
  2. jstack PID > threadDump.txt :导出当前进程的dump文体,各线程的状态信息;
  3. top -Hp pid :找出PID的进程占用CPU过高的线程TID。
  4. printf “%x\n” TID:将10进制的TID转为16进制TID,因为dump文件中的线程ID是16进制的;
  5. less threadDump.txt:查找转换成为16进制的线程TID,找到对应的线程调用栈分析问题。

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

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

相关文章

前端页面转pdf

首先&#xff0c;需要安装两个库 html2canvasjspdf 先引入这个公用的html转pdf的方法 /**path:src/utils/htmlToPdf.jsname:导出页面为pdf格式 **/ import html2Canvas from "html2canvas1.4.1"; import JsPDF from "jspdf2.5.1";const htmlToPdf {get…

2.Ansible的copy模块,我最常用的模块

1. 简述 先从我自身的情况来说&#xff0c;我不是运维人员&#xff0c;并且对linux操作也不是特别熟悉&#xff0c;所以工作中我使用ansible基本就是在平常的自动化部署中&#xff0c;而使用最多的模块就是copy模块。我使用copy模块也主要是来替换生产环境的配置文件。所以&am…

rabbitMQ镜像队列的使用

在rabbitMQ集群中&#xff0c;默认发送消息时&#xff0c;队列默认时在一个节点上存在的。 我们以node01 node02 node03三节点集群为例&#xff0c;在node01声明队列发送消息后&#xff0c;发现&#xff1a; 测试队列只在节点node01上出现。 我们手动停止node01后&#xff0c…

Tomcat外传

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 本篇开始&#xff0c;我…

C++11线程以及线程同步

C11中提供的线程类std::thread,基于此类创建一个新的线程相对简单&#xff0c;只需要提供线程函数和线程对象即可 一.命名空间 this_thread C11 添加一个关于线程的命名空间std::this_pthread ,此命名空间中提供四个公共的成员函数&#xff1b; 1.1 get_id() 调用命名空间s…

Python自动化测试——元素定位

1.selenium简介 Selenium是一个用于Web应用程序测试的工具。Selenium是直接运行在浏览器中&#xff0c;模拟用户操作web界面。支持多平台&#xff1a;windows、linux、MAC &#xff0c;支持多浏览器&#xff1a;ie、firefox、chrome等浏览器。 2. 启动浏览器 # 导入webdrive…

JavaWeb服务器详解和后端分层解耦

JavaWeb HTTP协议请求数据格式响应数据格式协议解析 Web服务器请求响应请求参数的接收响应 分层解耦IOC&DI入门IOC详解 HTTP协议 超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则 特点&#xff1a; 基于TCP协议&#xff1a;面向连接&#xff0c;安全 …

【Android知识笔记】架构专题(二)

分层架构概论 分层的依据是什么? 关注点分离:自下而上,从机器到用户,从抽象到具体,从通用到业务,每一层,各自关注各自的抽象层次。修改与影响:不同层之间的代码或技术方案修改,彼此互不影响。例如 UI 界面从 xml 布局改成 Jetpack Compose 之后,不应该影响数据层。换…

kafka中的常见问题处理

文章目录 1. 如何防⽌消息丢失2. 如何防⽌重复消费3. 如何做到消息的顺序消费4. 如何解决消息积压问题4.1 消息积压问题的出现4.2 消息积压的解决⽅案 5. 实现延时队列的效果5.1 应用场景5.2 具体方案 1. 如何防⽌消息丢失 ⽣产者&#xff1a;1&#xff09;使⽤同步发送 2&…

Maya 2024(3D建模、动画和渲染软件)

Maya 2024是一款非常强大的3D建模、动画和渲染软件&#xff0c;它提供了许多新功能和改进&#xff0c;以帮助建模师、动画师和渲染师更加高效地进行创作。 在建模方面&#xff0c;Maya 2024引入了Symmetry&#xff08;对称&#xff09;功能&#xff0c;可以在网格两侧生成均匀…

学习笔记三十六:通过Ingress-nginx实现灰度发布

通过Ingress-nginx实现灰度发布 灰度发布原理将新版本灰度给部分用户切一定比例的流量给新版本 部署两个版本的服务以 nginx 为例&#xff0c;先部署一个 v1 版本:部署一个 v2 版本再创建一个 Ingress&#xff0c;对外暴露服务&#xff0c;指向 v1 版本的服务:访问验证 基于 He…

智能井盖位移报警器效果一览,感知井盖异常

井盖位移是指井盖在受到外力作用下产生的位置移动。这种现象通常发生在道路颠簸、车流量较大或地下管道受压较大的区域&#xff0c;当然也不排除会出现在一些角落内。当井盖发生位移或倾斜时&#xff0c;不仅会影响城市内道路的通行&#xff0c;还会给行人和车辆带来安全隐患。…

web:catcat-new(文件包含漏洞、flask_session伪造)

前提知识 /etc/passwd 该文件储存了该Linux系统中所有用户的一些基本信息&#xff0c;只有root权限才可以修改。其具体格式为 用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell&#xff08;以冒号作为分隔符&#xff09; /proc/self proc是一个伪文件系统…

【前缀和]LeetCode1862:向下取整数对和

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 作者推荐 动态规划LeetCode2552&#xff1a;优化了6版的1324模式 题目 给你一个整数数组 nums &#xff0c;请你返回所有下标对 0 < i, j < nums.length 的 …

LangChain的函数,工具和代理(二):LangChain的表达式语言(LCEL)

LangChain Expression Language (LCEL) 是 LangChain 工具包的重要补充&#xff0c;旨在提高文本处理任务的效率和灵活性。LCEL 允许用户采用声明式方法来组合链&#xff0c;便于进行流处理、批处理和异步任务。其模块化架构还允许轻松定制和修改链组件。LCEL 的优势之一是它使…

知识图谱最简单的demo实现——基于pyvis

1、前言 我们在上篇文章中介绍了知识图谱的简单实现&#xff0c;最后使用neo4j进行了展示&#xff0c;对于有些情况我们可能并不想为了查看知识图的结果再去安装一个软件去实现&#xff0c;那么我们能不能直接将三元组画出来呢/ 接下来我们就介绍一个可视化的工具pyvis&#…

STM32/GD32_分散加载

Q&#xff1a;如何将一个变量、某个源文件的函数在编译阶段就存储在用户指定的区域&#xff1f; KEIL环境&#xff1a;.map后缀文件、.sct后缀文件 IAR环境&#xff1a;.map后缀文件、.icf后缀文件 【map文件】 对固件里面的变量、函数、常量等元素的存储空间进行分配的说明…

ffmpeg开发 环境配置

ffmpeg开发简图 1 下载ffmpeg开发包 https://ffmpeg.org/download.html 包含三个版本&#xff1a;Static、Shared以及Dev Static --- 包含3个应用程序&#xff1a;ffmpeg.exe , ffplay.exe , ffprobe.exe&#xff0c;体积都很大&#xff0c;相关的DLL已经被编译到exe里面去…

VS2022使用Vim按键

VS2022使用Vim按键 在插件管理里面搜索VsVim 点击安装&#xff0c;重启VS 工具->选项->VsVim 配置按键由谁处理&#xff0c;建议Ctrl C之类常用的使用VS处理&#xff0c;其它使用Vim处理

golang WaitGroup的使用与底层实现

使用的go版本为 go1.21.2 首先我们写一个简单的WaitGroup的使用代码 package mainimport ("fmt""sync" )func main() {var wg sync.WaitGroupwg.Add(1)go func() {defer wg.Done()fmt.Println("xiaochuan")}()wg.Wait() }WaitGroup的基本使用场…