8000 Merge branch 'JavaCourse00:main' into main · gitot/JavaCourseCodes@cd3ecf6 · GitHub 8000
[go: up one dir, main page]

Skip to content

Commit cd3ecf6

Browse files
authored
Merge branch 'JavaCourse00:main' into main
2 parents bc8eac9 + e84d39f commit cd3ecf6

File tree

244 files changed

+8933
-305
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

244 files changed

+8933
-305
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ hs_err_pid*
2424
*.iml
2525
*.idea/
2626

27+
out/
2728
classes/
2829
target/
2930
build/

01jvm/AnalysisForList.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
public class AnalysisForList {
2+
3+
private int[] array = new int[] {1,2,3};
4+
5+
public void testFor() {
6+
for (int i : array) {
7+
System.out.println(i);
8+
}
9+
}
10+
11+
public void testForIndex() {
12+
for (int i=0;i<array.length;i++) {
13+
System.out.println(array[i]);
14+
}
15+
}
16+
17+
public void testForIndex01() {
18+
int len = array.length;
19+
for (int i=0;i<len;i++) {
20+
System.out.println(array[i]);
21+
}
22+
}
23+
24+
}

01jvm/HelloByteCode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class HelloByteCode {
2+
3+
public static void main(String[] args) {
4+
System.out.println(new HelloByteCode());
5+
}
6+
7+
}

01jvm/HelloNum.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public class HelloNum {
2+
public static void main(String[] args) {
3+
int num1 = 1; // 字面量1;
4+
double num2 = 2.0D; // 大小写的D都可以
5+
long num3 = 3L; // 大小写的L都可以, 加L是好习惯;
6+
byte num4 = 4; // 可以直接赋予 [-128, 127] 范围内的字面量;
7+
if ("".length() < 10) {
8+
// 错误用法: num2 + num3 = 2.03
9+
System.out.println("错误用法: num2 + num3 = " + num2 + num3);
10+
}
11+
for (int i = 0; i < num1; i++) {
12+
// 四则运算: num1 * num4 = 4
13+
System.out.print("四则运算: num1 * num4 = ");
14+
System.out.println(num1 * num4);
15+
}
16+
}
17+
}

01jvm/JvmClassLoaderPrintPath.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import java.lang.reflect.Field;
2+
import java.net.URL;
3+
import java.net.URLClassLoader;
4+
import java.util.List;
5+
6+
public class JvmClassLoaderPrintPath {
7+
8+
public static void main(String[] args) {
9+
10+
// 启动类加载器
11+
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
12+
System.out.println("启动类加载器");
13+
for (URL url : urls) {
14+
System.out.println(" ===> " + url.toExternalForm());
15+
}
16+
17+
// 扩展类加载器
18+
printClassloader("扩展类加载器",JvmClassLoaderPrintPath.class.getClassLoader().getParent());
19+
20+
// 应用类加载器
21+
printClassloader("应用类加载器",JvmClassLoaderPrintPath.class.getClassLoader());
22+
23+
}
24+
25+
private static void printClassloader(String name, ClassLoader classLoader) {
26+
System.out.println();
27+
if (null != classLoader) {
28+
System.out.println(name + " Classloader -> " + classLoader.toString());
29+
printURLForClassloader(classLoader);
30+
} else {
31+
System.out.println(name + " Classloader -> null");
32+
}
33+
}
34+
35+
private static void printURLForClassloader(ClassLoader classLoader) {
36+
Object ucp = insightField(classLoader,"ucp");
37+
Object path = insightField(ucp,"path");
38+
List paths = (List) path;
39+
for (Object p : paths) {
40+
System.out.println(" ===> " + p.toString());
41+
}
42+
}
43+
44+
private static Object insightField(Object obj, String fName) {
45+
Field f = null;
46+
try {
47+
if (obj instanceof URLClassLoader) {
48+
f = URLClassLoader.class.getDeclaredField(fName);
49+
} else {
50+
f = obj.getClass().getDeclaredField(fName);
51+
}
52+
f.setAccessible(true);
53+
return f.get(obj);
54+
}
55+
catch (Exception ex) {
56+
ex.printStackTrace();
57+
}
58+
return null;
59+
}
60+
61+
62+
}

