java复习之JVM

JVM JDK JRE 的关系

JDK:Java Development Kit 是提供给java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK,就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等
JVM:是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。
JRE:Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包
在这里插入图片描述

什么是跨平台性?

就是java语言编写的程序,一次编译之后,可以在多个系统的平台运行,是通过JVM实现的,只要该系统安装了相应的java虚拟机,该系统就可以运行java程序

什么情况下会发生栈内存溢出

1 栈是线程私有的,它的生命周期和线程的生命周期是一样的,每个方法在执行的时候都会创建一个栈帧,用来存放局部变量,操作数栈,动态链接,方法出口等信息。局部变量有包含基本的数据类型,和引用的数据类型。
2 虚拟机栈溢出: 当线程请求的栈深度大于jvm所允许的最大深度的时候,就会抛出StackOverfloweError异常
3 本地方法栈溢出: 当在多线程的情况下,大量创建新的线程,导致新建立线程的时候没有足够的内存去创建对应的虚拟机栈,就会抛出OutOfMemory异常
4参数 -Xss 去调整JVM栈的大小

OOM内存溢出和内存泄漏

什么是内存泄漏

无用对象(不再使用的对象)持续占用内存或 无用对象的内存值得不到及时的释放,从而造成内存空间的浪费。内存泄漏最终会导致内存溢出的。结合一些工具如jmap,检查分析内存中的对象 或者重启java进程。

什么情况下会导致内存泄漏

1 使用单例模式造成的内存泄漏,
2 创建非静态内部类或者匿名内部类的对象可能会导致内存泄漏
3 资源未关闭可能会导致内存泄漏
4 使用集合ring器可能会导致内存泄漏

内存溢出

内存溢出发生在除了程序计数器之外的5个区域,会导致整个java进程挂掉,主要是你想要的内存超过了系统给你分配的内存空间。
java常见的内存溢出

  1. 堆溢出 : 不断的常见对象实例,当对象的数量达到了堆的最大容量限制后产生的内存溢出异常
  2. 栈溢出: 当线程请求的栈深度大于jvm所允许的最大深度的时候,就会抛出StackOverfloweError异常
  3. 本地方法栈溢出: 当在多线程的情况下,大量创建新的线程,导致新建立线程的时候没有足够的内存去创建对应的虚拟机栈,就会抛出OutOfMemory异常
  4. 运行时常量池溢出:代码在运行的时候创建了大量的常量超出了常量池的上限
  5. 方法区溢出:动态加载了大量的class信息,超出了方法区的上限

内存泄漏和内存溢出的关系

JVM内存模型

在这里插入图片描述
线程私有的:

  1. 程序计数器: 当前线程所执行的字节码的行号指示器。
  2. JVM虚拟机栈: 每个方法在执行的同时就会创建一个栈帧用来存放局部变量,操作数栈,动态链接,方法出口等信息。每一个方法的调用到执行完毕的过程,就对应一个栈帧在虚拟机中入栈和出栈的过程。
  3. 本地方法栈: 本地方法栈和虚拟机栈的作用是一样的,但是区别是本地方法栈为虚拟机使用的Native方法提供服务,虚拟机栈为java方法提供服务。
    线程共享的
  4. 堆:在JVM启动的时候创建,是java内存最大的一块。所有对象的实例以及数组都要往堆上分配,也是GC回收的地方,如果堆上没有足够的内存完成实例分配并且无法拓展的时候,就会抛出堆溢出异常。
    字符串常量池: 用于存储字符串对象、或者字符串对象的引用
  5. 方法区:存放已经被加载的类的信息、常量、静态变量、即时编译器编译后的代码数据等。
    运行时常量池:编译器运行时候产生的常量放在运行常量池中,这里的常量包含:基本数据类型、包装类和String

java程序运行的机制

在这里插入图片描述
1 首先利用工具编写java源代码,源文件的后缀名为.java文件
2 通过编译器把java文件变成字节码文件,字节码文件后缀名为.class
3 通过类加载把这些字节码文件加载到JVM中由CPU执行

什么是类加载器,了解那些类加载器

**类加载器:**根据指定权限名称将class文件加载到JVM内存,转为class对象
启动类加载器:由C++语言实现,负责将存放在<JAVA_HOME>\lib目录或-Xbootclasspath参数指定的路径中的类库加载到内存中。其他的都有java语言实现。
扩展类加载器:负责加载<JAVA_HOME>\lib\ext目录或java.ext.dirs系统变量指定的路径中的所有类库。
应用程序类加载器:。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
自定义类加载器:

双亲委派模型图

在这里插入图片描述

为啥需要双亲委派模型

工作流程:当一个类收到了类加载的请求,它首先不会自己加载这个类,而是先把请求委托到父类加载去完成,每一层加载器都是如此,因此所有的类加载请求都会传输到顶层的类加载器中。如果父类加载器反馈自己无法完成这个加载请求(就是他搜索的范围内没有所需的类),子类才会尝试自己去加载。主要是为了保证类的唯一性,防止内存中出现多份同样的字节码。

怎么打破双亲委派模型?

打破双亲委派机制则不仅要继承ClassLoader类,还要重写loadClass和findClass方法。

JVM内存模型的相关知识了解多少,比如重排序,内存屏障,happen-before,主内存,工作内存。

1)Java内存模型图:
在这里插入图片描述
jvm内存模型规定所有变量都存储在主内存中,每条线程都有自己的工作内存,线程的工作内存保存了该线程用到的变量的副本拷贝,线程对所有的共享变量的操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间不能访问对方的工作内存中的变量,而是要通过主内存来访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值