Java学习笔记11

沙箱安全机制

Java安全模型的核心就是Java沙箱,沙箱是一个限制程序运行的环境,沙箱机制就是将Java代码限制在JVM(虚拟机)特定的运行范围中,严格限制代码对本地系统资源的访问,保证对代码的有效隔离,防止对本地系统造成破坏。沙箱主要限制系统资源访问;系统资源:cpu、内存、文件系统、网络;不同级别的沙箱对这些资源访问的限制可以不一样
所有java程序运行都可以指定沙箱,定制安全策略
在java程序中,将运行代码分为本地代码和远程代码两种,本地代码默认可信任,远程代码默认不信任,授信的本地代码可访问本地一切资源,非授信代码早期依赖沙箱(sandbox)机制,JDK1.0安全模型
Java学习笔记11_第1张图片
严格的安全机制也限制了程序的功能性扩展,如用户希望远程代码想要访问本地文件时,无法实现,在Java1.1版本中对安全机制做了改进,增加了安全策略,允许用户指定远程代码对本地资源的访问,JDK1.1安全模型
Java学习笔记11_第2张图片
在JDK1.2中增加了代码签名,不管是本地代码还是远程代码,都会按照用户策略的设定,由类加载器加载到虚拟机中权限不同的运行空间,实现差异化的代码执行权限控制。JDK1.2安全模型
Java学习笔记11_第3张图片
JDK1.6引入了域(Domain)的概念,虚拟机会把所有的代码加载到不同的系统域和应用域,系统域部分专门与关键资源进行交互,而各个应用域部分则通过系统域的部分代理来对各种需要的资源进行访问,虚拟机中不同的受保护域对应着不同的权限,存在于不同域中的类文件,也就有了当前域的所有权限。JDK1.6安全模型
Java学习笔记11_第4张图片

组成沙箱的基本组件

  • 字节码校验器:确保Java类文件遵循Java语言规范,这样可以帮助Java程序实现内存保护,但不是所有的Java类文件都会经过字节码校验,如:核心类
  • 类加载器:其中类加载器在3个方面对Java沙箱起作用
    1. 防止恶意代码干涉善意代码
    2. 守护了被信任的类库边界
    3. 将代码归入保护域,确定代码可以进行哪些操作
    虚拟机为不同的类加载器载如的类提供了不同的命名空间,命名空间由一系列唯一的名称组成,每一个被装载的类将有一个名字,这个命名空间是由java虚拟机为类加载器维护的,它们互相之间甚至不可见。
    类加载器采用的是双亲委派机制
  1. 从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载从而无法访问
  2. 由于通过包严格区分访问域,外层恶意类通过内置代码也无法获得权限访问到内层类,破坏代码自然无法生效
  • 存取控制器(access controller):存取控制器可以控制核心API对操作系统的存取权限,这个控制是策略设定的,可以由用户指定
  • 安全管理器(Security manager):是核心API和操作系统之间的主要接口,实现权限控制,比存取控制器优先级高
  • 安全软件包:java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:安全提供者、消息摘要、数字签名、加密、鉴别

Native

多线程start()方法源码

public synchronized void start() {
   if (threadStatus != 0)
        throw new IllegalThreadStateException();

      group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
                    }
    }
}

private native void start0();

凡是带了native关键字的,说明java的作用范围达不到,去调用底层C语言的库
JNI:Java本地方法接口(Java Native Interface)
凡是带了native关键字的方法会进入本地方法栈,其他的进入java栈
Native Interface本地接口
本地接口的作用就是融合不同的编程语言为java语言所用,它的初衷是融合C/C++程序,java诞生时,C/C++大行其道,想要立足必须要调用C/C++程序,于是在内存中专门开辟了一块区域处理标记为native的代码,它的具体做法是在Native Method Stack中登记native方法,在执行引擎(Excution Engine)执行的时候加载Native Libraies
目前

该方法使用的越来越少,除非是与硬件有关的应用,比如通过java程序驱动打印机或者java系统管理生产设备,在企业级应用中已经比较少见了,因为现在异构领域通讯发达,可以使用Socket通信,也可以使用Web Service等等

