├── .gitattributes
├── Git使用教程:最详细、最傻瓜、最浅显、真正手把手教.md
├── Java笔记
├── JVM内存管理.jpeg
├── Tips
│ ├── Maven相关内容学习.md
│ ├── _vnote.json
│ ├── assets
│ │ └── 20191020153916868_1651964039.png
│ └── finally语句如何执行.md
├── _vnote.json
├── assets
│ ├── 1551267436382.png
│ ├── 1551268923990.png
│ ├── 1551271953665.png
│ ├── 1551512824910.png
│ ├── 1551517542209.png
│ ├── 1551626172914.png
│ ├── 1551628646433.png
│ ├── 1551708631498.png
│ ├── 1551859303006.png
│ ├── 1552270512675.png
│ ├── 1552270979760.png
│ ├── 1552274222807.png
│ ├── 22f72b18415405c3e0207925a8de74fa_hd.jpg
│ ├── 640-1551860568789.webp
│ ├── 640-1551878862223.webp
│ ├── 640-1551955088595.webp
│ ├── 640-1551958892751.webp
│ ├── 640.webp
│ ├── Collection.jpg
│ └── thread.jpg
├── java并发编程的艺术.md
├── java核心技术卷计划.md
├── 深入理解Java虚拟机.md
├── 设计模式
│ ├── _vnote.json
│ ├── code
│ │ ├── Singleton.java
│ │ └── Singleton1.java
│ └── 单例模式.md
└── 读一读JVM.md
├── LICENSE
├── Linux命令及Shell脚本学习笔记
├── Linux大棚命令百篇(上)
│ ├── _vnote.json
│ ├── assets
│ │ ├── 20191007182630566_2108786728.png
│ │ ├── 20191008220031920_1820220481.png
│ │ ├── 20191008220315271_1564072186.png
│ │ ├── 20191025111117600_875492706.png
│ │ ├── 20191025111321005_1206297223.png
│ │ ├── 20191025111736272_44758469.png
│ │ ├── 20191025112205069_1587054822.png
│ │ └── 20191025121416871_1717319503.png
│ └── 什么是Shell.md
├── README.md
├── Vi快捷操作学习.md
├── Windows转Linux之常用命令学习(一).md
├── Windows转Linux之常用命令学习(二).md
├── Windows转Linux之常用命令学习(二).md.vswp
├── _vnote.json
├── assets
│ ├── 1546870348043.png
│ ├── 1546872241318.png
│ ├── apt使用.png
│ ├── crontab.png
│ ├── df.png
│ ├── du-0.png
│ ├── du-exclude.png
│ ├── du-h.png
│ ├── du-maxdepth.png
│ ├── fdisk.png
│ ├── gb18030.png
│ ├── history.png
│ ├── selinux.png
│ ├── ssh连接失败.png
│ ├── vi常用命令.png
│ └── 系统信息.png
├── rpm命令使用.md
├── 包管理工具apt使用.md
├── 包管理工具yum使用.md
├── 终端常用快捷键.md
└── 韩顺平_Linux (大数据 javaEE Python 开发通用版).pdf
├── Linux系统下开发环境搭建
├── (可参考)Deepin 15.4 Win10双系统安装教程.pdf
├── AppImage打包方式及相关Linux游戏站推荐.md
├── Deepin15.8下搭建Python开发环境.md
├── Deepin下如何科-学(地)上-网.md
├── Deepin下搭建Hadoop、Spark等大数据开发环境.md
├── Deepin下源码编译安装配置git.md
├── Deepin使用体验、资源及问题归纳贴.md
├── Deepin常用快捷键及快捷其他操作.md
├── Deepin自定义右键新建文件模版.md
├── Deepin设置开机自启动脚本问题.md
├── IDEA常用快捷键.md
├── Linux中文件系统各个目录的作用.md
├── Linux应用推荐.md
├── README.md
├── Win10下双系统Deepin15.8安装.md
├── _vnote.json
├── assets
│ ├── 1547104601035.png
│ ├── 1547122130325.png
│ ├── 1547122270694.png
│ ├── 1547122288560.png
│ ├── 1547122720202.png
│ ├── 1547122847689.png
│ ├── 1547122893538.png
│ ├── 1547123056508.png
│ ├── 1547123559546.png
│ ├── 1547123614467.png
│ ├── 1547123742916.png
│ ├── 1547123811269.png
│ ├── 1547123827216.png
│ ├── 1547123852762.png
│ ├── 1547123928107.png
│ ├── 1547124309030.png
│ ├── 1547127856260.png
│ ├── 1549802209141.png
│ ├── 1549802355287.png
│ ├── 1549804313390.png
│ ├── 190111521.jpg
│ ├── 20190120220106492.png
│ ├── 20190123162839.png
│ ├── 20190517182502290_970489846.png
│ ├── add.png
│ ├── dropins.png
│ ├── eclipse下载.png
│ ├── eclipse安装.png
│ ├── folder选择.png
│ ├── gitconfig.png
│ ├── hadoop配置.png
│ ├── hdfs.png
│ ├── insert.png
│ ├── java-v.png
│ ├── java环境配置.png
│ ├── maven源.png
│ ├── maven配置.png
│ ├── metadata.png
│ ├── mvnsetting.png
│ ├── mysql安装.png
│ ├── mysql驱动.png
│ ├── pip下载在哪里.png
│ ├── pycharm中运行jupyter.png
│ ├── pycharm安装00.png
│ ├── pycharm安装01.png
│ ├── pycharm安装02.png
│ ├── pycharm安装03.png
│ ├── pycharm桌面.png
│ ├── pycharm虚拟环境00.png
│ ├── scalalocation.png
│ ├── scala插件.png
│ ├── select.png
│ ├── slave2.png
│ ├── slave文件.png
│ ├── sparkslave.png
│ ├── ssh免密.png
│ ├── startspark.png
│ ├── toolsdownload.png
│ ├── tools安装出错.png
│ ├── venv.png
│ ├── vm.png
│ ├── vmtools.png
│ ├── vm使用.png
│ ├── vm启动失败.png
│ ├── vm安装.png
│ ├── vm网络设置.png
│ ├── wHive.png
│ ├── yarn.png
│ ├── 传输公钥.png
│ ├── 创建git.png
│ ├── 发送masterpub.png
│ ├── 取消scala.png
│ ├── 启动musqld.png
│ ├── 启动venv.png
│ ├── 复制vm.png
│ ├── 字段.png
│ ├── 安装.png
│ ├── 安装scala插件.png
│ ├── 查看.png
│ ├── 查看mysql.png
│ ├── 深度截图_选择区域_20190219225738.png
│ ├── 解压.png
│ ├── 触摸板手势.png
│ └── 重命名.png
└── requirements.txt
├── README.md
├── README.md.20190124222838.bak
├── Spring-Boot-Learning
├── README.md
├── _vnote.json
└── assets
│ ├── 20191022153424858_1878326502.png
│ ├── 20191022153632597_151903268.png
│ ├── 20191022154456020_407860967.png
│ ├── 20191022154845144_995881766.png
│ ├── 20191022160835093_168811412.png
│ ├── 20191022161225973_1331719954.png
│ ├── 20191022161346956_1117468288.png
│ ├── 20191022201407698_1597655336.png
│ ├── 20191022210336626_1331334869.png
│ ├── 20191024095409385_232974006.png
│ ├── 20191024172348188_2081525319.png
│ ├── 20191028232512518_312968216.png
│ ├── 20191029202018852_969396943.png
│ ├── 20191029205135984_418441085.png
│ ├── 20191029224401689_359358011.png
│ ├── 20191029225826769_1169318871.png
│ └── 20191029230019588_1482385818.png
├── _vnote.json
├── assets
├── 1547472870163.png
├── 1547472895580.png
├── 1556878717809.png
├── 1556882392939.png
├── 1556883671229.png
├── 1556883688122.png
├── 1556883986766.png
├── 1556884056058.png
├── 1556884308437.png
├── 1556884626871.png
├── 1556884677828.png
├── 1556884770319.png
├── 1556885297319.png
├── 1556885669473.png
├── 1556885795335.png
├── 1556885939394.png
├── 1556886206847.png
├── 1556886589539.png
├── 1556886824092.png
├── 1556887053275.png
├── 1556887129427.png
├── 1556944982177.png
├── 1556945256521.png
├── 1556945314176.png
├── 1556945414408.png
├── 1556945533185.png
├── 1556945641117.png
├── 1556945756926.png
├── 1556945820141.png
├── 20190503174907.png
├── 20190822110758971_764642917.png
├── 20190822110907672_847619643.png
├── 20190822110937662_1548052493.png
└── githubLicense.png
├── eBook
├── HBase系列
│ └── HBase实战.pdf
├── JAVA核心知识点整理.pdf
├── Python
│ ├── Python3数据分析与挖掘.txt
│ ├── Python升级3.6 强力Django+杀手级Xadmin打造在线教育平台.txt
│ └── 分布式爬虫打造搜索引擎.txt
├── README.md
├── Spark系列
│ ├── 01-基于Spark2.x新闻网大数据实时分析可视化系统项目.txt
│ ├── 02-Spark离线和实时电影推荐系统直播回放(视频+文档+代码).txt
│ ├── 03-Spark项目实战:爱奇艺用户行为实时分析系统.txt
│ ├── 04-Spark企业级实战项目:道路交通实时流量监控预测系统.txt
│ ├── 05-Spark企业级实战项目:知名手机厂商用户行为实时分析系统.txt
│ ├── 06-Spark大型项目实战:电商用户行为分析大数据平台.txt
│ └── 07-Spark 2.0从入门到精通245讲.txt
├── _vnote.json
├── 代码审核.md
├── 算法及其余基础书籍
│ ├── 数据库和分布式
│ │ ├── 20个数据库常见面试题讲解 - 搜云库技术团队.pdf
│ │ ├── 『浅入深出』MySQL 中事务的实现.pdf
│ │ ├── 分布式系统一致性(ACID、CAP、BASE、二段提交、三段提交、TCC、幂等性)原理详解.pdf
│ │ ├── 分布式锁实现(基于redis-mysql).pdf
│ │ ├── 数据库两大神器【索引和锁】.pdf
│ │ └── 理解分布式事务 -贝聊科技.pdf
│ └── 牛客网算法.txt
└── 面试技术岗,你真能讲明白技术吗?.md
├── git团队协作项目操作说明.md
├── toc.py
├── 大数据
├── DataFun技术年货大数据篇.pdf
├── DataFun技术年货搜索推荐篇.pdf
├── DataFun技术年货风控反欺诈.pdf
├── _vnote.json
├── hadoop系列
│ ├── 01MapReduce编程初步及源码分析.md
│ ├── 02【MapReduce详解及源码解析(一)】——分片输入、Mapper及Map端Shuffle过程.md
│ ├── _vnote.json
│ ├── assets
│ │ └── copycode.gif
│ ├── hadoop和hive的一些面试题.zip
│ ├── 使用Java API对HDFS进行系列操作.md
│ ├── 大数据
│ │ ├── HDFS名词.jpg
│ │ ├── MapReduce_coding.png
│ │ ├── SecNamenode.jpg
│ │ ├── mapreduce.jpg
│ │ └── metadata.jpg
│ ├── 数据倾斜解决(MR、Hive、Spark).md
│ ├── 认识HDFS.md
│ └── 转载
│ │ ├── HDFS 架构学习总结 _ Matt's Blog.pdf
│ │ ├── YARN 架构学习总结 _ Matt's Blog.pdf
│ │ └── 唯品会HDFS性能挑战和优化实践.pdf
├── spark系列
│ ├── Intel-Spark SQL优化实践.pdf
│ ├── Koalas:让 pandas 轻松切换 Apache Spark,在大数据中规模应用.md
│ ├── RDD完整.pdf
│ ├── Spark SQL最佳实践.pdf
│ ├── SparkSQL子查询源码阅读.pdf
│ ├── Spark大数据相关面试.pdf
│ └── _vnote.json
├── 京东大数据技术白皮书-2018.12-120页.pdf
├── 今日头条推荐系统+架构设计实践.pdf
├── 快看漫画大数据平台的模型思维与用户增长实践.pdf
├── 有赞百亿级日志系统架构设计.pdf
├── 流式数据处理在百度数据工厂应用与实践.pdf
└── 用户画像相关资料
│ ├── 《奔跑吧兄弟2》电视直播观看人群用户画像报告.pdf
│ ├── 《用户画像分析》专题分享.pptx
│ ├── 基于用户画像的大数据挖掘实践 .pdf
│ ├── 用户画像举例.pdf
│ ├── 用户画像和精准化平台系统实践案例.pdf
│ ├── 用户画像实战应用.pdf
│ ├── 用户画像很重要-那你知道是怎么画出来的吗?.pdf
│ ├── 用户画像数据建模方法.docx
│ ├── 用户画像数据建模方法.pdfx.pdf
│ ├── 用户画像构建.docx
│ ├── 用户画像的方法、实践与行业应用.docx
│ └── 用户画像的构建及应用.pdf
└── 算法和数据结构
├── LeetCode刷题心得
├── LeetCode刷题心得.md
├── _vnote.json
└── assets
│ ├── Cycle.png
│ ├── reverseList.png
│ └── 奇偶链表.png
├── _vnote.json
└── 剑指Offer
├── _vnote.json
├── 字符串.md
└── 链表.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/Java笔记/JVM内存管理.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/JVM内存管理.jpeg
--------------------------------------------------------------------------------
/Java笔记/Tips/Maven相关内容学习.md:
--------------------------------------------------------------------------------
1 | # Maven相关内容学习
2 |
3 | 我这里安装的是 maven 3.6.0 版本的,在idea中也安装了相关插件
4 | 
5 |
6 | ## pom.xml文件如何配置
7 | 我这里先粘一个模版
8 |
9 | ```xml
10 |
11 |
14 | 4.0.0
15 |
16 | com.dlut.sparkLearning
17 | sparkSql
18 | 1.0-SNAPSHOT
19 | jar
20 |
21 |
22 | 2.4.0
23 | ...
24 |
25 |
26 |
27 |
28 |
29 |
30 | org.apache.spark
31 | spark-core_2.11
32 | ${spark.version}
33 | provided
34 |
35 |
36 | ...
37 |
38 |
39 | ...
40 | ...
41 | ...
42 |
43 | ...
44 | ...
45 |
46 | ```
47 | ### 基本配置
48 | - **每个项目都只有一个pom.xml文件**
49 | - 第一行规定了xml文档的版本和编码
50 | - project是pom.xml文件的根元素,规定了一些pom相关的命名空间及xsd元素
51 | - 基本配置
52 | - modelVersion规定了pom模型的版本,maven2和3只能是4.0.0
53 | - groupId、artifactId、version是用来区分项目的基本元素,规定了项目属于哪个项目组,项目在组中唯一id,项目版本
54 | - packaging规定了项目打包方式,默认是jar。可选pom, jar, maven-plugin, ejb, war, ear, rar, par
55 |
56 | ### 依赖配置
57 |
58 | - 依赖配置
59 | - properties定义pom中的常量,比如上面定义spark版本为2.4.0,引用时通过`${spark.version}`调用即可
60 | - dependencies定义了项目中需要的一些依赖
61 | - 父项目中的依赖会被子项目所引用,通常用来申明一些公共依赖,比如java版本啥的
62 | - 我通常会在 https://mvnrepository.com 查找一些依赖jar的dependency写法
63 | - dependency详细应用在下面展开
64 | - parent用来确定父项目位置,如下
65 | - groupId、artifactId、version和上文一样,但指定的是父项目的
66 | - relativePath,maven首先在当前项目中找父项目,然后在文件系统的这个位置(relativePath),然后在本地仓库,再在远程仓库找
67 | > 仓库是个啥?可以看下这篇文章的介绍:https://juejin.im/post/5a4a5e2bf265da4322418d7f
68 | ```xml
69 |
70 | com.dlut.Bigdata
71 | spark-parent
72 |
73 | 0.0.1-SNAPSHOT
74 |
75 | ```
76 | - dependencyManagement一般是在父项目中写,写法同dependencies。父项目定义了依赖,子项目不会直接使用相应依赖,只有子项目需要使用才引用,但无需写相关版本。可能没讲请
77 | ```xml
78 |
79 |
80 |
81 |
82 | org.apache.spark
83 | spark-core_2.11
84 | ${spark.version}
85 | provided
86 |
87 |
88 |
89 |
90 |
91 |
92 | org.apache.spark
93 | spark-core_2.11
94 |
95 | ```
96 | - models是一些maven项目会拆分成若干模快,暂时不太清楚
97 |
98 | #### 细说依赖dependency
99 | ```xml
100 |
101 | ...
102 | ...
103 | ...
104 | 依赖类型
105 | 依赖范围
106 | 依赖是否可选
107 |
108 |
109 |
110 | …
111 | …
112 |
113 |
114 |
115 | ```
116 | **我通常会在 https://mvnrepository.com 查找一些依赖jar的dependency写法**
117 |
118 | 1. groupId、artifactId和上面讲的一样,不用管
119 | 2. version是你需要考虑的,选择适合的版本
120 | 3. type是类型,默认是jar,和上面讲的packaging是一样的,不用管
121 | 4. scope是范围
122 | 1. 有*compile*(默认)、*provided*、*test*、*runtime*、*system*选项
123 | 2. 不写scope时默认是compile
124 | > | 依赖范围 | / |
125 | >| :------- | :------------------------------------------------------------------------------------------- |
126 | >| compile | 编译、测试、运行时都会用到该依赖(该依赖会编译打到jar包内,默认) |
127 | >| provided | 编译、测试时用到该依赖(运行环境中有该依赖时适用) |
128 | >| test | 编译测试代码和运行测试代码时会用到该依赖 |
129 | >| runtime | 测试、运行时用到该依赖,但编译时不会用到 |
130 | >| system | 和provided一样,但需要通过systemPath来指明依赖在系统中位置,谨慎使用,毕竟移到其他系统下位置可能不一样 |
131 | >
132 | >```xml
133 | >
134 | >
135 | >
136 | > org.apache.spark
137 | > spark-hive_2.11
138 | > 2.4.0
139 | > system
140 | > /home/xxx/Jars/spark-hive_2.11-2.4.0.jar
141 | >
142 | > ```
143 | 5. optional可选依赖,有true和false选择
144 | 1. `true`,还是针对A->B->C这种传递依赖,如果在B的pom文件中写明C依赖是`true`,则A不会引入C依赖。如果A需要C依赖的话,需要显示添加C依赖;或者将optional设为false或去掉
145 | 2. **optional选项在统一控制版本的情况下会失效**
146 | ```xml
147 |
148 |
149 | A
150 | A
151 | 1.0-SNAPSHOT
152 |
153 |
154 |
155 |
156 | joda-time
157 | joda-time
158 | 2.9.9
159 | true
160 |
161 |
162 |
163 |
164 | B
165 | B
166 | 1.0-SNAPSHOT
167 |
168 |
169 | A
170 | A
171 | 1.0-SNAPSHOT
172 |
173 |
174 |
175 |
176 |
177 | joda-time
178 | joda-time
179 |
180 |
181 | ```
182 | 6. exclusions用来排除传递性依赖,主动排除子项目传递过来的依赖
183 | > 传递性依赖,项目A依赖B,B中又对C有依赖,所以A也间接对C依赖,有传递之意。不用管那么多,Maven会解析各个直接依赖的pom文件,将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中
184 | > 不过有一点要记得,compile依赖范围选项会把该依赖打进jar包中,所以该依赖是直接打进项目还是借助环境中现有的依赖要考虑清除
185 |
186 | - 只需要groupId和artifactId
187 | - 排除一些不适合的版本的依赖
188 | ```xml
189 |
190 | ...
191 | ...
192 | ...
193 |
194 |
195 |
196 | A
197 | A
198 |
199 |
200 |
201 |
202 |
203 | A
204 | A
205 | ...
206 | ...
207 |
208 | ```
209 |
210 |
211 | ### 构建配置
212 |
213 | - 构建配置
214 | -
215 | ## setting.xml文件如何配置
216 |
217 |
218 | ### 参考文章
219 | - https://www.jianshu.com/p/0e3a1f9c9ce7
220 | - https://juejin.im/post/5a4a5e2bf265da4322418d7f
--------------------------------------------------------------------------------
/Java笔记/Tips/_vnote.json:
--------------------------------------------------------------------------------
1 | {
2 | "created_time": "2019-05-17T09:44:08Z",
3 | "files": [
4 | {
5 | "attachment_folder": "",
6 | "attachments": [
7 | ],
8 | "created_time": "2019-05-17T09:44:08Z",
9 | "modified_time": "2019-05-17T09:44:08Z",
10 | "name": "finally语句如何执行.md",
11 | "tags": [
12 | ]
13 | },
14 | {
15 | "attachment_folder": "",
16 | "attachments": [
17 | ],
18 | "created_time": "2019-10-20T07:37:29Z",
19 | "modified_time": "2019-10-21T15:18:16Z",
20 | "name": "Maven相关内容学习.md",
21 | "tags": [
22 | ]
23 | }
24 | ],
25 | "sub_directories": [
26 | ],
27 | "version": "1"
28 | }
29 |
--------------------------------------------------------------------------------
/Java笔记/Tips/assets/20191020153916868_1651964039.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/Tips/assets/20191020153916868_1651964039.png
--------------------------------------------------------------------------------
/Java笔记/Tips/finally语句如何执行.md:
--------------------------------------------------------------------------------
1 | ## finally语句如何执行
2 | 一般是在try...catch...finally中配对使用finally,多用来释放资源。虽然这个点很简单,但还是有些地方需要注意的。
3 | - 无论try是否发生异常,finally语句都会执行
4 | - 如果try/catch中包含控制转移语句(return、continue、break),finally都会在这些控制语句前执行
5 | - 但是像try/catch中有`System.exit(0)`退出JVM,或者Daemon线程退出(也就是线程被中断,被kill),finally语句都不会执行
6 |
7 | ```java
8 | public class testFinally{
9 | public static int test(){
10 | try{
11 | Integer.parseInt("execption");
12 | System.out.println("block 0");
13 | }catch (Exception e){
14 | System.out.println("block 1");
15 | //System.exit(0);//取消的话直接退出
16 | return iamReturn();
17 | }finally{
18 | System.out.println("block 2");
19 | return 2;
20 | }
21 | }
22 | public static int iamReturn() {
23 | System.out.println("return block");
24 | return 666;
25 | }
26 | public static void main(String[] args){
27 | System.out.println(test());
28 | }
29 | }
30 | ```
31 | 输出:
32 | > block 1
33 | return block
34 | block 2
35 | 2
36 |
37 | ```java
38 | public class testFinally1{
39 | public static int test(){
40 | try{
41 | System.out.println("block 0");
42 | return 1;
43 | }catch (Exception e){
44 | System.out.println("block 1");
45 | //return 2;
46 | }finally{
47 | System.out.println("block 2");
48 | //return 3;
49 | }
50 | return 4;//小心这里,可能会出现不可达的情况,比如finally中有return,或者try/catch都有return
51 | }
52 |
53 | public static void main(String[] args){
54 | System.out.println(test());
55 | }
56 | }
57 | ```
58 | 输出:
59 | > block 0
60 | block 2
61 | 1
62 |
63 | ```java
64 | public class testFinally2{
65 | public static int test(){
66 | int i = 0;
67 | try{
68 | return i;
69 | }finally{
70 | i++;//++i也罢
71 | }
72 | }
73 | public static void main(String[] args){
74 | System.out.println(test());
75 | }
76 | }
77 | ```
78 | 输出:
79 | > 0
80 |
81 | 这个还是输出0,不是1,即使finally会先于try种的return执行,这个涉及jvm如何编译finally语句
82 | > Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。请注意,前文中我们曾经提到过 return、throw 和 break、continue 的区别,对于这条规则(保留返回值),只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,因为它们根本就没有返回值。
83 |
84 | 这个还是挺秀的,之前都没注意过,今天看到提到了就记下来了
--------------------------------------------------------------------------------
/Java笔记/_vnote.json:
--------------------------------------------------------------------------------
1 | {
2 | "created_time": "2019-05-17T09:44:08Z",
3 | "files": [
4 | {
5 | "attachment_folder": "",
6 | "attachments": [
7 | ],
8 | "created_time": "2019-05-17T09:44:08Z",
9 | "modified_time": "2019-05-17T09:44:08Z",
10 | "name": "java并发编程的艺术.md",
11 | "tags": [
12 | ]
13 | },
14 | {
15 | "attachment_folder": "",
16 | "attachments": [
17 | ],
18 | "created_time": "2019-05-17T09:44:08Z",
19 | "modified_time": "2019-05-17T09:44:08Z",
20 | "name": "java核心技术卷计划.md",
21 | "tags": [
22 | ]
23 | },
24 | {
25 | "attachment_folder": "",
26 | "attachments": [
27 | ],
28 | "created_time": "2019-05-17T09:44:08Z",
29 | "modified_time": "2019-05-17T09:44:08Z",
30 | "name": "深入理解Java虚拟机.md",
31 | "tags": [
32 | ]
33 | },
34 | {
35 | "attachment_folder": "",
36 | "attachments": [
37 | ],
38 | "created_time": "2019-05-17T09:44:08Z",
39 | "modified_time": "2019-05-17T09:44:08Z",
40 | "name": "读一读JVM.md",
41 | "tags": [
42 | ]
43 | }
44 | ],
45 | "sub_directories": [
46 | {
47 | "name": "Tips"
48 | },
49 | {
50 | "name": "设计模式"
51 | }
52 | ],
53 | "version": "1"
54 | }
55 |
--------------------------------------------------------------------------------
/Java笔记/assets/1551267436382.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551267436382.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551268923990.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551268923990.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551271953665.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551271953665.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551512824910.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551512824910.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551517542209.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551517542209.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551626172914.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551626172914.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551628646433.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551628646433.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551708631498.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551708631498.png
--------------------------------------------------------------------------------
/Java笔记/assets/1551859303006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1551859303006.png
--------------------------------------------------------------------------------
/Java笔记/assets/1552270512675.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1552270512675.png
--------------------------------------------------------------------------------
/Java笔记/assets/1552270979760.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1552270979760.png
--------------------------------------------------------------------------------
/Java笔记/assets/1552274222807.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/1552274222807.png
--------------------------------------------------------------------------------
/Java笔记/assets/22f72b18415405c3e0207925a8de74fa_hd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/22f72b18415405c3e0207925a8de74fa_hd.jpg
--------------------------------------------------------------------------------
/Java笔记/assets/640-1551860568789.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/640-1551860568789.webp
--------------------------------------------------------------------------------
/Java笔记/assets/640-1551878862223.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/640-1551878862223.webp
--------------------------------------------------------------------------------
/Java笔记/assets/640-1551955088595.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/640-1551955088595.webp
--------------------------------------------------------------------------------
/Java笔记/assets/640-1551958892751.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/640-1551958892751.webp
--------------------------------------------------------------------------------
/Java笔记/assets/640.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/640.webp
--------------------------------------------------------------------------------
/Java笔记/assets/Collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/Collection.jpg
--------------------------------------------------------------------------------
/Java笔记/assets/thread.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josonle/Coding-Now/32b963ff23af1e957099d03cb9f935a32cbc9373/Java笔记/assets/thread.jpg
--------------------------------------------------------------------------------
/Java笔记/java并发编程的艺术.md:
--------------------------------------------------------------------------------
1 | ## Java提供的四种常用线程池解析
2 |
3 | 既然楼主踩坑就是使用了 JDK 的默认实现,那么再来看看这些默认实现到底干了什么,封装了哪些参数。简而言之 Executors 工厂方法Executors.newCachedThreadPool() 提供了无界线程池,可以进行自动线程回收;Executors.newFixedThreadPool(int) 提供了固定大小线程池,内部使用无界队列;Executors.newSingleThreadExecutor() 提供了单个后台线程。
4 |
5 | 详细介绍一下上述四种线程池。
6 |
7 | ### newCachedThreadPool
8 |
9 | ```text
10 | public static ExecutorService newCachedThreadPool() {
11 | return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
12 | 60L, TimeUnit.SECONDS,
13 | new SynchronousQueue());
14 | }
15 | ```
16 |
17 | 在newCachedThreadPool中如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
18 | 初看该构造函数时我有这样的疑惑:核心线程池为0,那按照前面所讲的线程池策略新任务来临时无法进入核心线程池,只能进入 SynchronousQueue中进行等待,而SynchronousQueue的大小为1,那岂不是第一个任务到达时只能等待在队列中,直到第二个任务到达发现无法进入队列才能创建第一个线程?
19 | 这个问题的答案在上面讲SynchronousQueue时其实已经给出了,要将一个元素放入SynchronousQueue中,必须有另一个线程正在等待接收这个元素。因此即便SynchronousQueue一开始为空且大小为1,第一个任务也无法放入其中,因为没有线程在等待从SynchronousQueue中取走元素。因此第一个任务到达时便会创建一个新线程执行该任务。
20 |
21 | ### newFixedThreadPool
22 |
23 | ```text
24 | public static ExecutorService newFixedThreadPool(int nThreads) {
25 | return new ThreadPoolExecutor(nThreads, nThreads,
26 | 0L, TimeUnit.MILLISECONDS,
27 | new LinkedBlockingQueue());
28 | }
29 | ```
30 |
31 | 看代码一目了然了,线程数量固定,使用无限大的队列。再次强调,楼主就是踩的这个无限大队列的坑。
32 |
33 | ### newScheduledThreadPool
34 |
35 | 创建一个定长线程池,支持定时及周期性任务执行。
36 |
37 | ```text
38 | public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
39 | return new ScheduledThreadPoolExecutor(corePoolSize);
40 | }
41 | ```
42 |
43 | 在来看看ScheduledThreadPoolExecutor()的构造函数
44 |
45 | ```text
46 | public ScheduledThreadPoolExecutor(int corePoolSize) {
47 | super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
48 | new DelayedWorkQueue());
49 | }
50 | ```
51 |
52 | ScheduledThreadPoolExecutor的父类即ThreadPoolExecutor,因此这里各参数含义和上面一样。值得关心的是DelayedWorkQueue这个阻塞对列,在上面没有介绍,它作为静态内部类就在ScheduledThreadPoolExecutor中进行了实现。简单的说,DelayedWorkQueue是一个无界队列,它能按一定的顺序对工作队列中的元素进行排列。
53 |
54 | ### newSingleThreadExecutor
55 |
56 | 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
57 |
58 | ```text
59 | public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
60 | return new DelegatedScheduledExecutorService
61 | (new ScheduledThreadPoolExecutor(1));
62 | }
63 | ```
64 |
65 | 首先new了一个线程数目为 1 的ScheduledThreadPoolExecutor,再把该对象传入DelegatedScheduledExecutorService中,看看DelegatedScheduledExecutorService的实现代码:
66 |
67 | ```text
68 | DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
69 | super(executor);
70 | e = executor;
71 | }
72 | ```
73 |
74 | 在看看它的父类
75 |
76 | ```text
77 | DelegatedExecutorService(ExecutorService executor) {
78 | e = executor;
79 | }
80 | ```
81 |
82 | 其实就是使用装饰模式增强了ScheduledExecutorService(1)的功能,不仅确保只有一个线程顺序执行任务,也保证线程意外终止后会重新创建一个线程继续执行任务。
83 |
84 | > 见:
--------------------------------------------------------------------------------
/Java笔记/深入理解Java虚拟机.md:
--------------------------------------------------------------------------------
1 | ### JVM堆内存分布
2 |
3 |
4 |
5 | ### JVM堆内存分配策略
6 |
7 | 分新生代、老年代、永久代(jdk 1.8之后替换成了Metaspace)
8 |
9 | - 新生代 【8:1:1】
10 |
11 | - Eden区+Survivor1区+Survivor2区,Eden和Survivor默认8:1,两块Survivor一样大(读完本书可以知道是因为新生代多采取复制清除GC算法)
12 | - 对象优先在 Eden 分配
13 |
14 | - 老年代 【新生代:老年代=1:2】
15 |
16 | - 大对象直接放入老年代
17 |
18 | - 长期存活的对象晋入老年代
19 |
20 | > 动态对象年龄判断:
21 | >
22 | > 对象最新进入Eden区,进过第一次MinorGC后如果该对象任然存活,移入Survivor区,并维护一个年龄计数器,设为1。后续如果再次经过一次MinorGC,还没死亡的话年龄计数器自增1,如果年龄超过15,自动晋入老年代。或者相同年龄的对象超过Survivor内存区域一般时,也会自动把这些对象移入老年代
23 |
24 | - 永久代在jdk 1.8中被Metaspace元空间取代
25 |
26 | - 参考:[Java8内存模型—永久代(PermGen)和元空间(Metaspace)](https://www.cnblogs.com/paddix/p/5309550.html)
27 | - 可由**-XX:MaxPermSize**进行设置,永久代也称为方法区 ,用来存放类的信息、常量池、方法数据、方法代码等
28 | - 元空间不再是存放在虚拟机中了,而是直接使用本地内存
29 |
30 | > 永久代也是会发生垃圾回收的,但有三点条件:
31 | >
32 | > 1. 该类的实例都被回收。
33 | >
34 | > 2. 加载该类的classLoader已经被回收
35 | >
36 | > 3. 该类不能通过反射访问到其方法,而且该类的java.lang.class没有被引用
37 | >
38 | > 满足这三个条件可以回收,但回不回收还得看jvm
39 | >
40 | > 但很少说永久代垃圾回收,垃圾回收侧重新生代、永久代
41 |
42 | #### 堆内存各区域比例及相关控制参数
43 |
44 | 总的来说,堆可分为新生代+老年代,可由参数**–Xms(初始堆大小)、-Xmx(最大堆大小)**来控制大小,新生代大小由参数**-Xmn**控制,新生代三块分区比例可由**–XX:SurvivorRatio**控制,新生代和老年代比例可由参数**–XX:NewRatio**控制
45 |
46 |
47 |
48 | ### 如何判断对象已死亡?
49 |
50 | #### 引用计数法
51 |
52 | 最容易想到的就是这种,每有一个引用指向对象,引用计数器就加一,引用失效就减一。一旦引用计数器为0,表明对象已死亡,可回收。
53 |
54 | **问题是如果两个对象相互引用,引用计数器始终不会为0**
55 |
56 |
57 |
58 | #### 可达性分析算法
59 |
60 | 提出一个GC Roots 对象的概念,GC Roots为起点向下搜索,所走过的路径为引用链,如果没有GC Roots对象到该对象的引用链,表明该对象可回收
61 |
62 | - GC Roots对象包含哪些?
63 | - JVM虚拟机栈中引用的对象(栈帧是对象调用方法时生成的,具体说是局部变量表中引用的对象)
64 | - 本地方法栈中的JNI引用的对象(Java Native Interface缩写,Native方法是jav调用其他语言的方法,多用来提高效率、和底层硬件、小做系统交互)
65 | - 方法区中静态变量、常量引用的对象
66 |
67 | 
68 |
69 | [图片引自:Gityuan的回答 - 知乎](https://www.zhihu.com/question/21539353/answer/95667088)
70 |
71 | 如图,像对象实例1、2、4、6是GC Roots可达的,3和5是可被回收的
72 |
73 |
74 |
75 | > 这里有个问题是,搜索时是采用广度优先还是深度优先搜索?搞不清
76 |
77 | ### 什么时候会进行垃圾回收GC?
78 |
79 | 垃圾回收不能像C++似的手动进行,java中是由JVM自动判断进行GC的,但System.gc()可以提示进行GC
80 |
81 |
82 |
83 | - 新生代内存空间不足时,会进行Minor GC
84 | - 长期存活的对象由新生代晋升入老年代时,老年代内存空间不足的话也会进行full GC
85 |
86 | #### 看下对象的引用
87 |
88 | 引用分为四种:强引用、软引用、弱引用、虚引用
89 |
90 | - 强引用:强引用存在的话,即使内存不够,也不会对强引用对象回收。`P p = new P()`就是强引用
91 | - 软引用:内存空间足够时,不会回收;不足时才会对其回收。**可用来实现内存敏感的高速缓存**
92 | - 弱引用:垃圾回收器扫描到弱引用对象时就会对其回收,无论内存空间足不足
93 | - 虚引用:“虚”字可知,表明该引用可有可无。该虚引用对象被垃圾回收器回收时候,系统能够接收到一个通知
94 |
95 |
96 |
97 | ### GC 算法有哪些?
98 |
99 | - 标志-清除法
100 | - 适合老年代
101 | - 问题:标记和清除效率不高、内存空间碎片化的问题
102 | - 标志-整理法
103 | - 适合老年代
104 | - 也是为了解决碎片问题,标志同上,但会将所有存活的对象向一端移动,再回收
105 | - 复制清除法
106 | - 适合新生代
107 | - 两块一样大小的内存,每次用一块,这也是它的缺点(内存只使用一半)
108 | - 每次只对一块内存空间回收,效率高,不会出现空间碎片
109 | - 分代收集法 【用的最多的GC算法】
110 | - 根据新生代和老年代对象的性质,采取新生代使用复制清除法,老年代使用标志-清除/整理法
111 | - 新生代会有大量对象死亡,所以Minor GC发生频率高,而老年代中对象存活率高,GC没那么频繁
112 |
113 | ### 垃圾回收器
114 |
115 | #### Serial回收器
116 |
117 | 单线程、独占式GC
118 |
119 | #### ParNew回收器
120 |
121 | 多线程的Serial
122 |
123 | #### CMS回收器
124 |
125 |
126 |
127 | #### G1回收器
128 |
129 |
130 |
131 | ### 补充
132 |
133 | 看到一篇博客提到了死亡对象如何搜索BFS、DFS,有点兴趣,[见此](http://blog.jobbole.com/109833/)
134 |
135 | > 为什么新生代用广度搜索,老生代用深度搜索?
136 | >
137 | > 深度优先DFS一般采用递归方式实现,处理tracing的时候,可能会导致栈空间溢出,所以一般采用广度优先来实现tracing(递归情况下容易爆栈)。
138 | > 广度优先的拷贝顺序使得GC后对象的空间局部性(memory locality)变差(相关变量散开了)。
139 | > 广度优先搜索法一般无回溯操作,即入栈和出栈的操作,所以运行速度比深度优先搜索算法法要快些。
140 | > 深度优先搜索法占内存少但速度较慢,广度优先搜索算法占内存多但速度较快。
141 | >
142 | > 结合深搜和广搜的实现,以及新生代移动数量小,老生代数量大的情况,我们可以得到了解答。
--------------------------------------------------------------------------------
/Java笔记/设计模式/_vnote.json:
--------------------------------------------------------------------------------
1 | {
2 | "created_time": "2019-05-17T09:44:08Z",
3 | "files": [
4 | {
5 | "attachment_folder": "",
6 | "attachments": [
7 | ],
8 | "created_time": "2019-05-17T09:44:08Z",
9 | "modified_time": "2019-05-17T09:44:08Z",
10 | "name": "单例模式.md",
11 | "tags": [
12 | ]
13 | }
14 | ],
15 | "sub_directories": [
16 | ],
17 | "version": "1"
18 | }
19 |
--------------------------------------------------------------------------------
/Java笔记/设计模式/code/Singleton.java:
--------------------------------------------------------------------------------
1 | public class Singleton{
2 | private Singleton() {};
3 | //懒汉式
4 | private static Singleton single = null;
5 | //解决线程安全问题
6 | public static Synchronized Singleton getInstance(){
7 | if(single==null){
8 | single = new Singleton();
9 | }
10 | return single;
11 | }
12 | ` //双重检查锁定
13 | private volatile static Singleton single1 = null;
14 | public static Singleton getInstance(){
15 | if(single1==null){
16 | synchronized(Singleton.class){
17 | if(single1==null)
18 | single1 = new Singleton();
19 | }
20 | }
21 | return single;
22 | }
23 | //静态内部类方式
24 | //final解决多线程问题,也减去了判断single是否实例化的性能
25 | public static class LazyHolder{
26 | private static final Singleton ISTANCE = new Singleton();
27 | }
28 | public static Singleton getInstance(){
29 | return LazyHolder.INSTANCE;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Java笔记/设计模式/code/Singleton1.java:
--------------------------------------------------------------------------------
1 | public class Singleton1{
2 | public static final Singleton1 single = new Singleton();
3 | private Singleton1() {};
4 |
5 | public static Singleton1 getInstance(){
6 | return single;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Java笔记/设计模式/单例模式.md:
--------------------------------------------------------------------------------
1 | ### 懒汉式单例模式
2 |
3 | ```java
4 | public class Singleton{
5 | private Singleton(){};
6 | private static Singleton single = null;
7 | //存在线程安全问题
8 | public static Singleton getInstance(){
9 | if(single==null)
10 | single = new Singleton();
11 | return single;
12 | }
13 | }
14 | ```
15 |
16 | ```java
17 | public class Singleton{
18 | private Singleton() {};
19 | //懒汉式
20 | private static Singleton single = null;
21 | //解决线程安全问题
22 | public static Synchronized Singleton getInstance(){
23 | if(single==null){
24 | single = new Singleton();
25 | }
26 | return single;
27 | }
28 | }
29 | ```
30 |
31 | ```java
32 | public class Singleton{
33 | private Singleton() {};
34 | //双重检查锁定
35 | private volatile static Singleton single1 = null;
36 | public static Singleton getInstance(){
37 | if(single1==null){
38 | synchronized(Singleton.class){
39 | if(single1==null)
40 | single1 = new Singleton();
41 | }
42 | }
43 | return single;
44 | }
45 | }
46 | ```
47 | 双重检查锁定有一个地方要注意,single要用volatile修饰,因为JMM模型的特点,要保证内存的可见性,以及避免无序写入
48 | > 参考:https://www.iteye.com/topic/652440
49 |
50 | ```java
51 | public class Singleton{
52 | private Singleton(){};
53 | //静态内部类方式
54 | //final解决多线程问题,也减去了判断single是否实例化的性能
55 | public static class LazyHolder{
56 | private static final Singleton ISTANCE = new Singleton();
57 | }
58 | public static Singleton getInstance(){
59 | return LazyHolder.INSTANCE;
60 | }
61 | }
62 | ```
63 | 用内部类实现延迟加载
64 |
65 | ### 饿汉式单例模式
66 | 区别于懒汉式是类初始化时就会生成实例对象,而懒汉式是调用getInstance方法时才会生成实例
67 |
68 | ```java
69 | public class Singleton{
70 | //final修饰,线程安全,且唯一
71 | private final static Singleton single = new Singleton();
72 |
73 | private Singleton(){};
74 | public static Singleton getInstance(){
75 | return single;
76 | }
77 | }
78 | ```
79 | ### 登记式单例模式
80 | 省略
81 |
82 | ### 懒汉和饿汉比较
83 | 除了实例对象创建的时间,还有懒汉是非线程安全的只有自己实现,而饿汉是线程安全的。饿汉式无论用不用该实例都已经分配了内存,但第一次调用时速度也更快。
84 | 其次是,上面懒汉式的几种写法区别。
85 | - `public static Synchronized Singleton getInstance()`是同步的,效率会低,毕竟大多数时并不需要同步
86 | - 相比而言,双重检查锁定会先判断single是否空来减少同步保证,但也实现了线程安全
87 | - 静态内部类方式利用了classloader的机制来保证初始化instance时只有一个线程
88 |
89 | ### 参考
90 | - https://blog.csdn.net/jason0539/article/details/23297037
91 | - https://www.iteye.com/topic/652440
--------------------------------------------------------------------------------
/Java笔记/读一读JVM.md:
--------------------------------------------------------------------------------
1 | ### Class文件和类结构
2 |
3 | 类初始化时会谈及加载、验证过程,后者会检查class文件是否符合JVM的规定。JVM规范严格定义了CLASS文件的格式
4 |
5 | ### 类加载过程
6 |
7 | 类是怎样被JVM使用的?JVM会先找到类的入口,也就是main方法,通过JNI方法和Class类对象沟通
8 |
9 | #### 加载
10 |
11 | 第一步就是**加载**:首先是找到类(通过类的全限定名来获取定义该类的二进制流),然后通过**类加载器**将类装载到JVM实例中(具体是通过IO从硬盘或者网络读取读取Class二进制文件,将字节流中的静态存储结构转为方法区中运行时数据结构,并在内存中生成一个该类的Class对象作为类中数据结构的入口)。本质上就是把class文件读取到内存中
12 |
13 | > #### 聊下类加载器和双亲委派机制
14 | >
15 | > JVM启动时会把JRE默认的一些类加载到内存,这部分类(JRE提供的底层所需的类)使用的加载器是JVM默认内置的由C/C++实现
16 | >
17 | > - Bootstrap ClassLoader:包含在JVM内的,由C++实现,负责加载`JAVA_HOME/lib`下或者`-Xbootclasspath`指定路径下的类(实际是 `/jre/lib`下的类)
18 | >
19 | > > `URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();`
20 | >
21 | > - Extension ClassLoader:独立于JVM外,Java实现的,加载`JAVA_HOME/lib/ext`下或者`java.ext.dirs`系统变量指定的路径下的类(实际打印可以发现是`jre/lib/ext`下的类)
22 | >
23 | > 
24 | >
25 | > - Application ClassLoader:独立于JVM外,java实现,加载`-classpath`用户路径下的类(具体类加载器是`sun.misc.Launcher$AppClassLoader`)
26 | >
27 | > - 用户自定义类加载器:加载第三方类,具体是继承ClassLoader类,重写findClass和loadClass方法来自定义获取CLASS文件的目的
28 | >
29 | > ```java
30 | > //ClassLoader中loadClass方法
31 | > protected Class> loadClass(String name, boolean resolve)
32 | > throws ClassNotFoundException
33 | > {
34 | > synchronized (getClassLoadingLock(name)) {
35 | > // First, check if the class has already been loaded,看缓存有没有没有才去找
36 | > Class> c = findLoadedClass(name);
37 | > if (c == null) {
38 | > long t0 = System.nanoTime();
39 | > try {
40 | > //先看是不是最顶层,如果不是则parent为空,然后获取父类
41 | > if (parent != null) {
42 | > c = parent.loadClass(name, false);
43 | > } else {
44 | > //如果为空则说明应用启动类加载器,让它去加载
45 | > c = findBootstrapClassOrNull(name);
46 | > }
47 | > } catch (ClassNotFoundException e) {
48 | > // ClassNotFoundException thrown if class not found
49 | > // from the non-null parent class loader
50 | > }
51 | > if (c == null) {
52 | > // If still not found, then invoke findClass in order
53 | > //如果还是没有就调用自己的方法,确保调用自己方法前都使用了父类方法,如此递归三次到顶
54 | > long t1 = System.nanoTime();
55 | > c = findClass(name);
56 | > // this is the defining class loader; record the stats
57 | > sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
58 | > sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
59 | > sun.misc.PerfCounter.getFindClasses().increment();
60 | > }
61 | > }
62 | > if (resolve) {
63 | > resolveClass(c);
64 | > }
65 | > return c;
66 | > }
67 | > }
68 | > protected Class> findClass(String name) throws ClassNotFoundException {
69 | > throw new ClassNotFoundException(name);
70 | > }
71 | > ```
72 | >
73 | >
74 | >
75 | > - 双亲委派模型
76 | >
77 | > 定义不细说,就是类加载器优先把类加载请求交付给父类加载器去加载,层层递归,直到父类加载器无法加载才尝试自己加载该类(最多迭代三次可达到BootStrap ClassLoader)。
78 | >
79 | > 好处是类有了层次性划分,不重复加载已有的类以及维护类的唯一性,因为**类本身和加载这个类的类加载器来确定这个类在JVM中的唯一性**,比如书中举例`java.lang.Object`层层交付会由BootStrap ClassLoader加载(到JAVA_HOME/lib下rt.jar中去找),哪怕你自己写了个`java.lang.Object`还是会层层交付最终还是BootStrap ClassLoader来加载,使得JVM中只会出现一个`java.lang.Object`对象。如果不双亲委派可能会出现多个Object对象,整个系统就乱套了
80 | >
81 | > - 破坏双亲委派机制
82 |
83 | - 何时会触发类加载器加载class文件
84 |
85 | 继承场景,子类的创建触发父类加载;反射场景,通过对象反射获取类对象;类作为入口场景,即包含main方法的类首先会被加载;通过new创建对象、直接调用static属性、方法、代码块的场景(getstatic/putstatic/invokestatic字节码指令)
86 |
87 | #### 验证、准备、解析 【归属于链接阶段】
88 |
89 | class文件被加载到内存中后并非直接使用,想想就知道,要是不符合规范不就是留了个后门安全隐患
90 |
91 | - 验证不通过会报VerifyError。 `- Xverify:none `参数可以关闭验证,可见验证阶段非强制的
92 | - 准备,即验证通过后为static变量分配内存并赋零值(0、null这些),不过遇到静态常量时会赋初值。准备阶段更不一定会发生,比如没有static变量
93 | - 解析,引用字面量转化为直接变量空间 【??????**具体干啥待细看**】
94 |
95 |
96 |
97 | #### 初始化
98 |
99 | 把变量的初始值和构造方法的内容初始化到变量的空间里面
100 |
101 | #### 使用
102 |
103 | #### 卸载
104 |
105 | ### JMM(运行时内存分布)
106 |
107 |
108 |
109 | ### 垃圾回收
110 |
111 | ### 对象的四种引用及使用场景
112 |
113 | 强(**StrongReference**)、软(**SoftReference**)、弱(**WeakReference**)、虚(**PhantomReference**)引用
114 |
115 | 强引用,`A a = new A();`引用对象a就是强引用,不管内存够不够都不会被GC回收
116 |
117 | 软引用,`SoftReference