JVM快速入门

JVM的结构

类加载器

作用:加载Class文件

1.虚拟机带的加载器

2.启动类(根)加载器

3.扩展类加载器

4.应用程序(系统)加载器

双亲委派机制

双亲委派的工作过程:上委托查找,向下委托加载 APP --> EXT--> BOOT

当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载器都是如此, 因此所有的加载请求都应该传送到启动类加载其中

  1. 类加载器收到类加载的请求! 类加载器收到类加载的请求!
  2. 将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
  3. 启动加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载
  4. 最终找不到该类会报:Class Not Found Exception异常

Bootstrap classLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。

ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。

AppClassLoader:主要负责加载应用程序的主函数类

沙箱安全机制

组成沙箱的基本组件: 

  • 字节码校验器(bytecode verifier)︰确保lava类文件遵循ava语言规范。这样可以帮助Java程序实现内存保护。但并不是所有的类文件都会经过字节码校验,比如核心类。
  • 类装载器(class loader) :其中类装载器在3个方面对Java沙箱起作用
    • 它防止恶意代码去干涉善意的代码; ...它防止恶意代码去干涉善意的代码;
    • 它守护了被信任的类库边界; ...它守护了被信任的类库边界;
    • 它将代码归入保护域,确定了代码可以进行哪些操作。
       

虚拟机为不同的类加载器载入的类提供不同的命名空间,命名空间由一系列唯一的名称组成,每一个被装载的类将有一个名字,这个命名空间是由Java虚拟机为每一个类装载器维护的,它们互相之间甚至不可见。 
类装载器采用的机制是双亲委派模式。
1.从最内层VM自带类加载器开始加载,外层恶意同名类得不到加载从而无法使用; 
2.由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码就自然无法生效。

  • 存取控制器(access controller)︰存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。
  • 安全管理器(security manager)︰是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。
  • ·安全软件包(security package) : java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括: 
    • 安全提供者。
    • 消息摘要
    • 数字签名keytools
    • 加密
    • 鉴别
       

Native:

package Native;

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

        },"my thread neme").start();
    }
//    native: 凡是带了native关键字的,说明java 的作用范围达不到了.会去调用底层C'语言的库
//    凡是带了native关键字的会进入本地方法栈 ---> 调用本地方法接口 JNI
//    JNI作用:扩展JAVA的使用,融合不同的语言为JAVA所用  , 最初像融合C;C++
//    JVM内存中为native专门开辟了一块标记区域: Native Method Stack,开辟的作用是为了登记natice方法
//    在最终执行的时候去加载本地方法库中的方法,通过JNI(本地方法接口)

//    现在调用其他接口: Socket;WebService HTTP
    private native void start0();
}

.

PC寄存器 :

程序计数器: Program Counter Register 
        每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计 

方法区:

Method Area方法区 
方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享区间

