JVM常用知识总结

1.jvm运行时数据区划分

在这里插入图片描述
虚拟机运行时。内存中数据区分为:虚拟机栈、本地方法栈、堆、程序计数器。
程序计数器:是一块较小的内存空间,每个线程都有一个独立的程序计数器。程序计数器中存放下一条指令存放的地址,字节码解释器工作是就是通过改变这个计数器值来执行下一条需要执行的字节码指令。
  java虚拟机栈:每个线程都有一个独立的java虚拟机栈,我们所说的“堆”、“栈”中“栈”就是虚拟机栈,虚拟机栈是用来描述java方法执行的内存模型。每个方法在执行过程会创建一个栈帧用于存储局部变量表、操作数栈等信息。每个方法从调用到执行完过程对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
  本地方法栈:与虚拟机栈作用类似,虚拟机栈执行java方法(字节码)服务,而本地方法栈为虚拟机使用的是Native方法服务。(native关键字修饰的方法叫做本地方法,本地方法和其它方法不一样,其他方法运行在虚拟机栈中,本地方法运行在本地方法栈中,native方法主要用于加载文件和动态链接库,与本地平台有关,可移植性不太高。)
  java堆:java堆(java Heap)是虚拟机所管理的内存最大一块,是被所有线程共享的一块内存区域,几乎所有的对象实例以及数组都要在堆上分配内存,堆也是垃圾收集器管理的主要的区域。
  方法区:方法区与堆一样是各个线程共享的内存区域,但不是描述java方法执行的内存模型,而是存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。编译期生成的各种字面量和符号的引用在类加载后进入方法区的常量池中存放。

2.虚拟机的类加载机制

类加载机制主要包括:加载、验证、准备、解析、初始化五个阶段。 加载是类加载的一个阶段:加载阶段通过类的全限定名获取该类的二进制字节流,在内存中生成一个此类的class对象。验证:验证阶段是为了确保class文件的字节流中的信息是否符合虚拟机的要求。验证会验证文件格式。元数据、字节码、符号引用是否负荷要求。过滤掉不合要求的文件。准备阶段:为静态变量、类变量分配内存,并设置系统默认值。解析阶段:将常量池中的符号引用转换为直接引用。初始化:完成对静态变量的初始化工作(为类的静态变量赋予用户定义的初始值),静态快执行等工作。

3.谈一谈类加载的双亲委派模型

双亲委派模型是一种设计模式(代理模式**),类加载过程按照启动类加载器、扩展类加载器、应用程序类加载器、自定义类加载这种层次关系进行加载交双亲委派模型。我们把每一层上面的类加载器叫做当前类加载器的父加载器。
在这里插入图片描述
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,他首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上。因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

4.为什么使用双亲委派模型

比如 java.lang.String 这个类,这个是jdk提供的类, 如果我们自定义个 包名:java.lang 然后在里面创建一个String 类, 当我在用String类的时候,根据前面所说,是由bootstrap级的loader 来进行加载的,这个时候它发现其实已经加载过了jdk的String了,那么就不会去加载自定义的String了,防止了重复加载 也加大了安全性。

5.java对象生命周期

