认识JVM

1.JVM的位置和jvm的体系结构

在这里插入图片描述

2.类加载器(Class Loader)

类加载器的作用:

  • 加载Class文件–>Class Loader加载并初始化 做一些实例化的操作
    类加载器首先是:
    AppClassLoader 应用类加载器,主要负责加载应用程序的主函数类
    ExtClassLoader 扩展类加载器,主要负责加载jre/lib/ext目录下的一些扩展的jar
    BootstrapClassLoader 根加载器,主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader
public class Car {
    public static void main(String[] args) {
//        classloader加载实例化几个对象
        Car car1 = new Car();

        //同一个class文件
        Class<? extends Car> aClass1 = car1.getClass();


        //同一个加载器
        ClassLoader classLoader1 = aClass1.getClassLoader();
        System.out.println(classLoader1);//这个是AppClassLoader 容器加载器
        ClassLoader parent = classLoader1.getParent();//这个是ExtClassLoader 扩展类加载器
        System.out.println(parent);
        System.out.println(parent.getParent());//根加载器,java取不到
    }
}

输出的结果是
在这里插入图片描述

3.双亲委派机制(转载自:添加链接描述)
在这里插入图片描述
当一个类的class文件要被加载时,会通过由下至上的查找顺序,先去应用类加载器去查找是否加载过,没有加载过就去扩展类加载器去同样的查找,直到根加载器,然后再考虑是否能够由自己加载,注意的是在查找到根加载器之前都不会去选择加载class文件,如果根加载器无法加载文件,会下沉到扩展类直到应用类加载器,由上至下的加载顺序,都加载不了就会抛出异常.
双亲委派机制的好处和作用是:1.避免重复加载,2.防止恶意篡改java的核心包代码
在这里插入图片描述

4.沙箱安全机制:就是java的安全模式(保证java程序的安全性)
jvm将java代码限定在特定的环境中运行,就会需要通过一些检测器来确保代码的安全性

1.字节码校验器
2.类装载器
3.存取控制器
4.安全管理器
5安全软件包

5.Native关键字
凡是调用了Native方法的,表示java层面是接触不到的,为融合不同的语言和扩展java程序的使用(简单理解是调用C++)
在java包里有native方法的时候,就会在类加载的时候在运行时数据区域里开辟了一块本地方法栈,用于登记native本地方法,可参考最上面的图片

   public static void main(String[] args) {
        new Thread(()->{

        }).start();
    }

点入start方法会看见:

 public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();//这里在java运行区域开辟了一块本地方法栈,用于登记native本地方法
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

//这个start0(),调用的是本地方法接口,JNI
    private native void start0();

6.PC寄存器—>程序计数器

每个线程有一份
作用:PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令。

7.方法区,方法区能存放的是什么?和堆 栈里放的有什么不一样?方法区具体在哪儿?
首先确定方法区的概念:参考添加链接描述
通过下面的图和实例看出

  •  1.方法区里放的是static变量,final常量(方法区里包含了常量池),和Class里的数据以及构造函数
    
  •  2.new 出来的对象都放在堆中,还有非static修饰的成员变量
    
  •  3.每个线程都有自己的一个栈区,栈区里面存放对象的引用 和 基础数据(8种基本数据类型)
    

在这里插入图片描述

public class  PersonDemo
{
	public static void main(String[] args) 
	{   //局部变量p和形参args都在main方法的栈帧中
		//new Person()对象在堆中分配空间
		Person p = new Person();
		//sum在栈中,new int[10]在堆中分配空间
		int[] sum = new int[10];
	}
}


class Person
{   // 实例变量name和age在堆(Heap)中分配空间
	private String name;
	private int age;
	//类变量(引用类型)name1和"cn"都在方法区(Method Area)
	private static String name1 = "cn";
	//类变量(引用类型)name2在方法区(Method Area)
	//new String("cn")对象在堆(Heap)中分配空间
	private static String name2 = new String("cn");
	//num在堆中,new int[10]也在堆中
	private int[] num = new int[10];


	Person(String name,int age)
	{	
		//this及形参name、age在构造方法被调用时
		//会在构造方法的栈帧中开辟空间
		this.name = name;
		this.age = age;
	}
	