静态变量(Static)、常量(Final)、类信息(Class)(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关
 

栈:数据结构

栈:先进后出,后进先出,相当于一个桶,先进的在最底下

栈就是一个特殊的线性表,数据先入后出,类似一个桶,只能对顶端进行操作,数据添加和取出分别叫做入栈和出栈(FIFO:First In First Out)

栈:栈内存,主管程序的运行,生命周期和线程同步,线程结束,栈内存也就释放了,对于栈内存不存在垃圾回收的概念,一旦线程结束,栈也会结束

栈存储:8种基本类型+队形引用+实例方法

栈运行原理:栈帧 ;栈顶,栈底,栈如果满了会StackOverflowError

 栈;堆;方法区的交互关系: 

 三种JVM:

  • Sun公司HotSpot Java Hotspot™ 64-Bit Server VM (build 25.181-b13,mixed mode)
  • BEA JRockit
  • IBM J9VM

堆: 

Heap,一个JVM只有一个堆内存,堆内存大小可以调节

类加载器读取类文件后,一般会将 类,方法,常量,变量,引用类型的真实对象,放入堆中

堆内存还细分三个区域:

  • 新生区(伊甸区)
  • 老年区
  • 永久区

javaGC的回收机制+清理算法_(illusion)的博客-CSDN博客

假设内存满了会报OOM错误 

新生区: 

类的诞生,成长,死亡 的地方

伊甸园:所有的对象都是在伊甸园区new出来的

幸存区:(S0,S1)

如果新生的对象无法在 Eden 区创建(Eden 区无法容纳) 就会触发一次Young GC,此时会将 S0 区与Eden 区的对象一起进行可达性分析,找出活跃的对象

将它复制到 S1 区并且将S0区域和 Eden 区的对象给清空,这样那些不可达的对象进行清除,并且将S0 区 和 S1区交换。

对象在伊甸园放不下将会执行一次轻GC,清理幸存区直到能放下对象,如果幸存区清理不出来,任然放不下对象,则会发生重GC,将清理幸存者区并且将幸存区存活下来的对象移到养老区,

如果清理过后幸存区域任然放不下对象,则重GC会将对象直接放在养老区中,如果养老区也不足以放下该对象,则会产生OOM。

永久区:

区域常驻内存的。用来存放JDK自身携带的Class对象。Interface元数据,存储的是Java运行时的一些环境或言息~,这个区域不存在垃圾回收!关闭VM虚拟就会释放这个区域的内存~ 

jdk1.6之前︰永久代,常量池是在方法区;

jdk1.7:永久代,但是慢慢的退化了,去永久代,常量池在堆中

jdk1.8之后∶无永久代,常量池在元空间

-Xms1024m -Xmx1024m -XX:+PrintGCDetails 调节初始内存总内存参数并打印信息

 

package Native;

public class Demo {
    public static void main(String[] args) {
//        返回虚拟机试图使用的最大内存
        long max = Runtime.getRuntime().maxMemory(); //返回字节 1024*1024
//        返回虚拟机总内存
        long all = Runtime.getRuntime().totalMemory();
        System.out.println("max:"+max+"字节\t"+(max/(double)1024/1024)+"MB");
        System.out.println("ll:"+all+"字节\t"+(all/(double)1024/1024)+"MB");
    }
//    -Xms1024m -Xmx1024m -XX:+PrintGCDetails 调节初始内存/`总内存参数并打印信息

}

//输出
/*
D:\Development_kit\java_file\bin\java.exe -Xms1024m -Xmx1024m -XX:+PrintGCDetails "-javaagent:D:\Development_kit\idea\IntelliJ IDEA 2019.1.4\lib\idea_rt.jar=65133:D:\Development_kit\idea\IntelliJ IDEA 2019.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\Development_kit\java_file\jre\lib\charsets.jar;D:\Development_kit\java_file\jre\lib\deploy.jar;D:\Development_kit\java_file\jre\lib\ext\access-bridge-64.jar;D:\Development_kit\java_file\jre\lib\ext\cldrdata.jar;D:\Development_kit\java_file\jre\lib\ext\dnsns.jar;D:\Development_kit\java_file\jre\lib\ext\jaccess.jar;D:\Development_kit\java_file\jre\lib\ext\jfxrt.jar;D:\Development_kit\java_file\jre\lib\ext\localedata.jar;D:\Development_kit\java_file\jre\lib\ext\nashorn.jar;D:\Development_kit\java_file\jre\lib\ext\sunec.jar;D:\Development_kit\java_file\jre\lib\ext\sunjce_provider.jar;D:\Development_kit\java_file\jre\lib\ext\sunmscapi.jar;D:\Development_kit\java_file\jre\lib\ext\sunpkcs11.jar;D:\Development_kit\java_file\jre\lib\ext\zipfs.jar;D:\Development_kit\java_file\jre\lib\javaws.jar;D:\Development_kit\java_file\jre\lib\jce.jar;D:\Development_kit\java_file\jre\lib\jfr.jar;D:\Development_kit\java_file\jre\lib\jfxswt.jar;D:\Development_kit\java_file\jre\lib\jsse.jar;D:\Development_kit\java_file\jre\lib\management-agent.jar;D:\Development_kit\java_file\jre\lib\plugin.jar;D:\Development_kit\java_file\jre\lib\resources.jar;D:\Development_kit\java_file\jre\lib\rt.jar;D:\Development_kit\idea\com-huixin\comnetwork\target\classes Native.Demo
max:1029177344字节	981.5MB
ll:1029177344字节	981.5MB
Heap
PSYoungGen      total 305664K, used 26214K [0x00000000eab00000, 0x0000000100000000, 0x0000000100000000)
eden space 262144K, 10% used [0x00000000eab00000,0x00000000ec499be8,0x00000000fab00000)
from space 43520K, 0% used [0x00000000fd580000,0x00000000fd580000,0x0000000100000000)
to   space 43520K, 0% used [0x00000000fab00000,0x00000000fab00000,0x00000000fd580000)
ParOldGen       total 699392K, used 0K [0x00000000c0000000, 0x00000000eab00000, 0x00000000eab00000)
object space 699392K, 0% used [0x00000000c0000000,0x00000000c0000000,0x00000000eab00000)
Metaspace       used 3256K, capacity 4496K, committed 4864K, reserved 1056768K
class space    used 353K, capacity 388K, committed 512K, reserved 1048576K

Process finished with exit code 0
*/

package Native;

import java.util.ArrayList;

//-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError 打印oom DUMP
//Xms:设置初始化内存分配大小 1/64
//Xmx:最大分配内存 1/4
//-XX:+PrintGCDetails 打印GC垃圾回收信息
public class Demo2 {
    byte[] array = new byte[1 * 1024 * 1024];

    public static void main(String[] args) {
        ArrayList<Demo2> list = new ArrayList<>();
        int count = 0;
        try {
            while (true) {
                list.add(new Demo2());
                count++;
            }
        } catch (Error e) {
            System.out.println("count:" + count);
            e.printStackTrace();
        }
    }
}

在src下找到.hprof文件双击打开,分析异常信息 

GC:

 

JVM在GC时,并不是对三个区域统一回收,回收的大部分都是新生代(E区) 

  • 新生代
  • 幸存区S区 (from , to)
  • Old区

GC分两种:轻GC(minor gc) 重gc(full gc)

四大算法应该为:复制算法,标记整理算法,标记清除算法,分代收集算法

引用计数法是对象被引用了计数器+1,引用结束-1,计数器为0就会被回收

幸存区:采用复制算法

好处:没有内存碎片

坏处:需要两倍内存空间,另一块S区永远时空的

 

标记清理: 

优点:不需要额外空间

缺点:两次扫描.浪费时间,会产生内存碎片 

 

标记整理: 

优点:没有碎片空间

缺点: 需要依次向前移动

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值