java中一个对象的完整生命周期涉及java平台的很多技术。在创建一个java对象之前,需要先由虚拟机加载该类,然后对该java类进行链接和初始化。初始化完成之后,才创建出该类的对象实例。java对象也有自己的初始化过程,主要通过构造方法完成。当不再有引用指向该对象时,对象占用的内存会在合适的时机被垃圾回收器回收。对象终止机制提供了一种方式在对象被回收之前进行清理工作。
(1)java类的加载及初始化
(2)java对象的创建及初始化
1.在实际创建对象之前分配内存空间。所需的内存空间大小取决于Java类及其父类和祖先类包含的所有实例域的数量和类型。
2.内存分配成功之后将所有实例域设为默认值。
3.调用构造方法,类的构造方法调用过程分成三步:第一步是调用父类的构造方法,没有显示定义将会调用默认构造方法。第二步是按照书写顺序初始化类中的实例域。第三步是执行类的构造方法中的相应代码。
(3)对象终止
1.Java采用自动内存管理机制,对象回收工作由垃圾回收器自动完成
2.如果一定要手动处理相关工作,Java提供了finalize方法。
如果一个java类的对象有自定义的销毁逻辑,那么可以覆写Object类的finalize方法,并在finalize中添加代码。finalize中的这一段处理逻辑称为对象的终止器,但在实际的程序中并不实用。最主要的原因是java语言并没有规定finalize方法的调用时间进行明确规定,只是规定finalize方法一定在对象的内存空间被垃圾回收器回收之前进行调用,然而垃圾回收器的运行时间是不固定的,因此一个对象的回收时间也是不固定的。这双重的不固定性导致finalize运行时间不固定,容易产生与时间有关的错误。

5.JVM垃圾回收的时候如何确定垃圾?知道什么是GC Roots?

5.1 什么是垃圾?
简单来说就是内存中已经不在被使用过的空间就是辣鸡
5.2要进行垃圾回收,如何判断一个对象是否可以被回收?
(1)引用记数法
(2)枚举根节点做可达性分析
为了解决引用计数法的循环引用问题,Java使用可达性算法。
在这里插入图片描述
从一系列GC Roots的对象做为起点,从这些节点向下进行搜索所有的引用链,当一个对象到GC Roots没有任何引用链时,则证明次对象是不可用的。
5.3那些对象可以作为GC Roots的对象?
(1)虚拟机栈中引用的对象
(2)方法区中的类静态属性引用的对象
(3)方法区中常量引用的对象
(4)本地方法栈中JNI(Native方法)引用的对象

6.你说你做过 JVM 调优和参数配置,请问如何盘点查看 JVM 系统默认值?

6.1 JVM的参数类型
(1)标配参数: -version -help
(2)X参数(了解):
-Xint:解释执行
(3)XX参数
Boolean类型:-XX: +或者-某个属性值(+表示开启,-表示关闭)
-XX:+PrintGCDetails:打印GC收集细节
-XX:-PrintGCDetails:不打印 GC 收集细节
-XX:+UseSerialGC:使用了串行收集器
-XX:-UseSerialGC:不使用了串行收集器
KV设置类型:-XX:key=value
-XX:MetaspaceSize=128m
-XX:MaxTenuringThreshold=15
jinfo 举例,如何查看当前运行程序的配置

public class HelloGC {
    public static void main(String[] args) {
        System.out.println("hello GC....");

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

    }
}

我们可以使用 jps -l 命令,查出进程 id

D:\JAVA2\data structure>jps -l
13600 jvm.HelloGC
3284
18392 sun.tools.jps.Jps
25576 org.jetbrains.jps.cmdline.Launcher

在使用 jinfo -flag PrintGCDetails 13600 命令查看

-XX:-PrintGCDetails

可以看出默认是不打印GC的收集细节
也可是使用jinfo -flags 13600查看所有的参数

两个经典参数:-Xms 和 - Xmx(如 -Xms1024m)
-Xms 等价于 -XX:InitialHeapSize
-Xmx 等价于 -XX:MaxHeapSize
6.2盘点家底查看JVM默认值
查看初始默认值:-XX:+PrintFlagsInitial

[Global flags]
    uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
    uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
    uintx AdaptiveSizePausePolicy                   = 0                                   {product}
    uintx AdaptiveSizePolicyCollectionCostMargin    = 50                                  {product}
    uintx AdaptiveSizePolicyInitializingSteps       = 20                                  {product}
    uintx AdaptiveSizePolicyOutputInterval          = 0                                   {product}
    uintx AdaptiveSizePolicyWeight                  = 10                                  {product}
    uintx AdaptiveSizeThroughPutPolicy              = 0                                   {product}
    uintx AdaptiveTimeWeight                        = 25                                  {product}

