Skip to content

Commit 375ba0b

Browse files
committed
update notes
1 parent 4ac2e82 commit 375ba0b

5 files changed

Lines changed: 13 additions & 32 deletions

File tree

BasicKnowledge/Android基础面试题.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Android基础面试题
22
===
33

4-
没有删这套题,虽然都是网上找的,在刚开始找工作的时候这套题帮了我很多,那时候`Android`刚起步,很多家都是这一套面试题,我都是直接去了不看题画画一顿就写完了,哈哈
4+
没有删这套题,虽然都是网上找的,在刚开始找工作的时候这套题帮了我很多,那时候`Android`刚起步,很多家都是这一套面试题,我都是直接去了不看题哗哗一顿就写完了,哈哈
55
现在估计没有公司会用这种笔试题了。还是留下来吧,回忆一下。
66

77
1. 下列哪些语句关于内存回收的说明是正确的? (b)

BasicKnowledge/Bitmap优化.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ Bitmap优化
33

44
1. 一个进程的内存可以由2个部分组成:`native和dalvik`
55
`dalvik`就是我们平常说的`java`堆,我们创建的对象是在这里面分配的,而`bitmap`是直接在`native`上分配的。
6-
一旦内存分配给`Java`后,以后这块内存即使释放后,也只能给`Java`的使用,所以如果`Java`突然占用了一个大块内存,
6+
一旦内存分配给`Java`后,以后这块内存即使释放后,也只能给`Java`使用,所以如果`Java`突然占用了一个大块内存,
77
即使很快释放了,`C`能用的内存也是16M减去`Java`最大占用的内存数。
8-
而`Bitmap`的生成是通过`malloc`进行内存分配的,占用的是`C`的内存,这个也就说明了,上述的`4MBitmap`无法生成的原因,
8+
而`Bitmap`的生成是通过`malloc`进行内存分配的,占用的是`C`的内存,这个也就说明了,有时候`4MBitmap`无法生成的原因,
99
因为在`13M`被`Java`用过后,剩下`C`能用的只有`3M`了。
1010

1111
2.`Android`应用里,最耗费内存的就是图片资源。
@@ -58,7 +58,7 @@ Bitmap优化
5858
// 打印出图片的宽和高
5959
Log.d("example", opts.outWidth + "," + opts.outHeight);
6060
```
61-
在实际项目中,可以利用上面的代码,先获取图片真实的宽度和高度,然后判断是否需要跑缩小。如果不需要缩小,设置inSampleSize的值为1。如果需要缩小,则动态计算并设置inSampleSize的值,对图片进行缩小。需要注意的是,在下次使用BitmapFactory的decodeFile()等方法实例化Bitmap对象前,别忘记将opts.inJustDecodeBound设置回false。否则获取的bitmap对象还是null
61+
在实际项目中,可以利用上面的代码,先获取图片真实的宽度和高度,然后判断是否需要缩小。如果不需要缩小,设置inSampleSize的值为1。如果需要缩小,则动态计算并设置inSampleSize的值,对图片进行缩小。需要注意的是,在下次使用BitmapFactory的decodeFile()等方法实例化Bitmap对象前,别忘记将opts.inJustDecodeBound设置回false。否则获取的bitmap对象还是null
6262

6363
以从Gallery获取一个图片为例讲解缩放:
6464
```java
@@ -134,4 +134,4 @@ Bitmap优化
134134
---
135135

136136
- 邮箱 :charon.chui@gmail.com
137-
- Good Luck!
137+
- Good Luck!