	//setName()方法在方法区中
	public void setName(String name)
	{
		this.name = name;
	}

	//speak()方法在方法区中
	public void speak()
	{
		System.out.println(this.name+"..."+this.age);
	}

	//showCountry()方法在方法区中
	public static void  showCountry()
	{
		System.out.println("country="+country);
	}
}

————————————————
原文链接:https://blog.csdn.net/u013241673/article/details/78574770

8.栈:数据结构(和队列类似)

队列; 先进先出 --> 两头没堵住的管道(FIFO: Fisrt input Fisrt Output)
栈:一个有底的桶,先进后出,后进先出

  • 程序 = 数据结构 + 算法!!!
  • 栈:有栈底和栈顶,管理程序的运行,生命周期和线程周期同步(创建->就绪->运行->阻塞->结束),线程结束,栈内存就会释放,不存在垃圾回收问题
  • 栈里存放的是一个个栈帧,栈帧里包含: 8大基本数据类型 + 对象 + 实例的方法

栈帧里有的元素
1.方法索引(index)
2.输入输出参数
3.本地变量
4.ClassFile(引用)
5.父帧
6.子帧

9.堆Heap

gc分为轻gc() 和 重gc(Full GC)

一个jvm只有一个堆内存,但是可以通过调节参数,调节大小.
类加载器读取了类文件后,一般会把什么放在堆中? ===>保存所有引用类型的真实对象

  • 方法
  • 常量
  • 变量

堆的细分:

新生区(伊甸园区Eden Space–>幸存0区–>幸存1区) 垃圾回收主要是在新生区和养老区
老年区(养老区)
永久区(JDK1.8以后叫元空间) 一般存放的是JDK自身携带的class对象,interface元数据
永久区逻辑上存在,物理上是不存在的

新生区

类:诞生和成长的地方,甚至死亡
伊甸园区:所有new出来的对象都是在

    public static void main(String[] args) {
     //返回虚拟机试图使用的最大内存
        long l = Runtime.getRuntime().maxMemory();
        System.out.println(l/1024/1024);
        //返回jvm的总内存
        long totalMemory = Runtime.getRuntime().totalMemory();
        System.out.println(totalMemory/1024/1024);

    }
//OOM情况下
//1.调大jvm内存-Xms1024m -Xmx1024m -XX:+PrintGCDetails
//2.看代码问题

确认元空间的大小

通过设置jvm的大小后,新生区的大小为 305664k + 老年区的大小699392k = 1005056k = 981.5M ,表示元空间在物理上的大小是0,存在于理论上
在这里插入图片描述

使用JProfiler工具分析OOM原因

如何在一个项目中排除OOM故障,研究为什么出错

1.内存快照分析工具,MAT,Jprofiler
2.Debug(不适用)

MAT和Jprofile作用:
1.分析Dump内存文件,快速定位内存泄露
2.获得堆中的数据
3.获得大的对象
Jprofiler通过dump文件命令下载文件进行分析:

-Xms1m 这个是设置初始化的jvm内存 -Xmx8m 这个是设置最大的内存空间
-Xms5m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError 堆内存溢出就下载文件
-Xms1m -Xmx8m -XX:+PrintGC 每次触发GC的时候打印相关日志
-XX:+PrintGCDetails 更详细的GC日志
-XX:MaxTenuingThreshold=进行设置 (默认为15次,在新生代存活的对象进行老年区)

GC算法

GC主要是在堆里的新生区进行回收
堆分为:新生区(方法区逻辑上在新生区) 老年区(当一个对象经历了15次GC还没死亡) 元空间(元空间物理上不存在,逻辑上存在)
新生区分为,在新生区的两个幸存区中,谁空谁是to:
	伊甸区(Eden)
	幸存区(To)
	幸存区(From)
GC分为两种:轻GC(普通的GC) 重GC(全局GC)	

GC的算法:

  • 标记清除法
  • 标记压缩
  • 复制算法:复制算法是发生在新生代,保证没有内存碎片,每次将From区的对象,复制到To区,此时为空的幸存区会变为To区,有对象的幸存区为From,但是会浪费一点内存
  • 引用计数器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值