查看修改更新:-XX:+PrintFlagsFinal

bool UsePSAdaptiveSurvivorSizePolicy           = true                                {product}
bool UseParNewGC                               = false                               {product}
bool UseParallelGC                            := true                                {product}
bool UseParallelOldGC                          = true                                {product}
bool UsePerfData                               = true                                {product}
bool UsePopCountInstruction                    = true                                {product}
bool UseRDPCForConstantTableBase               = false                               {C2 product}

= 与 := 的区别是,一个是默认,一个是人物改变或者 jvm 加载时改变的参数

7.平时开发中常用的JVM参数?

-Xms:初始大小内存,默认为物理内存的1/64;等价于-XX:InitialHeapSize
-Xmx:最大分配内存。默认为物理内存的1/4,等价与-XX:MaxHeapSize
-Xss:设置单个线程栈的大小,一般默认为512-1024k,等价与-XX:ThreadStackSize
-Xmn:设置年轻代的大小,整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小,持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-XX:MetaspaceSize:设置元空间大小(元空间的本质和永久代类似,都是对 JVM 规范中的方法区的实现,不过元空间于永久代之间最大区别在于,元空间并不在虚拟中,而是使用本地内存,因此默认情况下,元空间的大小仅受本地内存限制)
元空间默认比较小,我们可以调大一点
-XX:+PrintGCDetails:输出详细的GC收集日志信息

8.强引用、软引用、若引用、虚引用分别是什么?

在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用;java中根据其生命周期的长短,将引用分为4类。
8.1强引用
特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。
8.2软引用
特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。
应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。
8.3弱引用
特点:弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
应用场景:弱应用同样可用于内存敏感的缓存。
8.4虚引用
特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
ReferenceQueue queue = new ReferenceQueue ();
PhantomReference pr = new PhantomReference (object, queue);
程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。
应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

9请谈谈你对OOM的认识

9.1 java.lang.StackOverflowError: 栈溢出,在一个函数调用自己就会产生这个错误,比如递归。
9.2 java.lang.OutOfMenoryError:java heap sapce: 堆溢出,new一个很大的对象
9.3java.lang.OutOfMemoryError:GC overhead limit exceeded: 执行垃圾收集的时间比例太大, 有效的运算量太小,默认情况下,,如果GC花费的时间超过 98%, 并且GC回收的内存少于 2%, JVM就会抛出这个错误。
9.4java.lang.OutOfMemoryError:Direct buffer memory:直接内存溢出
配置参数:-Xms 10m -Xmx 10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m

public class DirectBufferDemo {
    public static void main(String[] args) {
        System.out.println("maxDirectMemory : " + sun.misc.VM.maxDirectMemory() / (1024 * 1024) + "MB");
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
    }
}

输出:

maxDirectMemory : 5MB
[GC (System.gc()) [PSYoungGen: 1315K->464K(2560K)] 1315K->472K(9728K), 0.0008907 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (System.gc()) [PSYoungGen: 464K->0K(2560K)] [ParOldGen: 8K->359K(7168K)] 472K->359K(9728K), [Metaspace: 3037K->3037K(1056768K)], 0.0060466 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
	at java.nio.Bits.reserveMemory(Bits.java:694)
	at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123)
	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311)
	at com.cuzz.jvm.DirectBufferDemo.main(DirectBufferDemo.java:17)
