双亲委派机制:安全
1.类加载器收到类加载的请求
2.将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
3.启动类加载器检查是否能够加载到当前这个类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子类加载器进行加载
4.重复步骤3
Class Not Found~
null: java调不到~ c,c++
Java安全机制的核心就是Java沙箱(sandbox)
沙箱是一个限制程序运行的环境。
沙箱机制就是将Java代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。
沙箱主要限制系统资源访问,系统资源包括CPU,内存,文件系统,网络
在Java中将执行程序分成本地代码和远程代码两种,本地代码默认视为可信任的,远程代码则被看作是不受信任的
对于授信的本地代码,可以访问一切本地资源
当前最新的安全机制实现,则引入了域(domain)的概念。虚拟机会把所有代码加载到不同的系统域和作用域,系统域部分专门负责与关键资源进行交互,而各个应用域部分则通过系统域的部分代理来对各种需要的资源进行访问。虚拟机中不同的受保护域(Protected Domain),对应不一样的权限(Permission)。存在于不同域中的类文件就具有了当前域的全部权限。
组成沙箱的基本组件:
1.字节码校验器:保证Java类文件遵循Java语言规范。并不是所有的类文件都会经过字节码校验,如核心类,java.*
2.类加载器:
虚拟机为不同的类加载器载入的类提供不同的命名空间,命名空间由一系列唯一的名称组成,每一个被加载的类将由一个名字,这个命名空间是由Java虚拟机为每一个类加载器维护的,他们互相之间是不可见的
类加载器采用的是双亲委派模式
从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载而无法使用
由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类
————存取控制器
————安全管理器
————安全软件包
+ 安全提供者
+ 消息摘要
+ 数字签名
+ 加密
+ 鉴别
native:
程序计数器:Program Counter Register
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码,(用来存储指向下一条指令的地址,也就是即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间
方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法的信息都保存在该区域,此区域属于共享空间
静态变量,常量,类信息(构造方法,接口定义),运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关
程序 = 数据结构+算法
栈内存,主管程序的运行,生命周期和线程同步
线程结束,栈内存也就释放,对于栈来说,不存在垃圾回收问题
栈+堆+方法区
Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)
JRockit
J9VM
Heap 一个JVM只有一个堆内存,堆内存的大小是可以调节的
类加载器读取了类文件后,一般会把什么什么东西放到堆中,类,方法,常量,变量~,保存我们所有引用类型的真实对象
堆内存中还要细分为三个区域
轻GC
重GC FullGC
GC垃圾回收,主要是再Eden区和老年代
假设内存满了,OOM(out of memory)
JDK8后,永久存储区改了名字,元空间
永久区
这个区域常驻内存,用来存放JDK自身携带的Class对象,interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存
一个启动类加载了大量的地反方jar包,Tomcat部署了太多的应用,大量动态生成的反射类,不断的被加载,直达内存满,就会出现OOM
元空间:逻辑上存在,物理上不存在
long max = Runtime.getRuntime().maxMemory();//返回虚拟机试图使用的最大内存
long total = Runtime.getRuntime().totalMemory();//返回jvm的初始化总内存
//默认情况下:分配的总内存时电脑内存的1/4,而初始化内存是1/64
//修改 VM options
//-Xms1024m -Xmx1024m -XX:+PrintGCDetails
//-Xms 设置初始化内存分配大小
//-Xmx 设置最大分配内存
//-XX:+PrintGCDetails //打印GC垃圾回收信息
//-XX:+HeapDumpOnOutOfMemoryError //OOM dump
OOM
在一个项目中,突然出现了OOM故障,那么该如何排除,研究为什么出错
MAT,Jprofiler
JVM在进行GC时,并不是对这三个区域统一回收,大部分时候,回收都是新生代
GC两种类:轻GC(普通的GC),重GC(全局GC)
从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC
Major GC 是清理永久代。Full GC 是清理整个堆空间—包括年轻代和永久代。
好处:没有内存碎片
坏处:浪费内存空间~:多了一半空间永远是空to
复制算法最佳使用情景:对象存活度低
缺点:两次扫描,严重浪费时间,会产生内存碎片
优点:不需要额外的空间
再优化:
答案:没有最好的算法,只有最合适的算法——>GC:分代收集算法
年轻代:
老年代:
CMS:老年代收集器,以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”实现
过程:
优点:
缺点:
CMS出现FullGC的原因
初始标记-->并发标记---->最终标记---->筛选回收(根据用户期望的GC停顿时间回收)
特点:
G1变化较大的是它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留了新生代和来年代的概念,但新生代和老年代不再是物理隔离的了它们都是一部分Region(不需要连续)的集合
java内存模型
Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样底层细节。此处的变量与Java编程时所说的变量不一样,指包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,后者是线程私有的,不会被共享。
Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存(可以与前面将的处理器的高速缓存类比),线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程之间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成,
作用:缓存一致性协议,用于定义数据读写的规则
JMM定义了线程工作内存和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存
线程工作内存:每个线程都有自己的工作区域,是从主内存拷贝的
### 可见性问题,指令重排