JVM运行时内存模型详解,元空间优化,new关键字详解,堆栈溢出详解

jvm运行时数据分区

在这里插入图片描述

  • 虚拟机栈:Stack Frame 存储栈帧(一对多
  • 程序计数器(Program Counter) 记录行号方便定位
  • 本地方法栈:主要用于处理本地方法 (c++ c 执行的内部方法 HotSpot虚拟机将本地方法栈和虚拟的合二为一
  • 堆(Heep): JVM管理的最大一块内存空间 与堆相关的重要概念:垃圾回收器。现代几乎所有的垃圾收集器都是采用的分代收集算法,所以,堆空间也基于这一点进行了相应的划分:新生代与老年代,Bden空间,From Survivor空间与To Survivor空间
  • 方法区(Method Area): 存储元(Class类的信息 包含常量池)数据。永久代(Permanent Generration),从JDK1.8开始,已经彻底废弃了永久代,使用元空间(meta space)

运行时常量池:方法区的一部分内容。

  • 直接内存:Direct Memory,与Java NIO密切相关,JVM通过堆上的DirectByteBuffer来操作直接内存。(元空间存储在直接内存能扩容到最大的本地内存metaspace,内存大小由虚拟机来决定的

元空间 (问题和优化)

参考:Java永久代去哪了?

问题

元空间和永久代其实都可以理解为是方法区的的一种实现 它们之间的关系好比接口和实现类的关系遵循着方法区的规则jdk1.8之前永久代是封装到堆内存当中。jdk1.8之后元空间是将源数据封装到直接(本地)内存
元空间存在问题
1.未限制-XX:MaxMatespaceSize最大数量会延伸到交换区这时候当我们进行本地内存分配时将会失败。
2.元空间的生命周期是跟随类加载器,区块内存的大小由类加载器决定大小不一就会导致碎片化,元空间虚拟机目前并不支持压缩操作,所以碎片化是目前最大的问题。

优化

  1. 为了避免频繁的 GC,建议将–XX:MetaspaceSize 设置为一个相对较高的值。
  2. XX:MinMetaspaceFreeRatio 和‑XX:MaxMetaspaceFreeRatio,他们类似于 GC 的
    FreeRatio 选项,用来设置元空间空闲比例的最大值和最小值

元空间虚拟机控制元空间的增长。但是有些时候我们想限制其增长,比如通过显式在命令行中设置 -XX:MaxMetaspaceSize**。默认情况下,-XX:MaxMetaspaceSize 的值没有限制,因此元空间甚至可以延伸到交换区,但是这时候当我们进行本地内存分配时将会失败。

对于一个 64 位的服务器端 JVM 来说,其默认的–XX:MetaspaceSize 值为 21MB(JVM会自动调整)。这就是初始的高水位线。一旦触及到这个水位线,Full GC 将会被触发并卸载没有用的类(即这些类对应的类加载器不再存活),然后这个高水位线将会重置。新的高水位线的值取决于 GC 后释放了多少元空间。如果释放的空间不足,这个高水位线则上升。如果释放空间过多,则高水位线下降。如果初始化的高水位线设置过低,上述高水位线调整情况会发生很多次。通过垃圾回收器的日志我们可以观察到 Full GC 多次调用为了避免频繁的 GC,建议将–XX:MetaspaceSize 设置为一个相对较高的值

经过多次 GC 之后,元空间虚拟机自动调节高水位线,以此来推迟下一次垃圾回收到来。

有这样两个选项 ‑XX:MinMetaspaceFreeRatio 和‑XX:MaxMetaspaceFreeRatio,他们类似于 GC 的 FreeRatio 选项,用来设置元空间空闲比例的最大值和最小值。我们可以通过命令行对这两个选项设置对应的值。

使用工具

示例

public class MyTest5 {
    
    
    public static void main(String[] args) {
    
    
        for(;;){
    
    
            //字符串存储在常量池 当不断的向元空间打印相同的字符串元空间占用内存和可用内存数据不会增加
            System.out.println("hello world");
        }
    }
}

jmap 指令
    <none>               to print same info as Solaris pmap
    -heap                to print java heap summary
    -histo[:live]        to print histogram of java object heap; if the "live"
                         suboption is specified, only count live objects
    -clstats             to print class loader statistics
    -finalizerinfo       to print information on objects awaiting finalization
    -dump:<dump-options> to dump java heap in hprof binary format
                         dump-options:
                           live         dump only live objects; if not specified,
                                        all objects in the heap are dumped.
                           format=b     binary format
                           file=<file>  dump heap to <file>
                         Example: jmap -dump:live,format=b,file=heap.bin <pid>
    -F                   force. Use with -dump:<dump-options> <pid> or -histo
                         to force a heap dump or histogram when <pid> does not
                         respond. The "live" suboption is not supported
                         in this mode.
    -h | -help           to print this help message
    -J<flag>             to pass <flag> directly to the runtime system

  • jmap -clstats PID 打印类加载器数据。(-clstats 是 -permstat 的替代方案,在 JDK8
    之前,-permstat 用来打印类加载器的数据)。下面的例子输出就是 DaCapo’s Avrora benchmark
    程序的类加载器数据
D:\workspaces\jvm>jmap -clstats 2124 
Attaching to process ID 2124, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.....................done.
class_loader加载器    classes bytes 字节数  parent_loader父加载器   alive?是否存活  type 类型

<bootstrap>     570     1084282   null          live    <internal>
0x000000076b69e0d8      27      77105   0x000000076b61ad18      live    sun/misc/Launcher$AppClassLoader@0x00000007c000f6a0
0x000000076b61ad18      0       0         null          live    sun/misc/Launcher$ExtClassLoader@0x00000007c000fa48

total = 3       597     1161387     N/A         alive=3, dead=0     N/A

  • jmap -heap PID 打印当前进程java堆信息
D:\workspaces\jvm>jmap -heap 8928
Attaching to process ID 8928, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.161-b12

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4261412864 (4064.0MB)
   NewSize                  = 88604672 (84.5MB)
   MaxNewSize               = 1420296192 (1354.5MB)
   OldSize                  = 177733632 (169.5MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation //年轻代
Eden Space:
   capacity = 66584576 (63.5MB)
   used     = 7991240 (7.621040344238281MB)
   free     = 58593336 (55.87895965576172MB)
   12.00163833738312% used
From Space:
   capacity = 11010048 (10.5MB)
   used     = 0 (0.0MB)
   free     = 11010048 (10.5MB)
   0.0% used
To Space:
   capacity = 11010048 (10.5MB)
   used     = 0 (0.0MB)
   free     = 11010048 (10.5MB)
   0.0% used
PS Old Generation //老年代
   capacity = 177733632 (169.5MB)
   used     = 0 (0.0MB)
   free     = 177733632 (169.5MB)
   0.0% used

1814 interned Strings occupying 162056 bytes.

jstat 指令
  • jstat -gc LVMID 用来打印指定元空间的信息,具体内容如下主要查看 MC(当前元空间容量)和 MU (已经被占用的元空间容量)数据
D:\workspaces\jvm>jstat -gc 10600
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
10752.0 10752.0  0.0    0.0   65024.0   7803.9   173568.0     0.0     4480.0 770.9  384.0   75.9       0    0.000   0      0.000    0.000

  • 当不断的向元空间打印相同的字符串元空间占用内存和可用内存数据不会增加,执行MyTest4使用cglib动态生成新的class类型 元数据大小动态增加元空间的容量上限是设置的200M超过了就会抛出OutOfMemoryError: Matespace 错误(jdk1.8之后)

在这里插入图片描述

jps指令 打印当前java进程id和进程名
usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]
D:\workspaces\jvm>jps
3984 Launcher
6388 Launcher
10136 Jps
5164
D:\workspaces\jvm>jps -l //打印当前进程的id和全路径名
6388 org.jetbrains.jps.cmdline.Launcher
6724 com.example.demo.com.jvm.memory.MyTest4
9240 org.jetbrains.jps.cmdline.Launcher
5164
9628 sun.tools.jps.Jps


D:\workspaces\jvm>jps -Vv //mlvV可以拆开或组合使用


jcmd获取当前jvm上所有进程的详细信息
常用命令(重要)
jps -l // 查看当前java进程
jcmd 8536 help //列出当前进程的可用操作指令
jcmd 1144 VM.flags //查看 1144 MyTest4的JVM对应的所有参数
jcmd 8536 help JFR.dump //查看操作指令的文档信以及对应指令的 指令信息
jcmd 8536 PerfCounter.print //输出当前进程性能相关内容
jcmd 8536 VM.uptime //查看 pid进程的运行时长 单位s
jcmd 7828 GC.class_histogram //查看 pid进程的 类的统计信息
jcmd 4660 Thread.print //查看线程的堆栈信息
 //将堆栈信息导出到本地指定文件test.hprof 没有则创建 可以通过jvisualvm
jcmd 4660 GC.heap_dump C:\Users\Admin\Desktop\spring\test.hprof
jcmd 6104 VM.system_properties //查看指定id 的jvm的属性信息
jcmd 8936 VM.version //查看JVM版本 
jcmd 8936 VM.command_line // 查看jvm的启动命令行参数信息

jcmd 和 jsp 其实是一样的 只不过 信息打印的更加详细
在这里插入图片描述

D:\workspaces\jvm>jcmd -help
Usage: jcmd <pid | main class> <command ...|PerfCounter.print|-f file>
   or: jcmd -l
   or: jcmd -h

  command must be a valid jcmd command for the selected jvm.
  Use the command "help" to see which commands are available.
  If the pid is 0, commands will be sent to all Java processes.
  The main class argument will be used to match (either partially
  or fully) the class used to start Java.
  If no options are given, lists Java processes (same as -p).

  PerfCounter.print display the counters exposed by this process
  -f  read and execute commands from the file
  -l  list JVM processes on the local machine
  -h  this help

  • 查看当前的进程的Jvm参数
D:\workspaces\jvm>jps -l
1440 org.jetbrains.jps.cmdline.Launcher
6388 org.jetbrains.jps.cmdline.Launcher
7636 sun.tools.jps.Jps
1144 com.example.demo.com.jvm.memory.MyTest5
2172 com.example.demo.com.jvm.memory.MyTest4
5164


D:\workspaces\jvm>jcmd 1144 VM.flags //查看 1144 MyTest4的JVM对应的所有参数
1144:
-XX:CICompilerCount=4 -XX:InitialHeapSize=266338304 -XX:MaxHeapSize=4261412864 -XX:MaxNewSize=1420296192 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88604672 -XX:OldSize=177733632 -XX:+UseCompressedClassPointers -XX:+UseCompressedO
ops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC


D:\workspaces\jvm>jcmd 2172 VM.flags //查看MyTest5的进程参数 包含自己设置的参数
2172:
-XX:CICompilerCount=4 -XX:InitialHeapSize=266338304 -XX:MaxHeapSize=4261412864 -XX:MaxMetaspaceSize=209715200 -XX:MaxNewSize=1420296192 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88604672 -XX:OldSize=177733632 -XX:+UseCompressedCl
assPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
//计算-XX:MaxMatespaceSize 的堆内存
D:\workspaces\jvm>python
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 209715200/1024
204800 
>>> 204800/1024
200 //正好 200m 就是我们设置的值

  • 查看某个指令的详细操作信息
D:\workspaces\jvm>jcmd 8536 help JFR.dump
8536:
JFR.dump
Copies contents of a JFR recording to file. Either the name or the recording id must be specified.
将JFR录制的内容复制到文件中。必须指定名称或录制id。
Impact: Low

Permission: java.lang.management.ManagementPermission(monitor)

Syntax : JFR.dump [options]

Options: (options must be specified using the <key> or <key>=<value> syntax)
        name : [optional] Recording name, e.g. \"My Recording\" (STRING, no default value)
        recording : [optional] Recording number, use JFR.check to list available recordings (JLONG, -1)
        filename :  Copy recording data to file, i.e \"C:\Users\user\My Recording.jfr\" (STRING, no default value)
        compress : [optional] GZip-compress "filename" destination (BOOLEAN, false)

  • 查看JVM性能的相关参数
D:\workspaces\jvm>jcmd 8536 PerfCounter.print
8536:
java.ci.totalTime=446592
java.cls.loadedClasses=560
java.cls.sharedLoadedClasses=0
java.cls.sharedUnloadedClasses=0
java.cls.unloadedClasses=0
java.property.java.class.path="C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Ja
va\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Fil
  • 查看当前进程的运行时长
D:\workspaces\jvm>jcmd 8536 VM.uptime
8536:
1204.853 s

  • 查看 pid进程的 类的统计信息
序号            类实例数         占用字节      class
1278:             1             16  sun.security.provider.NativeSeedGenerator
1279:             1             16  sun.security.util.AlgorithmDecomposer
1280:             1             16  sun.security.util.DisabledAlgorithmConstraints$Constraints
1281:             1             16  sun.util.calendar.Gregorian
1282:             1             16  sun.util.locale.provider.AuxLocaleProviderAdapter$NullProvider
1283:             1             16  sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter
1284:             1             16  sun.util.locale.provider.SPILocaleProviderAdapter
1285:             1             16  sun.util.resources.LocaleData
1286:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl
 //统计  因为是静态创建不是运行期动态生成一般编译期都确定好了不会改变 如果是运行期则会不断增加
Total         73051       21463968  

  • 将堆栈信息打印到本地
D:\workspaces\jvm>jcmd 4660 GC.heap_dump C:\Users\Admin\Desktop\spring\test.hprof
4660:
Heap dump file created //文件创建成功

通过jvisualvm 打开之后可以查看堆对应的信息
在这里插入图片描述

jstack指令 线程堆栈信息的分析工具
D:\workspaces\jvm>jstack
Usage:
    jstack [-l] <pid>  //获取pid线程的堆栈信息
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

jmc指令 实时获取java进程的统计数据

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

将jcmd集成到这里面
在这里插入图片描述

new 关键字创建对象的3个步骤:

  • 1.在堆内存中创建出对象实例
    -类加载检测
    -分配内存分两种1.指针碰撞,2.空闲列表
  • 2.为对象的实例成员变量赋初值(成员变量赋值在构造方法中完成的)
  • 3.将对象的引用返回

指针碰撞,空闲列表

  • 指针碰撞(前提是堆中的空间通过一个指针进行分割,一侧已经被占用的空间,另一侧是未被占用的空间)
  • 空闲列表(前提是堆内存空间中已被使用与未被使用的空间是交织在一起的,这时,虚拟机就需要通过一个列表来记录哪些空间是可以使用的哪些空间已经被使用了,接下来找出来可以容纳下新创建对象的且未被使用的空间,在此空间存放该对象,同时还要修改列表上的记录)

对象内存的布局

在Hotspot虚拟机中 对象在内存的布局分为三个区域 对象头(存在元数据指针和hash码),实例数据(成员变量)和对齐填充(占位作用)

对象的访问定位

  1. 句柄:如果使用句柄的话,那么 Java 堆中将会划分出一块内存来作为句柄池,reference 中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息;

在这里插入图片描述
2. 直接指针:如果使用直接指针访问,那么 Java 堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而 reference 中存储的直接就是对象的地址。
在这里插入图片描述

OutOfMemoryError 堆内存溢出

jvm参数

-Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError 堆空间最小5兆最大5兆 出现错误打印到磁盘
public class MyTest1 {
    
    


    public static void main(String[] args) {
    
    

        List<MyTest1> list = new ArrayList<>();

        for (; ; ) {
    
    
            //堆中开辟大量空间
            list.add(new MyTest1());
            //尽最大努力 快速回收未被使用的对象
            System.gc();
        }

    }

//设置参数 -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError 堆空间最小5兆最大5兆 出现错误打印到磁盘
//堆中开辟内存>堆空间内存  会抛出OutOfMemoryError异常

//jvisualvm工具
}


打印

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12244.hprof ...
Heap dump file created [7758416 bytes in 0.022 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:3210)
	at java.util.Arrays.copyOf(Arrays.java:3181)
	at java.util.ArrayList.grow(ArrayList.java:265)
	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
	at java.util.ArrayList.add(ArrayList.java:462)
	at com.example.demo.com.jvm.memory.MyTest1.main(MyTest1.java:46)

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

StackOverflowError 虚拟机栈溢出

JVM参数

-Xss50k 将栈内存设置成50K

示例

/**
 * 虚拟机栈溢出
 */
public class MyTest2 {
    
    

    private int length;

    public int getLength() {
    
    
        return length;
    }

    public void setLength(int length) {
    
    
        this.length = length;
    }

   public void test() {
    
    
        this.length++;
        try {
    
    
            Thread.sleep(300);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        this.test();
    }
    public static void main(String[] args) {
    
    
        MyTest2 myTest2 = new MyTest2();

        try {
    
    
            myTest2.test();

        } catch (Throwable t) {
    
    
            System.out.println(myTest2.length);
            t.printStackTrace();
        }
    }
}

当栈设置太小 打印

Error: Could not create the Java Virtual Machine.

错误:无法创建Java虚拟机。

Error: A fatal exception has occurred. Program will exit.

错误:发生了致命异常。程序将退出。



The stack size specified is too small, Specify at least 108k

指定的堆栈大小太小,请至少指定108k  必须的108K才能创建虚拟机

当设置成指定的108K 堆栈溢出
打印

java.lang.StackOverflowError
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:19)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
991
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)
	at com.example.demo.com.jvm.memory.MyTest2.test(MyTest2.java:21)

监控工具

此时可以用jconsole工具 或者jvisualvm工具来监测当前类的所以信息
运行点击对应的全路径类
在这里插入图片描述
在这里插入图片描述

死锁

public class MyTest3 {
    
    

    public static void main(String[] args) {
    
    
		//AB递归调用 当执行第一次就行成了死锁
        new Thread(() -> A.method(),"ThreadA").start();
        new Thread(() -> B.method(),"ThreadB").start();
    }
}


class A {
    
    
    public static synchronized void method() {
    
    

        System.out.println("method a");
        try {
    
    
            Thread.sleep(5000);
            B.method();

        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

class B {
    
    
    public static synchronized void method() {
    
    
        System.out.println("method b");

        try {
    
    
            Thread.sleep(5000);
            A.method();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
    }
}

可以看到工具中AB互相锁定
jconsole

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

OutOfMemoryError 方法区内存溢出

JVM指令

元空间指令
 -XX:MaxMetaspaceSize=10m 最大元空间内存为10m
 ‑XX:MinMetaspaceFreeRatio 和‑XX:MaxMetaspaceFreeRatio,
 他们类似于 GC 的 FreeRatio 选项,用来设置元空间空闲比例的最大值和最小值。
/**
 * 方法区产生内存溢出 采用cglib不断在元空间增加实例
 */
public class MyTest4 {
    
    

    public static void main(String[] args) {
    
    
        for (; ; ) {
    
    
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(MyTest4.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> proxy.invokeSuper(obj, args1));

            System.out.println("helld world");
            enhancer.create();
        }

        //元空间指令 -XX:MaxMetaspaceSize=10m 最大元空间内存为10m
        //OutOfMemoryError 元空间溢出错误
    }
}

打印

helld world
helld world
helld world
Exception in thread "main" net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:348)
	at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
	at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:117)
	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)
	at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
	at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
	at com.example.demo.com.jvm.memory.MyTest4.main(MyTest4.java:19)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)
	... 6 more
Caused by: java.lang.OutOfMemoryError: Metaspace //内存错误:元空间 jdk1.8之后
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
	... 11 more

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

猜你喜欢

转载自blog.csdn.net/qq_42261668/article/details/108770675