PC寄存器

程序计数器:Program Counter Register
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向一条指令的地址,即将要执行的指令代码)

方法区(Method Area)

方法区被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单的说所有定义的方法信息都保存在该区域,此区域属于共享空间
静态变量(static)、常量(final)、类信息(构造方法、接口定义)(Class)、运行时的常量池存在方法区中,但是实例变量存在堆内存中

栈:数据结构
程序=数据结构+算法
栈:先进后出、后进先出
队列:先进先出
栈:栈内存,主管程序运行,生命周期和线程同步
线程结束,栈内存也就释放,对栈来说,不存在垃圾回收问题
栈存放:8大基本类型、对象引用和实例方法
Java学习笔记11_第5张图片
栈运行原理:栈帧
栈+堆+方法区:交互关系
(问题:JVM在内存中实例化的过程分析)
三种JVM
sun公司:HotSpot
BEA JRockit
IBM J9VM
一般学习的都是HotSpot

Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的
类加载器读取类文件后,会把什么放入堆中?类、方法、常量、变量,保存我们所有引用类型的真实对象
堆内存还要细分为3个区域

  • 新生区
  • 养老区
  • 永久区
    Java学习笔记11_第6张图片
    JDK8以后将永久区改为元空间
    GC垃圾回收主要在伊甸园和养老区
    OOM:堆内存不够(OutOfMemoryError)
    新生区:
    类:诞生和成长的地方,甚至是死亡
    伊甸园:所有对象都是在伊甸园区new出来的
    幸存者区(0,1)
    永久区:这个区域是常驻内存的,用于存放jdk自身携带的Class对象。Interface元数据,存储的是java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭java虚拟机就会释放这个区域的内存
    一个启动类加载了大量的第三方jar包,tomcat部署了太多的应用,大量动态生成的反射类,不断被加载直到内存满,就会出现OOM
    jdk1.6之前:存在永久区,常量池在方法区中
    jdk1.7:存在永久区,但慢慢退化了,(去永久区),常量池在堆中
    jdk1.8之后:无永久区,常量池在元空间
package jvm;

public class Test01 {
    public static void main(String[] args) {
        //返回虚拟机试图使用的最大内存
        long max=Runtime.getRuntime().maxMemory();
        //返回jvm初始化的总内存
        long initTotal=Runtime.getRuntime().totalMemory();
        System.out.println("最大内存="+(double)max/1024/1024);
        System.out.println("初始化总内存="+(double)initTotal/1024/1024);
    }
}

内存分析(出现错误)

在一个项目中出现OOM(OutOfMemoryError)错误,如何排错?

  • 能看到代码第几行出错:内存快照分析工具:MAT,jprofiler
  • Debug:一行行分析代码
    MAT、jprofiler的作用
  • 分析Dump内存文件,快速定位内存泄漏
  • 获得堆中的数据
  • 获得大对象等等
jprofiler使用步骤
  1. 安装jprofiler
  2. 发生错误的代码
package jvm;

import java.util.ArrayList;

public class Test02 {
    byte[] test = new byte[1024 * 1024];//1m

    //会发生OOM错误的代码
    public static void main(String[] args) {
        ArrayList<Test02> arrayList = new ArrayList<>();
        int count = 0;
        try {
            while (true) {
                arrayList.add(new Test02());
                count++;

            }
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
            System.out.println(count);

        }
    }
}

Java学习笔记11_第7张图片3. 进行相关配置
Java学习笔记11_第8张图片
在这里插入图片描述
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
4. 再次运行代码
Java学习笔记11_第9张图片
在当前工程的文件夹中找到相应文件并打开
Java学习笔记11_第10张图片
点击大对象,查看是否存在比较大的对象
Java学习笔记11_第11张图片
也可以点击线程查看相关信息
Java学习笔记11_第12张图片
vm options使用的相关命令

  • (-Xms设置初始化内存分配大小)
  • (-Xmx设置最大分配内存)
  • (-XX:+PrintGCDetails):打印GC垃圾回收信息
  • (-XX:+HeapDumpOnOutOfMemoryError):oom dump文件

你可能感兴趣的:(笔记)