Java Internal

Java 常用类的代码实现

Vector:

1
2
3
4
5
6
7
8
9
/**
* 底层存储
*/
protected Object[] elementData;

/**
* 动态扩展 (浅拷贝)
*/
elementData = Arrays.copyOf(elementData, newCapacity);

TreeSet:

基于 TreeMap 实现的,根据元素的自然顺序 Comparable 进行排序。对于基本操作 addremovecontains 保证 log(n) 的时间复杂度。

1
2
3
4
5
6
7
8
9
/**
* 底层存储
*/
private transient NavigableMap<E,Object> m;

/**
* Key 所关联的 Value
*/
private static final Object PRESENT = new Object();

TreeMap:

基于红黑树实现的,红黑树是 AVL 树的一种变种,其执行插入所需要的开销相对较低,再有就是实践中发生的旋转相对较少。根据元素的自然顺序 Comparable 进行排序。对于基本操作 containsKeygetputremove 保证 log(n) 的时间复杂度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 节点定义
*/
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;
}

/**
* 根节点
*/
private transient Entry<K,V> root;

插入操作,最终目标是保证它的父节点是黑色的,而它本身是红色的。我们可以用颜色的改变和树的旋转来帮助我们完成这个目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 插入值
*/
public V put(K key, V value) {
Entry<K,V> t = root;

// 根节点
if (t == null) {
root = new Entry<>(key, value, null);
return null;
}

// 寻找 parent
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);

// 新项作为树叶放入树中,小于就设置为左孩子,大于就设置为右孩子
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;

// 插入之后进行调整
fixAfterInsertion(e);
}

取值操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
final Entry<K,V> getEntry(Object key) {
Comparable<? super K> k = (Comparable<? super K>) key;

// 一个一个对比
Entry<K,V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}

return null;
}

是否包含 key:

1
2
3
public boolean containsKey(Object key) {
return getEntry(key) != null;
}

JUC

IO

NIO

Reflect

Proxy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Proxy.java

/** parameter types of a proxy class constructor */
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };

public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{

final Class<?>[] intfs = interfaces.clone();

/*
* 获取或者生成代理类
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);

/*
* 获取代理类的构造方法
*
* Invoke its constructor with the designated invocation handler.
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
return cons.newInstance(new Object[]{h});
}

getProxyClass0 会查看缓存或者创建一个代理类:

1
2
3
4
5
6
7
8
// Proxy.java
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}

proxyClassCache 是定义在 Proxy 类里面的一个代理类缓存:

1
2
3
4
5
/**
* a cache of proxy classes
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

WeakCache.get() 会首先尝试从缓存中查找代理类,如果查找不到,则会创建 Factory 对象并调用 get() 方法获取代理类。

Factory.get() 方法会调用 ProxyClassFactory.apply() 方法创建并加载代理类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Proxy.ProxyClassFactory
*/
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

// 最终的包名: com.sun.proxy + $Proxy + 0
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;

// 生成 byte,写入文件
byte[] proxyClassFile = ProxyGenerator
.generateProxyClass(proxyName, interfaces, accessFlags);

// 加载代理类 (native 方法)
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}

再看 ProxyGenerator.generateProxyClass 的反编译代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ProxyGenerator.class

private static final boolean saveGeneratedFiles =
((Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();

public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();

// 需要保存文件
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
// 路径为: com/sun/proxy/$Proxy0.class
var2 = Paths.get(var0 + ".class");
}

Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}

return var4;
}

由上面代码我们可以看出来,通过在生成代理类之前,加入如下这么一句话,就能保存下来这个代理类文件:

Proxy0.class

这个文件的路径,就在项目的根路径下面:

paths

以下代码是在 idea 中双击 Proxy0.class 反编译后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.buptnsrc.search.crawl.Car.IHello;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements IHello {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;

public $Proxy0(InvocationHandler var1) throws {
super(var1);
}

public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}

public final void sayHello() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

public final int hashCode() throws {
try {
return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.buptnsrc.search.crawl.Car$IHello").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}

推荐文章