一组连续空间,存储多个相同类型的值
https://blog.csdn.net/romantic_jie/article/details/91355437
略(后面详细介绍)
所有的父类,如果没有显示继承,那么隐式存在
Java集合类存放在java.util包中,是一个用来存放对象的容器。
注意:
HashTable: KV都不允许为null,线程安全,效率低
HashMap(和HashTable相反):哈希表(Node[]
)、链表(Node next
解决哈希冲突)、红黑树(TreeNode
解决链表过长,效率过低问题)
ConcurrentHashMap:1.7版本之前 哈希表 + 链表 + 分段锁 1.8以后 哈希表 + 链表 + 红黑树
CAS(Compare And Set): 类似于乐观锁
ArrayList:底层数组实现,查询快,增删慢。线程不安全,效率高。
Vector:底层数组实现,查询快,增删慢。线程安全,效率低。
LinkedList:底层链表实现,查询慢,增删快。
list和set区别?
* List:有序,可重复
* Set:无序,不可重复
* 如何保证元素唯一:HashSet存储元素底层依靠两个方法hashcode() equals()
* 执行步骤:
* hashcode先执行,会判断存储的元素哈希值是否一样
* 相同:执行equals判断内容
* 相同:不存
* 不同:存
* 不同:存储
注:如果存储自定义对象,请在类中覆盖hashcode和equals。
Collection:List可重复,Set集合不可重复。光棍
Map:键不可重复,值可重复。
略
网络中传输的数据均为字节,保证数据能够进行网络传输
transient
BIO:同步阻塞IO
NIO:同步非阻塞IO Netty
AIO:异步非阻塞IO
网络编程
阻塞和非阻塞体现在线程利用率
阻塞:先有线程再有完整的IO操作,线程服务于一次完整的IO
非阻塞:关注的事件,事件发生后进行事件操作,线程利用率更高
同步和异步
request.getInputStream
进程:正在运行的程序。
cpu:单cpu一个时间点只能执行一个进程。
- 为什么我们感觉多个进程是同时执行的?
- 是因为cpu在做着程序之间的高效切换,让我们感觉是同时在执行。
线程:在一个进程中,包含多个任务,而每一个任务就是一个线程。
多线程:每一个进程想要执行必须抢到cpu才能执行,如果一个进程中线程的数量比较多,那么该进程抢到的概率就更大,但是不保证一定抢到,因为线程的执行是随机性的。
并发:在一段时间内多个线程切换执行。
并行:在一个时间点多个线程同时执行。
多线程并发环境中操作临界资源,保证线程的安全,对临界资源加锁
将需要执行的任务交给线程池,线程池会分配线程去执行该任务,任务执行结束线程不会死亡,而是回到线程池中处于空闲状态,等待下一个任务。
通过.class文件获取的对象,使用该对象中的构造方法,实例变量,实例方法。
单例(静态内部类)
保证内存中只有一个对象
工厂(好处 : 解耦合)
主要解决的是对象创建的问题,工厂的职责在于创建一个对象
代理(静态代理、动态代理)
客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。
适配器
将一个类的接口转成客户期望的另外一个接口,使得原本由于接口不匹配而不能一起工作的那些类可以一起工作。
责任链
当系统需要嵌入多个独立功能模块时,可以使用责任链设计模式
责任
:主要负责实际功能实现。链
:用于协调责任调度,记录调度状态。https://blog.csdn.net/qq_38950316/article/details/81087809
Java 语法基础:HashMap结构,锁-分类,JVM GC策略,自定线程池参数含义,JVM内存分析指令-jmap,jstack,jstats, Java类加载策略,网络编程 阻塞IO和NIO – 高级Java开发工程师
概念:一款轻量级的javaEE解决方案,众多优秀设计模式的组合
控制:给属性赋值的权利
反转:把给属性赋值的权利由代码反转到了配置文件中
控制反转,有容器工厂负责对象的创建销毁(生命周期)
或者@Bean
当一个类型需要另一个类型时,可以把另一个类型作为该类型的属性,通过对应的注入方式进行赋值
set注入
、构造注入
和自动注入(ByType @Autowired | ByName @Resource)
将代码中其它功能(事务、日志、性能等)剥离出来形成独立的功能方法或者功能类,如果使用到这些功能时,通过动态代理方式生成代理类,增强普通类功能
@Before
@After
和@Around
等exeuction(* com.baizhi.*.*(..))
解决事务嵌套问题
1.PROPAGATION(propagation)_REQUIRED – 如果存在当前事务则用当前事务;如果不存在当前事务,就新建一个事务。这是最常见的选择。
2.PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。开启一个新事务,新事务执行完毕后,唤醒之前挂起的事务,继续执行。如果不存在当前事务,则新建一个事务
5.PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
脏读: 一个事务读取了另一个事务尚未提交的数据
isolation=“READ_COMMITTED” 解决脏读问题
不可重复读:多次读取到的数据不一致
isolation=“REPEATABLE(repeatable)_READ” 解决不可重复读问题
幻影读:多次统计的结果不一致
isolation=“SERIALIZABLE(serializable)” 解决幻影读问题
安全:SERIALIZABLE>REPEATABLE_READ>READ_COMMITTED
性能:READ_COMMITTED>REPEATABLE_READ>SERIALIZABLE
isolation=“DEFAULT” 根据数据库默认隔离属性定
Oracle数据库隔离属性级别: READ_COMMITTED
Mysql数据库隔离属性级别: REPEATABLE_READ
作用:解决事务嵌套问题
propagation=“REQUIRED” 默认值 当外部有事务则融入到外部事务中,如果外部没有事务,则开启新的事务 (增删改)
propagation=“SUPPORTS” 当外部有事务则融入到外部事务中,如果外部没有事务,也不开启事务(查)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I5L3l4to-1586439809864)(D:\java168\java168\三阶段资料\框架阶段\Spring\Spring-Day4\图片\传播属性补充.png)]
read-only=false 默认值 (增删改)
read-only=true 查询(提高查询效率)
作用:决定释放锁标记的等待时长
time-out=-1 由数据库来决定
作用:哪些异常进行提交?哪些异常进行回滚?
默认对于未检查异常进行回滚操作,对已检查异常进行提交操作
rollback-for 指定哪些异常进行回滚操作
no-rollback-for 指定哪些异常进行提交操作
总结:实战开发中事务属性的应用
增删改: isolation=“default” propagation=“REQUIRED” read-only=“false” time-out="-1"
异常属性默认 (全部用默认)
查询: isolation=“default” propagation=“SUPPORTS” read-only=“true” time-out="-1"
异常属性默认
对象什么时候被创建?
对象只创建一次时(scope=“singleton”):工厂被创建则对象被创建 饿汉式
对象每次创建新的(scope=“prototype”): 该对象使用时被创建 懒汉式
对象什么时候被销毁?
工厂关闭时,对象被销毁 但是还与垃圾回收机制有关
init-method 指定对象创建调用的初始化方法
destory-method 指定对象销毁调用的销毁方法
作用:替换配置文件中,复杂的配置
开发步骤:
1.把注解放置对应的位置上
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6e0pLf5-1586439809865)(C:\Users\战神\AppData\Roaming\Typora\typora-user-images\1586434941807.png)]
2.告知Spring框架在哪一个包中使用了注解
<context:component-scan base-package="com.baizhi.entity">/context:component-scan
常用注解:
@Component
放置位置:类上
作用:创建简单对象
注意:默认提供ID 类名首字母小写
@Service
位置:Service实现类上
作用:创建Service实现类对象
@Autowired
位置:属性上
作用:为属性做自动注入
前提:在Spring工厂中必须有为该属性注入的值
@Transactional
位置:方法 类
作用:为方法添加对应的事务
前提: 必须激活该注解
!--激活@Transactional注解-- <tx:annotation-driven transaction
manager="transactionManager">/tx:annotation-driven
@Controller
位置:类
作用:自动创建Action对象
@Scope
位置:类
作用:决定对象创建的次数
singleton 只创建一次
prototype 每次创建新的
开发步䠫:
1.建表
2.写实体
3.定义DAO接口
4.Mapper文件实现DAO接口
5.Spring配置文件中配置mybatis相关的内容
6.定义Service接口
7.实现Service接口
i.@Service 自动创建Service实现类对象
ii.@Autowired 自动为DAO属性做注入
8.配置额外功能事务
i.@Transactional 给对应的方法添加事务
ii.在Spring配置文件中进行激活
9.开发Action
i.@Controller 创建Action对象
ii.@Scope 决定创建对象的次数
iii.@Autowired 自动注入Service实现类对象
10.struts.xml中配置
11.告知Spring框架在那一个包下使用了注解
概念:是一款控制层的框架,解决MVC分层开发中控制层的问题
好处:
SpringMVC框架是Spring全家桶体系的组成部分,与Spring体系做到无缝衔接
SpringMVC无论从开发效率还是运行效率都比Struts2高
作用
1.接收数据
2.调用业务
3.跳转页面
作用:
1.指定后台Action的访问路径
2.指定该方法被访问的请求方式
位置:
类 相当于struts2中的namespace
方法 相当于struts2中的name
RequestMethod.GET 该方法只能被GET方式访问
RequestMethod.POST 该方法只能被POST方式访问
method ={RequestMethod.POST,RequestMethod.GET} 既可以被POST方式又可以被GET方式访问 (默认)
i.解决传入的键与形参名不一致的问题
ii.可以设置接收数据的默认值
@DateTimeFormat(pattern = “yyyy-MM-dd”) 自定义接收数据类型
Forward跳转(请求转发):一次请求 地址栏不变 可以使用Request作用域传递数据
Redirect跳转(重定向): 两次请求 地址栏发生改变 不可以使用Request作用域传递数据
使用Model和ModelMap替换Request作用域
作用: 与视图层解耦合
作用:减少控制器中代码的冗余
开发步䠫:
1.implements HandlerInterceptor 接口
2.在SpringMVC的配置文件中配置
模型
视图
控制
接受客户端请求 —> 业务处理 —> 返回客户端
1、 用户发送请求至前端控制器DispatcherServlet。
2、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、 Controller执行完成返回ModelAndView。
7、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、 ViewReslover解析后返回具体View。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户。
简化Spring应用的初始搭建以及开发过程,内嵌WEB容器,提供自动配置,程序员只需要关注业务功能开发而不是Bean的配置;
springboot(微框架) = springmvc(控制器) + spring(项目管理)
创建独立的Spring应用程序
嵌入的Tomcat,无需部署WAR文件
简化Maven配置
自动配置Spring
没有XML配置
软件设计风格
使用请求方式说明对资源操作;
GET http://localhost:8080/user/1 # 获取用户id=1
DELETE http://localhost:8080/user/1 # 删除用户id=1
POST【更新】
PUT【新增】
Spring4.0后提供配置注解
根据导入的依赖自动完成配置
web
---> DispatcherServlet
---> CharacterEncodingFitler
springboot是对原有项目中spring框架和springmvc的进一步封装,因此在springboot中同样支持spring框架中AOP切面编程,不过在springboot中为了快速开发仅仅提供了注解方式的切面编程.
重点注解
参考: https://www.cnblogs.com/tanwei81/p/6814022.html
优秀的持久层框架,对数据库进行访问和操作。
替换JDBC技术 ----- 定制化SQL(动态SQL),高级映射关系,支持缓存。
mybtis中代码的书写
JDBC —> 接口 Connection PreparedStatement ResultSet DrvierManager
Resources、SqlSessionFactory、SqlSession
Resources : 读取MyBatis的核心配置文件。
SqlSession : 类似连接Connection
将mapper.xml文件 转换成对应的DAO实现类(DAOImpl)
内部封装了Connection对象 使用SqlSession去访问数据库
sqlSession.commit(); sqlSession.rollback();
SqlSessionFactory :SqlSession的工厂 用来创建SqlSession对象。
应用优化策略,提高访问效率,大大减轻数据库的访问负载
一级缓存:SqlSession,缓存依赖于会话
二级缓存:NameSpace级别,所有的查询语句都会进行缓存,在调用增删改方法时所有的查询缓存会失效;
—> JVM
—> 保存第三方存储系统(内存 分布式)
基于Redis管理MyBatis二级缓存 构建分布式缓存服务;
注意:
好处 : 减少数据库的通信次数,提高效率。
不好 : 缓存 ---> 大量占用内存。 空间 换 时间
不安全的,数据的不一致。
1. 关注 缓存的命中率
Cache Hit Ratio [com.baizhi.dao.DepDAO]: 0.75
如果命中过低不建议使用缓存
2. 脏数据 --- 缓存中的数据和数据库中的数据不一致
执行Commit操作会自动清空缓存数据
ORM思想:实体属性,表中的列名 一一对应。
mapper文件中取值的语法: #{…} . ${} 存在SQL注入的风险 不建议使用
DQL (Data Query Language) : 数据查询语言
DDL(创建表) : 数据的定义语言
DML(增删改) : 数据修改语言
case...when..
create、alter、desc、drop、truncate
脏读(A事务读取到了B事务未提交的数据)
不重复读(A事务内多次读取同一条数据,结果不一致)
幻影读(A事务多次读取结果的条数不一致)
等级:由低到高
效率:由高到低
参考Spring
主键索引:约束primary key
,建议在查表时使用主键,因为这样做的话可以使用到主键索引
唯一索引:约束unique
复合索引:对多个字段创建一个索引;
普通索引:单字段创建一个索引
create index 索引名 on 表名(字段1,字段2,字段3....)
Hash
BTree
https://blog.csdn.net/iteye_19269/article/details/82678056
简化SQL语句
create view 视图名 select ...
Myisam 不支持事务和外键 适用于只读查询
Innodb 支持事务和外键 适用于读写查询
https://www.cnblogs.com/wangsen/p/10863405.html
https://www.cnblogs.com/klb561/p/10344364.html
https://www.runoob.com/w3cnote/mysql-stored-procedure.html
尽可能利用索引查询
尽量避免三张表以上的连接操作,可以使用子查询代替表连接
查询利用条件查询,避免全表的扫表
避免使用 *
,建议使用字段方式
总结:上网资料 + 理解
一、二、三范式
https://www.cnblogs.com/wenxiaofei/p/9853682.html
解决现有MVC开发思想中 控制器的问题。 —> 替换Servlet技术
框架: framewrok 软件开发中的半成品!!!
解决了软件开发过程中的通用问题(代码冗余或设计的不合理),从而提高了开发效率。
接收参数 冗余、类型转换、编码的处理
流程跳转 硬编码 ---> 跳转路径写死在java文件中
Servlet(单例)
不能定义成员变量
Struts2(多例)
每一次请求访问都会创建一个全新的对象(构造方法被多次调用),可以定义成员变量
Servlet 中跳转 请求转发 / 重定向
forward: 一次请求使用request作用域传递数据,地址栏不发生改变。
redirect : 两次请求不能使用request作用域传递数据,地址栏发生改变。
Struts2 中依然保持这两种跳转方式,由原有的代码书写变成的Struts.xml的配置
四个: forward redirect
Action ---> jsp dispatcher(默认值) redirect
Action ---> Action chain redirectAction
目的: 减少Action的数量,将多个Action中的方法抽取的一个Action中书写。
注意: 尽量将一类的Action书写在一起 UserAction ProductAction
作用: 可以将多个action中的冗余代码,抽取到拦截器中定义, 实现代码的复用。
拦截器可以拦截请求 , 也可以拦截响应。
开发步䠫:
拦截器的开发步骤:
1. 开发拦截器(代码) 实现接口 interceptor
intercept 方法 ----> ai.invoke(); 放行 / return “String” 错误跳转的页面。
2. 配置 struts.xml
2.1 声明拦截器
2.2 定义拦截器栈
2.3 完成拦截器栈的使用配置
a. 使用默认的拦截器配置 package中所有的action都拦截
b. 在action标签中使用拦截器栈
只针对Action中某一类特定的方法进行拦截。
继承 : MethodFilterInterceptor
接收数据
替换request作用域
从struts.xml中读取数据
向struts.xml中传输数据 ${ 成员变量名称 }
基于内存KV存储的非关系数据库
传统的关系型数据库只能存储结构化数据,对于非结构化的数据支持不够完善,nosql这个技术门类的出现,更好的解决了这些问题,它 告诉了世界不仅仅是sql。
Key:String
Value:String、List、Set、Sorted Set、Hash
RDB(内存快照)
在某个时刻,将Redis内存中全量数据逆向生产一个快照文件dump.rdb
,在Redis Server恢复运行时通过加载二进制快照文件实现内存数据的恢复;
问题:丢失未保存在快照中的内存数据
60s 10000
300s 10
900s 1
AOF(追加日志)
写操作日志文件,通过方式将用户的写操作指令记录到appendonly.aof
,在Redis Server恢复运行时通过再次执行日志文件中写操作命令实现内存数据的恢复;
默认 1s 记录一次
1写操作 记录一次
写入时机由系统决定
aof日志文件重写:不断追加写操作指令导致日志文件越来越大
自动触发:
auto-aof-rewrite-percentage 100
或者auto-aof-rewrite-min-size 64mb
手动触发
bgrewrite
基于Lucene全文检索引擎
DSL风格
请求方式 + 资源 + RequetBody (请求参数)
IK分词
es 默认采用的分页方式是 from+ size 的形式,在深度分页的情况下,这种使用方式效率是非常低的,比如from = 5000, size=10, es 需要在各个分片上匹配排序并得到5000*10条有效数据,然后在结果集中取最后10条;
https://blog.csdn.net/u011228889/article/details/79760167
反向索引
通过运行创建索引,在查询时根据匹配索引寻找数据的过程;类似于查字典过程(索引:拼音表或者偏旁部首表 数据:中文汉字)
我爱北京天安门 —> 我 | 爱 | 北京 | 天安门 —> 索引
北京 --> 北京 —> 匹配索引 —> 我爱北京天安门
https://blog.csdn.net/qq_31871785/article/details/86149698
略
数据库连接技术
线程局部变量
保证在同一个线程中能够获取到相同的变量对象;
Thread#ThreadLocalMap#getOrSet
运行在服务器端JAVA程序
Java动态网页技术(不重要 | 淘汰)
9大内置对象:request、session、application、page、pageContext、exception、config、response、out
略
JDK7 数组+链表
JDK8 数组+链表+红黑树
- 当数组中某一个链表长度>=8,数组的长度>=64时,会将此链表转换为红黑树的存储方式。
capacity:容量
factor:因子
HashMap是Map接口的实现类,键值对存储(基于哈希表的映射:根据指定的键,可以获取对应 的值),并允许null作为键和值,线程不安全,即方法为非同步(Lock、Synchronized)方法
Lock:显示加锁,加完之后必须手动的释放(unlock)
Synchronized:自动释放
Java.util.concurrent.locks(juc):Java并发包
用这两种基本结构进行构建。
数组的特点(连续的一组空间):寻址容易,插入和删除难,空间浪费;
而链表的特点(空间不连续):寻址困难,插入和删除容易,节省空间。
储方式。
素代表的是每一个链表的头结点。结构如下:
Public class TESThASHmAP{
public static void main(String[] args){
//头插法
Node head;
Node n1 = new Node(data:"aa");
head =n1;
Node n0 = new Node(data:"00");
no.next = n1;
head = n0;
Node n2 = new Node(data:"bb");
n1.next = n2;
n2.next = new Node(data:"cc");
//尾插法
//先遍历for循环,获取最后一个
//遍历链表
for(Node n = head;n!=null;n=n.next){
Syatem.out.println(n.getData());
}
//数组+链表
Node[] ns = new Node[3];
ns[0] = new Node(data:"aa");
ns[1] = head; //链表
}
Class Node{
//数据区
Private String data;
//地址区
Node next;
Node before;
Public Node(String data){
this.data = data;
}
Public String getData(){
return this.data;
}
}
}
Jdk保护集合(线程安全)的策略
负载因子过大,会导致链表过长,耗时(遍历),性能降低
负载因子过小,会造成空间浪费
提高效率
相同的对象返回相同的Hash值,不同的对象返回不同的Hash值
尽可能不破坏离散度
减少下标冲突的可能性(提高离散度)
无序的
存储的下标取决于元素的Hash值&数组的长度
HashSet底层本质为HashMap
运行在操作系统之上的
橙色:线程共享
灰色:线程独有
.class文件通过类加载加载到Java虚拟机中
Java虚拟机是一大块内存,内存分为栈空间、堆空间、本地方法区、程序计数器
堆空间:存储对象的
栈空间:局部变量
程序计数器(指示器)
一块小的内存空间,告知程序下一步做什么的指令,每个线程拥有一个独立的程序计数器
Java虚拟机栈(先进后出)
每一个方法被调用都会分配一个栈帧,一个栈帧里面包含局部变量表、调用链接、方法的出口
本地方法栈(Native)
Java堆(GC堆–垃圾回收器)
方法区:存储虚拟机加载的信息、常量、静态变量
类加载机制
虚拟机把描述类的数据从.class文件加载到内存中,并对数据进行校 验、转换解析和初始 化,最终形成可以被虚拟机直接使用的Java类型
类加载过程
将class文件字节码内容加载到内存中;并将这些内容转换成方法区中的运行时数据结构;
在内存中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口
确保class 文件中的字节内容符合jvm规范,并且不会危害jvm自身的安全。
正式为类变量(静态变量)分配内存空间,并为静态变量初始化(赋默认 值),静态变量的内存在方法区中分配。
虚拟机常量池内的符号引用替换为直接引用的过程。
- 比如String s =“aaa”,转化为 s的地址指向“aaa”的地址
根据程序员通过程序制定的主观计划完成静态变量等资源的初始化。 在这个过程会完成静态变量的赋值和静态代码块中的语句。
用于实现类加载过程中加载阶段,负责将class文件字节码内容加载到内 存中;并将这些内容转换成方法区中的运行时数据结构,在内存中生成一个代表这个类的 java.lang.Class对象, 作为方法区类数据的访问入口。
虚拟机自带的类加载
C++语言实现,负责加载 %Java_home%/jre/lib/rt.jar 中的内容
扩展类加载器:
Java语言实现,负责加载 %Java_home%/jre/lib/ext/*.jar中的内容
应用程序类加载器:
也可以称为系统类加载器,它负责加载用户类路径classPath的所有类。
如果应用程序中没有定义过自己的类加载器,一般情况默认使用应用程序类加载。
用户自定义的类加载器
继承java.lang.ClassLoader
应用程序类加载器拿到一个任务,逐级委派给父加载器,当父类加载反馈自己无法完成这个加载请求**(它的搜索范围中没有找到所需要的类)**的时候,子类才会尝试自己加载。
好处
Java随着它的类加载一起具备了一种带有优先级的层次关系
加载位于rt.jar中的java.lang.Object类,无论哪一个类加载加载这个类,最终都委托给最顶级的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。
如何保证在生成类对象的时候它的线程安全?
Synchronized(加锁)
堆(java堆,CG堆)
是JVM中所管理的内存中最大的一块内存区域,是线程共享的,在JVM启动时创建,存放了对象的实例及数组(所有new的对象)
堆内存逻辑分为
分配图(JDK7.0)
简述:
新生区是对象的创建、应用、消亡的区域,一个对象在这里产生、应用、最终被垃圾回收器收集,消亡。
新生区又分为两部分:伊甸区和幸存者区。
所有新创建的对象(new) 都是在伊甸区;
幸存者分为两个:幸存者0区和1区
- 当伊甸区的空间用完时,程序需要创建新的对象
- JVM对伊甸区开始进行垃圾回收,应用的是YGC,将伊甸区不再使用的对象进行销毁
- 然后将伊甸区剩余的对象移到幸存者0区,0区满了,对0区进行垃圾销毁,存活的对象移到幸存者1区
- 如果1区也满了,则再将1区的对象移动到养老区
- 如果养老区也满了,此时JVM将开启 FullGC(简称:FGC),进行养老区的内存清理
- 但是如果执行Full GC之后依然无法保存 新的对象,则产生OOM异常:堆内存溢出
永久区:存放静态常量的
分配图(JDK8.0)
将永久区取消了,由元空间(物理内存)代替
-Xms(启动空间):设置初始分配大小,默认为物理内存的 1/64
-Xmx(最大空间):最大分配内存,默认为物理内存的 1/4
-XX:+PrintGCDetails:输出详细的GC处理日志
调参
StankOverflowError(栈溢出)
Memory leak(内存泄漏)
申请的内存空间没有被释放,会降低程序运行效率,多次泄漏就会造成内存溢出
OOM(内存溢出)
没有足够的内存空间供其使用
产生原因
避免方法
尽早释放无用对象的引用
适应临时变量时,让引用变量在退出时设置为 null,暗示垃圾收集器来收集对象
尽量少用静态变量
因为静态变量是全局的,GC 不会回收
尽量运用对象池技术提高系统性能
常量池、串池、连接池(重复利用,提高效率)
不要在经常调用的方法中创建对象,尤其忌讳在循环中创建对象
优化配置
是一种抽象的概念,并不真实存在,它描述的是一组规则和规范
Java线程会将主内存(共享)中的数据拷贝到自身工作内存中完成相应操作,再将结果保存(save)到主内存中
是指一个操作是不可中断的,即时是多个线程一起执行的时候,一 个操作一旦开始,就不会被其他线程干扰。
实现:在 Java 中可以使用 synchronized/Lock 关键字来保证方法和代码块内的操 作原子性。
是指一个线程修改了某一个共享的值,其他线程是否能够立即知道这个值被修改。
实现:可以以利用 Java 中的 volatile 关键字来保证多线程操作时变量的可见 性;也可以利用 synchronized /final 关键字实现可见性。
是指程序执行的顺序按照代码的先后顺序执行。
实现:可以使用 Java 中 synchronized/volatile 关键字来保证多线程之 间操作的有序性