jvm学习总结
  wqzTkljHCzgq 2023年11月02日 26 0

jvm学习总结

jvm学习总结_java

1、程序计数器

jvm学习总结_常量池_02

2、虚拟机栈

2.1、定义

控制栈的大小

Xss256kb  // 命令行参数

2.2、线程诊断

top 命令查看cpu运行情况
ps H -eo pid,tid,%cpu |grep 进程ID

2.3、线程死锁

void function(){
	while(true){
		// 方法一直循环不断地运行
	}
}

3、本地方法栈

Java 中使用native修饰的方法,说明这个方法是在本地方法区。

public class Object{

	public native Object clone(){
		
	}
}

4、堆

4.1、定义

控制堆内存的大小

Xmx8m

4.2、堆内存溢出

jvm学习总结_常量池_03

jvm学习总结_System_04

4.3、堆内存诊断

jvm学习总结_System_05

package com.bubaiwantong.heap;

import java.util.ArrayList;

public class Demo02 {
    public static void main(String[] args) {
        ArrayList<Student> students = new ArrayList<>();
        try {
            Thread.sleep(30000);
            for (int i = 0; i < 200; i++) {
                Student student = new Student();
                students.add(student);
            }
            Thread.sleep(300000);
        }catch (Exception e){
            e.printStackTrace();

        }
    }


}

class Student{

    private byte[] info = new byte[10 * 1024 * 1024];

}

jvm学习总结_常量池_06

5、方法区

5.1、定义

jvm学习总结_System_07

5.2、JDK版本比较

  • 1.8之前方法区在JVM内部
  • 1.8止呕方法区变成了元空间

jvm学习总结_常量池_08

永久代

  • -XX:MaxPermSize=8m
package com.bubaiwantong.method;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * 配置VM参数
 * -XX:MaxPermSize=8m
 */
public class Demo02 extends ClassLoader{
    public static void main(String[] args) {
        int count=0;
        try {
            Demo02 test = new Demo02();
            for (int i = 0; i < 10000; i++,count++) {
                ClassWriter cw = new ClassWriter(0);
                cw.visit(Opcodes.V1_8,Opcodes.ACC_PUBLIC,"Class" + i,null,"java/lang/Object",null);
                byte[] code = cw.toByteArray();
                test.defineClass("Class" + i,code,0,code.length);
            }
        }finally {
            System.out.println(count);
        }

    }

}

元空间

  • 配置VM参数
  • -XX:MaxMetaspaceSize=8m
package com.bubaiwantong.method;

import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;

/**
 * 配置VM参数
 * -XX:MaxMetaspaceSize=8m
 */
public class Demo01 extends ClassLoader{
    public static void main(String[] args) {
        int count=0;
        try {
            Demo01 test = new Demo01();
            for (int i = 0; i < 10000; i++,count++) {
                ClassWriter cw = new ClassWriter(0);
                cw.visit(Opcodes.V1_8,Opcodes.ACC_PUBLIC,"Class" + i,null,"java/lang/Object",null);
                byte[] code = cw.toByteArray();
                test.defineClass("Class" + i,code,0,code.length);
            }
        }finally {
            System.out.println(count);
        }

    }

}

jvm学习总结_常量池_09

5.4、运行时常量池

  • 常量池,就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
  • 运行时常量池,常量池是*.class文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址。

5.5、StringTable特性

jvm学习总结_常量池_10

串池讲解没有听懂,可以听下这个课程

package com.bubaiwantong.compile;

public class Demo03 {

    public static void main(String[] args) {

        // ["ab","a","b"]
        String x = "ab";
        String s = new String("a") + new String("b");
        // 堆 new String("a") new String("b") new String("ab")

        String s2= s.intern();
        // 将这个字符串对象尝试放入到串池,如果有则并不放入,如果没有则放入串池,会把串池中的对象返回。

        System.out.println(s2 == x);  // true  串池已经有"ab",所以直接取出来,和x相等
        System.out.println(s == x);   // false	这个是new String("ab")的对象,所以与“ab”并不相等
        // 归根结底还是看 == 比较的什么吧,== 判断连个对象的地址是否相等,而并不是判断两个对象的值相等。
    }
}

jvm学习总结_常量池_11

1) 调换位置

String x2=new String("c")+new String("d");
x2.intern(); // 将"cd"放入到串池中,然后x1将会从串池中取出"cd",所以这是两个相同的对象。
String x1= "cd";

System.out.println(x1 == x2); // true

2) JDK1.6

// jdk 1.6
String x2=new String("c")+new String("d");
x2.intern();  // 会将“cd”复制一份到串池中,也就是说把复制一份副本到串池中,而自己还在堆中,所以这两个x1和x2不是一个对象
String x1= "cd";

System.out.println(x1 == x2); // false

总结一下:intern()在jdk1.6执行,如果串池中没有,会复制一个副本,也就是说会新建一个对象吧,所以地址值也会不一样。

而在jdk1.8执行的时候,intern()这个函数会将x2自己放进去,所以当x1去取得时候,x1与x2会相等。

jvm学习总结_java_12

6、直接内存

6.1、定义

  • 直接内存 这块内存由可以说是共享内存,Java虚拟机和操作系统都可以访问

6.2、分配和回收原理

  • 使用了Unsafe对象完成了直接内存的分配回收,并且回收需要主动调用freeMemory方法
  • ByteBuffer的实现类内部,使用了Cleaner(虚引用)来监测ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Cleaner的clean方法调用freeMemory来释放直接内存。
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.reflect.Field;

/**
 * 直接内存 这块内存由可以说是共享内存,Java虚拟机和操作系统都可以访问
 */
public class Demo03 {
    static int _1GB = 1024*1024*1024;

    public static void main(String[] args) throws IOException {
        Unsafe unsafe= getUnsafe();
        long base = unsafe.allocateMemory(_1GB);  // 获取分配内存的地址
        unsafe.setMemory(base,_1GB,(byte ) 0); // 分配内存
        System.in.read();
        unsafe.freeMemory(base);  // 释放内存
        System.in.read();

    }

    public static Unsafe getUnsafe(){
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            Unsafe unsafe = (Unsafe ) f.get(null);
            return unsafe;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
  • 禁用显示的垃圾回收
-Xx:+DisableExplicitGC //显示的

jvm学习总结_常量池_13

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

上一篇: Redis秒杀 下一篇: 【MySQL】SQL优化
  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  2Vtxr3XfwhHq   2024年05月17日   53   0   0 Java
  Tnh5bgG19sRf   2024年05月20日   109   0   0 Java
  8s1LUHPryisj   2024年05月17日   46   0   0 Java
  aRSRdgycpgWt   2024年05月17日   47   0   0 Java
wqzTkljHCzgq