JVM简单概述

1.jvm位置分布

2.JVM的体系结构

 3.类加载器

步骤:

加载-->连接(验证,准备,解析)-->初始化

作用:加载Class文件~

*类是抽象的,对象是具体的 

Class<test> testClass = test.class;
//类是抽象的是模板
Class<? extends Class> aClass = testClass.getClass();
Class<? extends Class> bClass = testClass.getClass();
Class<? extends Class> cClass = testClass.getClass();
System.out.println(aClass);
System.out.println(bClass);
System.out.println(cClass);
//对象的具体的
test aObject = new test();
test bObject = new test();
System.out.println(aObject.hashCode());
System.out.println(bObject.hashCode());

输出:

class java.lang.Class

class java.lang.Class

135721597

142257191

(1)虚拟机加载器

(2)启动类(根)加载器 BootStrap /jre/lib/rt.jar

//先创建对象
test test = new test();
//获取对象的类
Class<? extends com.hyq.sxsb.controller.test> aClass = test.getClass();
//获取该类通过那个加载器加载
ClassLoader classLoader = aClass.getClassLoader();
System.out.println(classLoader);
//再次获取该加载器的父类
ClassLoader classLoaderParent = classLoader.getParent();
System.out.println(classLoaderParent);
//再次获取该加载器的祖父类
ClassLoader classLoaderParentParent = classLoaderParent.getParent();
System.out.println(classLoaderParentParent);

 

输出:

sun.misc.Launcher$AppClassLoader@18b4aac2

sun.misc.Launcher$ExtClassLoader@816f27d

null   这里的启动类加载器java程序获取不到,是使用C编写的

(3)扩展类加载器ExtClassLoader  /jre/lib/ext

//先创建对象
test test = new test();
//获取对象的类
Class<? extends com.hyq.sxsb.controller.test> aClass = test.getClass();
//获取该类通过那个加载器加载
ClassLoader classLoader = aClass.getClassLoader();
System.out.println(classLoader);
//再次获取该加载器的父类
ClassLoader parent = classLoader.getParent();
System.out.println(parent);

输出:

sun.misc.Launcher$AppClassLoader@18b4aac2

sun.misc.Launcher$ExtClassLoader@816f27d

(4)应用程序加载器AppClassLoader

//先创建对象
test test = new test();
//获取对象的类
Class<? extends com.hyq.sxsb.controller.test> aClass = test.getClass();
//获取该类通过那个加载器加载
ClassLoader classLoader = aClass.getClassLoader();
System.out.println(classLoader);

输出:sun.misc.Launcher$AppClassLoader@18b4aac2

4.双亲委派机制

先向上委派:

AppClassLoader-->ExtClassLoader-->BootStrap最终执行

当BootStrap加载器中不能加载这个类时。

然后从BootStrap向下查找;

BootStrap-->ExtClassLoader(也不能)-->AppClassLoader

当AppClassLoader中也不能时就会报ClassNotFoundException异常

5.沙箱安全机制

        Java安全模式的核心就是沙箱(sandbox),Java中将执行程序分为本地代码和远程代码两种。本地代码默认视为可信任的,而远程代码则是不被信任的。

 

最新的安全机制实现,加入了域(Domain)的概念。JDK1.6

(1)组成沙箱的基本组件

        ①字节码校验器:确保java类文件遵循java语言规范,帮助java程序实现内存保护,但不是所有的类文件都会经过字节码校验,比如核心类。

Class test{
  public static void main(String[] args){
      System.out.println() 当这里缺少”;”号时就会编译错误。
    } 
}

 

②类加载器

         其中类加载器在3个方面对java起作用。

        防止恶意代码区干涉善意的代码;           (双亲委派机制)

        守护被信任的类库边界

        将代码归入保护域,确定了代码可以进行哪些操作

6.Native方法区(本地方法区)

大致看一下Thread中的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);
//刚开始线程的的状态为false
    boolean started = false;
    try {
//当执行start0()方法后才会将线程的状态置为true,也就是创建线程
        start0();
        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()方法

private native void start0();

首先需要注意的是Thread是一个类,因此直接写方法体是会报错的。

eg:private void lala();会直接报错

 但是在Thread类中是使用native关键字修饰的方法体就不会报错吗?

         事实上只要是使用native修饰的方法,说明java的作用范围达不到,因此就会去调用底层C语言的库。也就是下图中的本地方法接口(JNI=>java native interface),会进入本地方法栈。

        所以说在使用Native修饰的方法时,会在JVM的本地方法栈中开辟一块区域来登记native方法,再通过JNI(本地方法接口)来加载本地方法库。也就可以访问java中没有的东西,例如C,C++等。也就体现出了java的跨平台性  

  

7.PC寄存器 

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

8.方法区

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

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

        以上,只是逻辑上的定义。在HotSpot中,方法区仅仅只是逻辑上的独立,实际上还是包含在Java堆中,也是就说,方式区在物理上属于Java堆区中的一部分,而永久区(Permanent Generation)就是方法区的实现。

9.栈:数据结构

         先进后出,后进先出(弹夹)

        生命周期和线程同步。一旦线程结束,栈就Over,因此不存在垃圾回收问题。

        程序 = 数据结构+算法

        程序 = 框架+业务逻辑~    ......渣渣

        StackOverflowError栈溢出 

栈中存储8大基本类型,对象引用地址,实例的方法引用

运行原理:栈中的数据都是以栈帧的格式存在的。

 栈 + 堆 + 方法区的调用关系:

 

10.堆和HotSpot

(1)三种JVM:

        Sun公司的HotSpot:Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

        BEA JRockit:最快的JVM适用于财务前端,军工等

        IBM J9:

(2)堆

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

        类加载器读取了类文件后,一般会把什么东西放到栈中?

        类,方法,常量,变量~(实例对象的信息),保存我们所有引用的真实对象:

        堆中还要细分为三个区域:

 GC垃圾回收主要是在伊甸园区和养老区。假设内存满了,出现OOM(堆溢出),堆内存不够!

OutOfMemoryError:java heap space

JDK1.8之后,永久存储区改为(元空间)

        ①新生区(伊甸园区 Eden Space)

        New的对象都是在伊甸园区。

        ②养老区

        ③永久区 Perm

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

        一个启动类,加载了大量的第三方jar包,Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直到内存满,就会出现OOM

(1)JDK1.7之前:
运行时常量池(包含 字符串常量池 )存放在 方法区,此时 hotspot 虚拟机对方法区的实现为永久代。

(2)JDK1.7:

字符串常量池 被从方法区拿到了堆中;
运行时常量池 剩下的东西还在 方法区, 也就是hotspot中的永久代。

(3)JDK1.8:

hotspot移除了 永久代,用 元空间(Metaspace) 取而代之。这时候,
字符串常量池还在堆,
运行时常量池 还在方法区, 只不过方法区的实现从永久代变成元空间(Metaspace)。

默认情况下:分配的总内存是电脑内存的1/4,初始化内存是1/64。

调整jvm分配的内存和初始化内存

在Configurations中的VM options:-Xms1024m -Xmm1024m -XX:+PrintGCDetails。

进行配置-XX:+PrintGCDetails打印信息。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这个名字还中

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值