01jvm/README.md

Lines changed: 116 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
## 作业内容
77

88

9-
> Week01 作业题目(周四)
9+
> Week01 作业题目:
1010
11-
1.(选做)自己写一个简单的 Hello.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。
11+
1.(必做)自己写一个简单的 HelloNum.java,里面需要涉及基本类型,四则运行,if 和 for,然后自己分析一下对应的字节码,有问题群里讨论。
1212

1313
2.(必做)自定义一个 Classloader,加载一个 Hello.xlass 文件,执行 hello 方法,此文件内容是一个 Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。
1414

@@ -18,24 +18,132 @@
1818

1919
注意:如果没有线上系统,可以自己 run 一个 web/java 项目。
2020

21-
> Week01 作业题目(周六):
21+
5.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。
2222

23-
1.(选做)本机使用 G1 GC 启动一个程序,仿照课上案例分析一下 JVM 情况。
2423

2524

2625
## 操作步骤
2726

2827

29-
### 作业2
28+
### 作业1(必做)
29+
30+
1. 编写代码, 根据自己的意愿随意编写, 可参考: [HelloNum.java](./HelloNum.java)
31+
2. 编译代码, 执行命令: `javac -g HelloNum.java`
32+
3. 查看反编译的代码。
33+
- 3.1 可以安装并使用idea的jclasslib插件, 选中 [HelloNum.java](./HelloNum.java) 文件, 选择 `View --> Show Bytecode With jclasslib` 即可。
34+
- 3.2 或者直接通过命令行工具 javap, 执行命令: `javap -v HelloNum.class`
35+
4. 分析相关的字节码。【此步骤需要各位同学自己进行分析】
36+
37+
38+
### 作业2(必做)
3039

3140
1. 打开 Spring 官网: https://spring.io/
3241
2. 找到 Projects --> Spring Initializr: https://start.spring.io/
3342
3. 填写项目信息, 生成 maven 项目; 下载并解压。
3443
4. Idea或者Eclipse从已有的Source导入Maven项目。
35-
5. 增加课程资源 Hello.xlass 文件到 src/main/resources 目录。
36-
6. 编写代码,实现 findClass 方法,解码方法
44+
5. 从课件资料中找到资源 Hello.xlass 文件并复制到 src/main/resources 目录。
45+
6. 编写代码,实现 findClass 方法,以及对应的解码方法
3746
7. 编写main方法,调用 loadClass 方法;
3847
8. 创建实例,以及调用方法
3948
9. 执行.
4049

