1.JVM
是一个运行环境,和其他计算机软件没有什么区别。
2.体系结构:运行时数据区
1.栈里面不会有垃圾。
2.调优百分之九九是在堆和方法区里面。百分之九九是在堆里。
3.类加载器
作用:–> 加载class文件 --> 实例化
双亲委派机制
1.类加载器收到加载的委托,会将这个请求委托给父类,一直向上,直到根类加载器
2.启动类(根)加载器检查是否能够加载这个类,能就使用当前加载器,否则抛出异常,通知子类加载器加载
3.null 加载不到,C,C++.
4.沙箱安全机制
沙箱是一个限制程序运行的环境,就是将java代码限定在虚拟机特定的运行环境中,并且严格限定代码对本地资源的访问,来保证对代码的隔离,防止对本地系统造成破坏。
沙箱主要限制对系统资源的访问。
系统资源包括:
CPU、内存、文件系统、网络等。
最新的安全机制引入了域概念,虚拟机会把代码加载到不同的系统域和应用域。
5.Native
凡是带了native关键字的,说明java作用范围达不到了,回去调用底层c语言的库
会进入本地方法栈
调用本地方法接口JNI
JNI作用:扩展java的使用,融合不同的编程语言为java所用,最初融合c,c++;
现在调用其他语言接口:socket,webservice,http等
6.方法区
被所有线程共享,所有字段和方法字节码,以及一些特殊方法,入构造函数,接口代码也在此定义,此区域属于共享区域。
静态变量,常量,类信息,运行时常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。
static,final,class,常量池。
7.栈
程序 = 数据结构 + 算法;
程序 = 框架 + 业务逻辑;
栈:先进后出,后进先出,(像桶这样的,进去压在底部出不来)
队列:先进先出(FIFO: First Input First Output)
如下所示栈溢出:递归
main()先执行最后结束;------就是样子的;
程序正在执行的方法一定在栈的顶部;
栈满了:StackOverflowError;递归
栈;栈内存;主管程序的运行,生命周期和线程同步;
线程结束;栈内存也就释放,程序结束,对于栈来说不存在垃圾回收问题。
线程结束;栈就over;
栈:八大基本类型 + 对象引用 + 实例方法;
栈–堆--方法区(里面有常量池) : 交互关系;
对象实例化的过程:
1、JVM会根据指定路径读取Cat.class文件,并加载进内存,有父类(如:Animal)的情况下,会先加载的.class文件(即Animal.class)。
2、在堆内存开辟空间,分配地址
3、在对象空间中,对对象的属性进行默认初始化。
3.1调用对应构造函数进行初始化,这个栗子中,调用的就是,无参构造函数
3.2在构造函数中,第一行会到调用父类中构造函数进行初始化
3.3父类初始化完毕后,再对子类属性进行显示初始化
4、再进行子类构造函数的特定初始化
5、初始化完毕后,将地址赋值给引用变量。
8.堆
三种JVM
sun:HotSpot;
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)
IBM:J9Vm;
BEA:Jrockit;
堆:heap,一个JVM只有一个;堆内存大小:是可以调节的;
堆内存分三个区域:
新生区;
养老区:
永久区:
GC垃圾回收机制主要在养老区和伊甸园区;
内存满了,报错,OOM(OutOfMemoryRrror),堆内存不够! 字符串无限加长;
9.内存调优
1.新生区:
类,诞生和成长的地方,甚至死亡;
伊甸园区:所有对象都是在伊甸园区new出来的;满了,垃圾回收;a还在使用,幸存下来,进入幸存者0区
幸存者0区:
幸存者1区:
2.养老区:
3.永久区:
这个区域是常驻内存的,用来存放JDK自身携带的class,interface元数据,
存储的是java运行时的环境,
这个区域不存在垃圾回收!关闭jvm虚拟机就会释放这个区域。
一个启动类,加载大量的jar包,tomcat部署太多的应用,大量生成动态反射代码,不断被加载,会出现OOM。
修改内存OOM错误,
1.先修改内存:尝试扩大堆内存;
2.分析内存,看什么地方出错;