一:JVM的位置所在
JVM的位置是在操作系统和java程序之间,所以JVM并不是直接操作底层硬件系统的。所以插入一个话题,如果在新买的电脑上有java的环境,那应该已经是被用过的,除非商家安装的java环境,但是这种几率应该不高,所以说大概率应该是被坑了,别人用过的电脑(可以在cmd中,使用命令java -verison来查看)。
二:JVM的内存结构
(1)首先将.java源程序编译成.class文件(二进制)
(2) 然后将.class文件加载到类加载器中,这个class文件可能是本地的.class文件,也可能是从网络上获取过来的.class文件(实现序列化接口)
(3) 类加载器对class文件进行加载=>连接=>初始化的操作
(4) 下面则是到了JVM的运行数据区中(堆,栈,方法区,本地方发栈以及程序计数器)
类加载器(ClassLoader)
1:加载:是将本地的.class文件(或者网络节点的.class文件)中的二进制读入到内存中,把它放到运行时数据区的方法中,然后再堆区创建一个Class对象,用于封装类在方法区中的数据结构。class封装了类在方法区中的结构,并且向java程序提供了类在方法区中的数据结构接口。类的加载是由加载器完成的,加载器有:启动类加载器、扩展类加载器、系统类加载器、用户自定义类加载器。这里就牵扯到了java的双亲委派机制。
双亲委派机制:当某个类加载器需要加载某个.class文件,他首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
类加载器的类别:
(1)BootstrapLoader(启动加载器):c++
编写,加载java
核心库 java.*
,构造ExtClassLoader
和AppClassLoader
。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
(2)ExtClassLoader (标准扩展类加载器):java
编写,加载扩展库,如classpath
中的jre
,javax.*
或者java.ext.dir
指定位置中的类,开发者可以直接使用标准扩展类加载器。
(3)AppClassLoader(系统类加载器):java
编写,加载程序所在的目录,如user.dir
所在的位置的class
(4)CustomClassLoader(用户自定义类加载器):java
编写,用户自定义的类加载器,可加载指定路径的class
文件
作用: 1:防止重复加载同一个.class,通过委托到上面问一问,加载过了,就不用在加载一遍。保证数据安全。
2:保证核心.class不被篡改,通过委托方式,不会去篡改核心.class
,即使篡改也不会去加载,即使加载也不会是同一个.class
对象了。不同的加载器加载同一个.class
也不是同一个Class
对象。这样保证了Class
执行安全。
2:
验证:保证被加载的类的正确性;
准备:给类静态变量分配内存空间,赋值一个默认的初始值;
解析:把类中的符号引用转换为直接引用
3:初始化:给类的静态变量赋值正确的值。
运行时数据区:
(1)方法区:Method Area 方法区 是 Java虚拟机规范中定义的运行是数据区域之一,和堆(heap)一样可以在线程之间共享!
JDK1.7之前:永久代是用于存储一些虚拟机加载类信息,常量,字符串,静态变量等等,永久代是有限制的,如果满了会报OutofMemoryError:PerGen
JDK1.8之后:彻底将永久代移除HotPot Jvm,java Heap 中或者MetaSpace(Native Heap)空间
方法区重要就是来存:类信息,常量,字符串、静态变量、符号引用、方法代码。。。。。。
元空间和永久代,都是对JVM规范中方法区的实现。
元空间和永久代最大的区别:==元空间并不在Java虚拟机中,使用的是本地内存!==
-XX:MetasapceSize10m
(未完待续......)
原文:https://www.cnblogs.com/clover-forever/p/12492255.html