41-
具体的参见: [https://github.com/renfufei/JAVA-000/blob/main/Week_01/homework01/src/main/java/com/renfufei/homework01/XlassLoader.java](XlassLoader.java)
50+
具体代码可参考: [XlassLoader.java](./XlassLoader.java)
51+
52+
53+
### 作业3(必做)
54+
55+
对应的图片需要各位同学自己绘制,可以部分参考PPT课件。
56+
57+
提示:
58+
59+
- Xms 设置堆内存的初始值
60+
- Xmx 设置堆内存的最大值
61+
- Xmn 设置堆内存中的年轻代的最大值
62+
- Meta 区不属于堆内存, 归属为非堆
63+
- DirectMemory 直接内存, 属于 JVM 内存中开辟出来的本地内存空间。
64+
- Xss设置的是单个线程栈的最大空间;
65+
66+
JVM进程空间中的内存一般来说包括以下这些部分:
67+
68+
- 堆内存(Xms ~ Xmx) = 年轻代(~Xmn) + 老年代
69+
- 非堆 = Meta + CodeCache + ...
70+
- Native内存 = 直接内存 + Native + ...
71+
- 栈内存 = n * Xss
72+
73+
另外,注意区分规范与实现的区别, 需要根据具体实现以及版本, 才能确定。 一般来说,我们的目的是为了排查故障和诊断问题,大致弄清楚这些参数和空间的关系即可。 具体设置时还需要留一些冗余量。
74+
75+
76+
### 4.(选做)
77+
78+
这个是具体案例分析, 请各位同学自己分析。
79+
80+
比如我们一个生产系统应用的启动参数为:
81+
82+
```
83+
JAVA_OPTS=-Xmx200g -Xms200g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZCollectionInterval=30 -XX:ZAllocationSpikeTolerance=5 -XX:ReservedCodeCacheSize=2g -XX:InitialCodeCacheSize=2g -XX:ConcGCThreads=8 -XX:ParallelGCThreads=16
84+
```
85+
86+
另一个系统的启动参数为:
87+
88+
```
89+
JAVA_OPTS=-Xmx4g -Xms4g -XX:+UseG1GC -XX:MaxGCPauseMillis=50
90+
```
91+
92+
具体如何设置, 需要考虑的因素包括:
93+
94+
- 系统容量: 业务规模, 并发, 成本预算; 需要兼顾性能与成本;
95+
- 延迟要求: 最坏情况下能接受多少时间的延迟尖刺。
96+
- 吞吐量: 根据业务特征来确定, 比如, 网关, 大数据底层平台, 批处理作业系统, 在线实时应用, 他们最重要的需求不一样。
97+
- 系统架构: 比如拆分为小内存更多节点, 还是大内存少量节点。
98+
- 其他...
99+
100+
101+
### 5.(选做)
102+
103+
例如使用以下命令:
104+
105+
```
106+
# 编译
107+
javac -g GCLogAnalysis.java
108+
# JDK8 启动程序
109+
java -Xmx2g -Xms2g -XX:+UseG1GC -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:gc.log GCLogAnalysis
110+
```
111+
112+
尝试使用课程中介绍的各种工具JDK命令行和图形工具来进行分析。
113+
114+
其中 [GCLogAnalysis.java](./GCLogAnalysis.java) 文件也可以从课件资料zip中找到.
115+
116+
## 几个命令用法
117+
### 1、十六进制方式查看文件
118+
`hexdump -C Hello.class`
119+
输出:`00000000 ca fe ba be 00 00 00 34 00 1c 0a 00 06 00 0e 09`
120+
121+
可以看到magic number: `cafe babe`
122+
以及`00 00 00 34`,十六进制34=十进制3*16+4=52,这是jdk8,如果是jdk11则是55,十六进制37.
123+
124+
### 2、Base64方式编码文件
125+
`base64 Hello.class`
126+
### 3、显示JVM默认参数
127+
```
128+
java -XX:+PrintFlagsFinal -version
129+
130+
java -XX:+PrintFlagsFinal -version | grep -F " Use" | grep -F "GC "
131+
132+
java -XX:+PrintFlagsFinal -version | grep MaxNewSize
133+
134+
```
135+
136+
### 4、切换不同jdk
137+
```
138+
jenv shell 1.8
139+
jenv shell 11
140+
```
141+
显示所有jdk
142+
```
143+
jenv versions
144+
```
145+
146+
## 更多资料
147+
148+
更多中英文的技术文章和参考资料: <https://github.com/cncounter/translation>
149+

01jvm/TestAddUrl.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
package io.kimmking.kmq;
2-
3-
import lombok.SneakyThrows;
41

52
import java.io.File;
63
import java.lang.reflect.Method;
@@ -9,15 +6,14 @@
96

107
public class TestAddUrl {
118

12-
@SneakyThrows
13-
public static void main(String[] args) {
9+
public static void main(String[] args) throws Exception {
1410
URLClassLoader classLoader = (URLClassLoader) TestAddUrl.class.getClassLoader();
15-
String dir = "/Users/kimmking/Downloads/Hello";
11+
String dir = "./lib";
1612
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
1713
method.setAccessible(true);
18-
method.invoke(classLoader, new File(dir).toURL());
14+
method.invoke(classLoader, new File(dir).getAbsoluteFile().toURL());
1915

20-
Class klass = Class.forName("Hello",true, classLoader);
16+
Class klass = Class.forName("HelloKimmking",true, classLoader);
2117
Object obj = klass.newInstance();
2218
Method hello = klass.getDeclaredMethod("hello");
2319
hello.invoke(obj);

01jvm/XlassLoader.java

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import java.io.Closeable;
2+
import java.io.IOException;
3+
import java.io.InputStream;
4+
import java.lang.reflect.Method;
5+
6+
/*
7+
第一周作业:
8+
2.(必做)自定义一个 Classloader,加载一个 lib.Hello.xlass 文件,执行 hello 方法,此文件内容是一个 lib.Hello.class 文件所有字节(x=255-x)处理后的文件。文件群里提供。
9+
*/
10+
public class XlassLoader extends ClassLoader {
11+
12+
public static void main(String[] args) throws Exception {
13+
// 相关参数
14+
final String packageName = "lib";
15+
final String className = "Hello";
16+
final String methodName = "hello";
17+
// 创建类加载器
18+
ClassLoader classLoader = new XlassLoader();
19+
// 加载相应的类
20+
Class<?> clazz = classLoader.loadClass(packageName + "." + className);
21+
// 看看里面有些什么方法
22+
for (Method m : clazz.getDeclaredMethods()) {
23+
System.out.println(clazz.getSimpleName() + "." + m.getName());
24+
}
25+
// 创建对象
26+
Object instance = clazz.getDeclaredConstructor().newInstance();
27+
// 调用实例方法
28+
Method method = clazz.getMethod(methodName);
29+
method.invoke(instance);
30+
}
31+
32+
@Override
33+
protected Class<?> findClass(String name) throws ClassNotFoundException {
34+
// 如果支持包名, 则需要进行路径转换
35+
String resourcePath = name.replace(".", "/");
36+
// 文件后缀
37+
final String suffix = ".xlass";
38+
// 获取输入流
39+
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(resourcePath + suffix);
40+
try {
41+
// 读取数据
42+
int length = inputStream.available();
43+
byte[] byteArray = new byte[length];
44+
inputStream.read(byteArray);
45+
// 转换
46+
byte[] classBytes = decode(byteArray);
47+
// 通知底层定义这个类
48+
return defineClass(name, classBytes, 0, classBytes.length);
49+
} catch (IOException e) {
50+
throw new ClassNotFoundException(name, e);
51+
} finally {
52+
close(inputStream);
53+
}
54+
}
55+
56+
// 解码
57+
private static byte[] decode(byte[] byteArray) {
58+
byte[] targetArray = new byte[byteArray.length];
59+
for (int i = 0; i < byteArray.length; i++) {
60+
targetArray[i] = (byte) (255 - byteArray[i]);
61+
}
62+
return targetArray;
63+
}
64+
65+
// 关闭
66+
private static void close(Closeable res) {
67+
if (null != res) {
68+
try {
69+
res.close();
70+
} catch (IOException e) {
71+
e.printStackTrace();
72+
}
73+
}
74+
}
75+
}

01jvm/jvm/HelloClassLoader.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package jvm;
2+
3+
import java.util.Base64;
4+
5+
public class HelloClassLoader extends ClassLoader {
6+
7+
public static void main(String[] args) throws Exception {
8+
9+
new HelloClassLoader().findClass("jvm.lib.Hello").newInstance();
10+
}
11+
12+
@Override
13+
protected Class<?> findClass(String name) throws ClassNotFoundException {
14+
String helloBase64 = "yv66vgAAADQAHAoABgAOCQAPABAIABEKABIAEwcAFAcAFQEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAApIZWxsby5qYXZhDAAHAAgHABYMABcAGAEAGEhlbGxvIENsYXNzIEluaXRpYWxpemVkIQcAGQwAGgAbAQAJanZtL0hlbGxvAQAQamF2YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0cmVhbTsBABNqYXZhL2lvL1ByaW50U3RyZWFtAQAHcHJpbnRsbgEAFShMamF2YS9sYW5nL1N0cmluZzspVgAhAAUABgAAAAAAAgABAAcACAABAAkAAAAdAAEAAQAAAAUqtwABsQAAAAEACgAAAAYAAQAAAAMACAALAAgAAQAJAAAAJQACAAAAAAAJsgACEgO2AASxAAAAAQAKAAAACgACAAAABQAIAAYAAQAMAAAAAgAN";
15+
byte[] bytes = decode(helloBase64);
16+
return defineClass(name,bytes,0,bytes.length);
17+
}
18+
19+
public byte[] decode(String base64) {
20+
return Base64.getDecoder().decode(base64);
21+
}
22+
}

0 commit comments

Comments
 (0)
0