Heap
 PSYoungGen      total 2560K, used 56K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 2% used [0x00000000ffd00000,0x00000000ffd0e170,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 359K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 5% used [0x00000000ff600000,0x00000000ff659e28,0x00000000ffd00000)
 Metaspace       used 3068K, capacity 4496K, committed 4864K, reserved 1056768K
  class space    used 336K, capacity 388K, committed 512K, reserved 1048576K

这个错误常出现NIO通信中,因为NIO要在buffer中进行大量的读写。ByteBuffer.allocate分配的内存是在JVM管理范围内。创建效率高,读取和写入效率低。ByteBuffer.allocateDirect分配的内存不由JVM管理,分配的是直接内存。创建效率低,读取和写入的效率高。

10 GC垃圾回收算法和垃圾收集器的关系法?

10.1 GC垃圾回收算法
标记清楚(Mark-Sweep):算法分为“标记”和“清除”两个阶段,它是最基础的收集算法,后续的收集算法都是基于这种思路并对其不足进行改进而得到的。它的主要不足有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

复制回收:它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。

标记整理:根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
GC算法是内存回收的方法论,垃圾收集器就是算法的落地实现
10.2垃圾收集器
目前为止还没有完美的收集器出现,更加没有万能的收集器,只是针对具体引用最适合的收集器,进行分代收集。
(1)串行垃圾收集器(Serial):它为单线程环境设计且只使用一个线程进行垃圾回收,会暂停所有的用户线程,所以不适合服务环境。
(2)并行垃圾收集器(Parallel ):多个垃圾收集线程并行工作,此时用户线程是暂停的,用于科学计算、大数据处理等弱交互场景。
(3)并发垃圾收集器(CMS):用户线程和垃圾收集线程同时执行(不一定是并行,可能是交替执行),不需要停顿用户线程,互联网公司多用它,适用对相应时间有要求的场景。
(4)G1垃圾收集器:G1 垃圾回收器将堆内存分割成不同的区域然后并发的对其进行垃圾回收。

11. 怎么查看服务器默认垃圾收集器是哪个?生产是如何配置垃圾收集器?谈谈你对垃圾收集器的理解?

11.1怎么查看服务器默认的垃圾收集器是那个?
java -XX:+PrintCommandLineFlags
11.2 java的GC回收的类型主要有
UseSerialGC, UseParallelGC, UseConcMarkSweepGC, UseParNewGC, UseParallelOldGC, UseG1GC
java8以后基本不使用Serial Old
在这里插入图片描述
新生代
串行 GC (Serial/ Serital Copying)
并行 GC (ParNew)
并行回收 GC (Parallel/ Parallel Scanvenge)
老年代
串行 GC (Serial Old/ Serial MSC)
并行 GC (Parallel Old/ Parallel MSC)
并发标记清除 GC (CMS)
并发标记清除 GC (CMS)
是一种以获取最短回收停顿时间为目标的收集器,适合应用在互联网站或者 B/S 系统的服务器上,这个类应用尤其重视服务器的响应速度,希望系统停顿时间最短。
CMS 非常适合堆内存大、CPU 核数多的服务器端应用,也是 G1 出现之前大型应用首选收集器。
并发停顿比较少,并发指的是与用户线程一起执行。
从名字(包含“Mark Sweep”)上就可以看出,CMS收集器是基于“标记—清除”算法实现的,它的运作过程相对于前面几种收集器来说更复杂一些,整个过程分为4个步骤,包括:
(1)初始标记(CMS initial mark)
(2)并发标记(CMS concurrent mark)
(3)重新标记(CMS remark)
(4)并发清除(CMS concurrent sweep)
优缺点
优点:并发收集停顿低
缺点:并发执行对 CPU 资源压力大,采用的标记清除算法会导致大量碎片
11.3 垃圾收集器配置代码总结
配置新生代收集器,老年代收集器会自动配置上。
在这里插入图片描述
11.4 如何选择垃圾收集器
单 CPU 或者小内存,单机程序:-XX:UseSerialGC
多 CPU 需要最大吞吐量,如后台计算型应用:-XX:UseParallelGC 或者 -XX:UseParallelOldGC
多 CPU 追求低停顿时间,需要快速响应,如互联网应用:-XX:+UseConcMarkSweepGC

12 G1垃圾收集器了解吗?

12.1 以前收集器的特点
(1)年轻代和老年代是各自独立且连续的内存块
(2)年轻代收集器使用 eden + S0 + S1 进行复制算法
(3)老年代收集必须扫描整个老年代区域
(4)都是以尽可能的少而快速地执行 GC 为设计原则
12.2 G1是什么?
(1)G1 是一种面向服务端的垃圾收集器,应用在多核处理器和大容量内存环境中,在实现高吞吐量的同时,尽可能的满足垃圾收集器的暂停时间要求。
(2)像 CMS 收集器一样,能与应用程序线程并发执行,整理空闲空间更快,需要更多的时间来预测 GC 停顿时间,不希望牺牲大量的吞吐性能,不需要更大的 JAVA Heap。
(3)G1 收集器的设计目的是取代 CMS 收集器,同时与 CMS 相比,G1 垃圾收集器是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。G1 的 Stop The World 更可控,G1 在停顿上添加了预测机制,用户可以指定期望的停顿时间。
G1 是在 2012 年才在 jdk.1.7u4 中可以呀用,在 jdk9 中将 G1 变成默认垃圾收集器来代替 CMS。它是以款面向服务应用的收集器。
(4)主要改变是 Eden、Survivor 和 Tenured 等内存区域不再是连续的,而是变成了一个个大小一样的 region,每个 region 从 1M 到 32M 不等,一个 region 有可能属于 Eden、Survivor 或者 Tenured 内存区域。
12.3 特点
(1)G1 能充分利用多 CPU、多核环境硬件优势,尽量缩短 STW。
(2)G1 整体采用标记-整理算法,局部是通过是通过复制算法,不会产生内存碎片。
宏观上看 G1 之中不在区分年轻代和老年代,被内存划分为多个独立的子区域。
(3)G1 收集器里面讲整个的内存区域混合在一起,但其本身依然在小范围内要进行年轻代和老年代的区分。保留了新生代和老年代,但她们不在是物理隔离,而是一部分 Region 的集合且不需要 Region 是连续的,也就是说依然会采用不同的 GC 方式来处理不同的区域。
(4)G1 虽然也是分代收集器,但整个内存分区不存在物理上的年轻代和老年代的区别,也不需要完全独立的 Survivor to space 堆做复制准备。G1 只有逻辑上的分代概念,或者说每个分区都可能随 G1 的运行在不同代之间前后切换。

13.JVMGC+SpringBoot微服务的生产部署和调参优化

JVMGC——调优——SpringBoot调优
步骤:
(1)IDEA 开发完微服务工程
(2)maven进行clean——package
(3)要求微服务启动的时候,同时配置我们的JVMGC的调优参数
a. 内调:在IDEA中调
b. 外调:在cmd窗口配置:java -Server JVM的各种参数 -jar jar/war包的名字

14. 生产环境服务器变慢,诊断思路和性能评估谈谈?

查看整机:top load average:x,y,z
查看cpu:vmstat
内存:free-m pidstat -p进称号 -r采样间隔
硬盘:df 查看磁盘剩余空间数

15. 假如生产环境出现CPU过高,请谈谈你的分析思路和定位?

(1)先用 top 命令找出 CPU 占比最高的
(2)ps -ef 或者 jps 进一步定位,得知是一个怎么样的一个后台程序
(3)定位到具体的线程或代码
ps -mp 11111 -o THREAD,tid,time
-m 显示所有的线程
-p 进程使用cpu的时间
-o 该参数后是用户自定义格式
(4)将需要的线程 ID 转化为 16 进制格式
(5)jstat <进程ID> | grep <线程ID(16进制)> -A60

16.对于JDK自带的JVM监控和性能分析工具用过那些?一般是怎么用到的?

16.1 JDK本身就给我们提供了可以查询JVM的指令
jps——查看当前java进程
jinfo——查看正在运行的java应用程序的扩展参数
jstat——查看堆内存各部分的使用量、垃圾回收、类加载数量
16.2 可视化工具JConsole使用
首先在JDK的bin目录下,双击打开JConsole.exe程序 ,然后选择你自己启动的项目或者程序,双击即可打开监控界面。
在这里插入图片描述
在这里插入图片描述
JConsole查看当前程序/进程的全局情况
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值