BasicKnowledge/Fragment专题.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,4 +334,4 @@ public abstract class BaseFragment extends Fragment {
334334
---
335335

336336
- 邮箱 :charon.chui@gmail.com
337-
- Good Luck!
337+
- Good Luck!

BasicKnowledge/Scroller简介.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ Scroller简介
2929
public void computeScroll() {
3030
}
3131
```
32-
通过注释我们可以看到该方法又父类调用根据滚动的值去更新`View`,在使用`Scroller`的时候通常都要实现该方法。来达到子`View`的滚动效果。
33-
继续往下跟发现在`draw()`方法中回去调用`computeScroll()`,而`draw()`方法会在父布局调用`drawChild()`的时候使用。
32+
通过注释我们可以看到该方法由父类调用根据滚动的值去更新`View`,在使用`Scroller`的时候通常都要实现该方法。来达到子`View`的滚动效果。
33+
继续往下跟发现在`draw()`方法中会去调用`computeScroll()`,而`draw()`方法会在父布局调用`drawChild()`的时候使用。
3434

3535
3. 具体关联
3636
通过上面两步大体能得到`Scroller`与`View`的移动要通过`computeScroll()`来完成,但是在究竟如何进行代码实现。

JavaKnowledge/Java内存模型.md

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ Stack Memory、Method Area、PC、Native Stack Memory),这些区域都有各
2828
- 堆内存在JVM启动的时候被加载(初始大小: -Xms)
2929
- 堆内存在程序运行时会增加或减少
3030
- 最小值: -Xmx
31-
- 从结构上来分,可以分为新生代和老年代。而新生代又可以分为Eden空间、From Survivor空间(s0)、To Survivor空间(s1)。 所有新生成的对象首先
32-
都是放在新生代的。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来的对象,和从前一个Survivor复制
33-
过来的对象,而复制到老年代的只有从第一个Survivor区过来的对象。而且,Survivor区总有一个是空的。
31+
- 从结构上来分,可以分为新生代和老年代。而新生代又可以分为Eden空间、From Survivor空间(s0)、To Survivor空间(s1)。 所有新生成的对象首先都是放在新生代的。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来的对象,和从前一个Survivor复制过来的对象,而复制到老年代的只有从第一个Survivor区过来的对象。而且,Survivor区总有一个是空的。
3432

35-
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/jvm_heap_memory.png)
33+
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/jvm_heap_memory.png)
3634

3735
在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步?在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的。
3836

@@ -44,10 +42,9 @@ Stack Memory、Method Area、PC、Native Stack Memory),这些区域都有各
4442

4543
每当一个方法执行完成时,该栈帧就会弹出栈帧的元素作为这个方法的返回值,并且清除这个栈帧,Java栈的栈顶的栈帧就是当前正在执行的活动栈,也就是当前正在执行的方法,PC寄存器也会指向该地址。只有这个活动的栈帧的本地变量可以被操作栈使用,当在这个栈帧中调用另外一个方法时,与之对应的一个新的栈帧被创建,这个新创建的栈帧被放到Java栈的栈顶,变为当前的活动栈。同样现在只有这个栈的本地变量才能被使用,当这个栈帧中所有指令都完成时,这个栈帧被移除Java栈,刚才的那个栈帧变为活动栈帧,前面栈帧的返回值变为这个栈帧的操作栈的一个操作数。
4644

47-
48-
4945
线程stack中同样会包含该线程调用栈中所有方法执行所需要的本地变量,一个线程只能获取到它自己对应的线程stack。一个线程创建的本地变量对于其他任何线程都是不可见的。即使两个线程执行完全相同的代码,这两个线程仍然会在各自自己对应的线程stack中创建自己的本地变量。
5046
所有基础类型的局部变量(boolean,byte,short,char,int,long,float,double)都被保存在自己的线程stack中。一个线程可以将一个基础变量的副本传递给另一个线程,但是它不能共享原始局部变量本身。
47+
5148
堆内存包含在Java应用程序中创建的所有对象,而不管创建该对象的线程是什么。这包括基本类型的对象版本(例如Byte,Integer,Long等)。创建对象并将其分配给局部变量,或者将其创建为另一个对象的成员变量都没有关系,该对象仍存储在堆中。
5249
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/java-memory-model-1.png)
5350

@@ -60,12 +57,10 @@ Stack Memory、Method Area、PC、Native Stack Memory),这些区域都有各
6057
- 静态类变量也与类定义一起存储在堆中。
6158
- 引用对象的所有线程都可以访问堆上的对象。当线程可以访问对象时,它也可以访问该对象的成员变量。如果两个线程同时在同一个对象上调用一个方法,则它们都将有权访问该对象的成员变量,但是每个线程将拥有自己的局部变量副本。
6259

63-
64-
6560
Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError:
6661

6762
- StackOverFlowError: 若Java虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前Java虚拟机栈的最大深度的时候,就抛出StackOverFlowError异常。
68-
- OutOfMemoryError: 若 Java 虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError异常。
63+
- OutOfMemoryError: 若Java虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出OutOfMemoryError异常。
6964

7065
## Method Area
7166

@@ -91,8 +86,6 @@ Java 虚拟机栈会出现两种异常:StackOverFlowError 和 OutOfMemoryError
9186

9287
常量池中存储了如字符串、final变量值、类名和方法名常量。常量池在编译期间就被确定,并保存在已编译的.class文件中。一般分为两类:字面量和应用量。字面量就是字符串、final变量等。类名和方法名属于引用量。引用量最常见的是在调用方法的时候,根据方法名找到方法的引用,并以此定为到函数体进行函数代码的执行。引用量包含:类和接口的权限定名、字段的名称和描述符,方法的名称和描述符。
9388

94-
95-
9689
JVM会加载、链接、初始化class文件。一个class文件会把其所有所有符号引用都保留在一个位置,即常量池中。
9790

9891
每个class文件都会有一个对应constant pool。但是class文件中的常量池显然是不够的,因为需要再JVM上执行。这种情况下,需要runtime constant pool来服务JVM的运行。
@@ -136,21 +129,17 @@ Double i4 = 1.2;
136129
System.out.println(i3 == i4);// 输出false
137130
```
138131

139-
140-
141132
### Method Area & Constant Pool改动
142133

143134
很多人愿意把方法区称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot虚拟机的设计团队选择把GC 分代收集扩展至方法区,或者说使用永久代来实现方法区而已。对于其他虚拟机(如BEA JRockit、IBM J9 等)来说是不存在永久代的概念的。
144135

145-
146-
147136
在JDK1.7中,将字符串常量池和静态变量从方法区域中移到堆中,其余的运行时常量池仍在方法区域中,即hotspot中的永久生成。 所有的被intern的String被存储在PermGen区.PermGen区使用-XX:MaxPermSize=N来设置最大大小,但是由于应用程序string.intern通常是不可预测和不可控的,因此不好设置这个大小。设置不好的话,常常会引起java.lang.OutOfMemoryError: PermGen space。
148137

149138
![](https://raw.githubusercontent.com/CharonChui/Pictures/master/java7_method_constant_pool.jpg)
150139

151140
在 JDK 1.8中移除整个永久代,取而代之的是一个叫元空间(Metaspace)的区域(永久代使用的是JVM的堆内存空间,而元空间使用的是物理内存,直接受到本机的物理内存限制)。string constant pool仍然还是在Heap内存中。runtime constant pool也仍然在方法区。但是方法区的实现已经改成使用Metaspace。 ![](https://raw.githubusercontent.com/CharonChui/Pictures/master/java8_memory_method.jpg)
152141

153-
为什么要移除永久代,改为元空间嗯
142+
为什么要移除永久代,改为元空间呢
154143

155144
> Metaspace与PermGen之间最大的区别在于:Metaspace并不在虚拟机中,而是使用本机内存。如果没有使用-XX:MaxMetaspaceSize来设置类的元数据的大小,其最大可利用空间是整个系统内存的可用空间。JVM也可以增加本地内存空间来满足类元数据信息的存储。
156145
> 但是如果没有设置最大值,则可能存在bug导致Metaspace的空间在不停的扩展,会导致机器的内存不足;进而可能出现swap内存被耗尽;最终导致进程直接被系统直接kill掉。
@@ -161,10 +150,6 @@ System.out.println(i3 == i4);// 输出false
161150

162151
在很大程度上,这只是名称的更改。早在引入PermGen时,就没有Java EE或动态类的加载(取消加载),因此,一旦加载了一个类,该类便一直停留在内存中,直到JVM关闭为止,从而实现了永久生成。如今,可以在JVM的生命周期内加载和卸载类,因此对于保留元数据的区域,Metaspace更有意义。
163152

164-
165-
166-
167-
168153
## Native Method Stack
169154

170155
本地方法栈和Java栈所发挥的作用非常相似,区别不过是Java栈为JVM执行Java方法服务,而本地方法栈为JVM执行Native方法服务。如Java使用c或c++编写的接口服务时,代码在此区运行,本地方法栈也会抛出StackOverflowError和OutOfMemoryError异常。
@@ -190,7 +175,6 @@ Java线程之间的通信由Java内存模型(JMM)控制,JMM决定一个线程
190175

191176
## 重排
192177

193-
194178
在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序。
195179

196180
这里说的重排序可以发生在好几个地方:编译器、运行时、JIT等,比如编译器会觉得把一个变量的写操作放在最后会更有效率,编译后,这个指令就在最后了(前提是只要不改变程序的语义,编译器、执行器就可以这样自由的随意优化),一旦编译器对某个变量的写操作进行优化(放到最后),那么在执行之前,另一个线程将不会看到这个执行结果。
@@ -213,8 +197,6 @@ Class Reordering {
213197
```
214198
假设这段代码有2个线程并发执行,线程A执行writer方法,线程B执行reader方法,线程B看到y的值为2,因为把y设置成2发生在变量x的写入之后(代码层面),所以能断定线程B这时看到的x就是1吗?
215199

216-
217-
218200
当然不行!因为在writer方法中,可能发生了重排序,y的写入动作可能发在x写入之前,这种情况下,线程B就有可能看到x的值还是0。
219201

220202
在Java内存模型中,描述了在多线程代码中,哪些行为是正确的、合法的,以及多线程之间如何进行通信,代码中变量的读写行为如何反应到内存、CPU缓存的底层细节。
@@ -250,7 +232,6 @@ a是在栈内存中的,当main()方法执行结束,a就被清理了。但是
250232
- [Where Has the Java PermGen Gone?](https://www.infoq.com/articles/Java-PERMGEN-Removed/)
251233

252234

253-
254235
---
255236
- 邮箱 :charon.chui@gmail.com
256237
- Good Luck!

0 commit comments

Comments
 (0)