Skip to content

Commit 2016eba

Browse files
committed
fix(arc_dns_injector): Fix Java 21
CachedAddresses no longer exists, so we use CachedLookup instead since it's the same class, just renamed. This is horrible but it works so don't blame me
1 parent 66db228 commit 2016eba

2 files changed

Lines changed: 158 additions & 6 deletions

File tree

arc_dns_injector/src/main/java/git/artdeell/arcdns/ArcDNSInjectorAgent.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,23 @@ public static void premain(String args) {
55
System.out.println("Arc Capes DNS Injector");
66
System.out.println("Parts of Alibaba's DCM library were used, please read https://github.com/alibaba/java-dns-cache-manipulator/blob/main/README.md for more info");
77
String[] injectedIps = new String[]{args};
8+
89
try {
9-
CacheUtil_J9.setInetAddressCache("s.optifine.net", injectedIps, CacheUtilCommons.NEVER_EXPIRATION);
10+
CacheUtil_J21.setInetAddressCache("s.optifine.net", injectedIps, CacheUtilCommons.NEVER_EXPIRATION);
1011
} catch (Exception e) {
1112
try {
12-
CacheUtil_J8.setInetAddressCache("s.optifine.net", injectedIps, CacheUtilCommons.NEVER_EXPIRATION);
13+
CacheUtil_J9.setInetAddressCache("s.optifine.net", injectedIps, CacheUtilCommons.NEVER_EXPIRATION);
1314
} catch (Exception e2) {
14-
System.out.println("Failed to inject cache!");
15-
e2.addSuppressed(e);
16-
e2.printStackTrace();
17-
return;
15+
try {
16+
CacheUtil_J8.setInetAddressCache("s.optifine.net", injectedIps, CacheUtilCommons.NEVER_EXPIRATION);
17+
} catch (Exception e3) {
18+
System.out.println("Failed to inject cache!");
19+
e2.addSuppressed(e);
20+
e2.printStackTrace();
21+
e3.addSuppressed(e);
22+
e3.printStackTrace();
23+
return;
24+
}
1825
}
1926
}
2027
System.out.println("Added DNS cache entry: s.optifine.net/"+args);
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package git.artdeell.arcdns;
2+
import static git.artdeell.arcdns.CacheUtilCommons.NEVER_EXPIRATION;
3+
4+
import java.lang.reflect.Constructor;
5+
import java.lang.reflect.Field;
6+
import java.lang.reflect.InvocationTargetException;
7+
import java.net.InetAddress;
8+
import java.net.UnknownHostException;
9+
import java.util.ArrayList;
10+
import java.util.Iterator;
11+
import java.util.List;
12+
import java.util.Map;
13+
import java.util.concurrent.ConcurrentMap;
14+
import java.util.concurrent.ConcurrentSkipListSet;
15+
public class CacheUtil_J21 {
16+
public static void setInetAddressCache(String host, String[] ips, long expireMillis)
17+
throws UnknownHostException, IllegalAccessException, InstantiationException,
18+
InvocationTargetException, ClassNotFoundException, NoSuchFieldException {
19+
long expiration = expireMillis == NEVER_EXPIRATION ? NEVER_EXPIRATION : System.nanoTime() + expireMillis * 1_000_000;
20+
Object cachedAddresses = newCachedAddresses(host, ips, expiration);
21+
22+
getCacheOfInetAddress().put(host, cachedAddresses);
23+
getExpirySetOfInetAddress().add(cachedAddresses);
24+
}
25+
26+
private static Object newCachedAddresses(String host, String[] ips, long expiration)
27+
throws ClassNotFoundException, UnknownHostException, IllegalAccessException,
28+
InvocationTargetException, InstantiationException {
29+
// InetAddress.CachedAddresses has only one constructor
30+
return getConstructorOfInetAddress$CachedAddresses().newInstance(host, CacheUtilCommons.toInetAddressArray(host, ips), expiration);
31+
}
32+
33+
private static volatile Constructor<?> constructorOfInetAddress$CachedAddresses = null;
34+
35+
private static Constructor<?> getConstructorOfInetAddress$CachedAddresses() throws ClassNotFoundException {
36+
if (constructorOfInetAddress$CachedAddresses != null) return constructorOfInetAddress$CachedAddresses;
37+
38+
synchronized (CacheUtilCommons.class) {
39+
// double check
40+
if (constructorOfInetAddress$CachedAddresses != null) return constructorOfInetAddress$CachedAddresses;
41+
42+
final Class<?> clazz = Class.forName(inetAddress$CachedAddresses_ClassName);
43+
44+
// InetAddress.CacheEntry has only one constructor:
45+
//
46+
// - for jdk 9-jdk12, constructor signature is CachedAddresses(String host, InetAddress[] inetAddresses, long expiryTime)
47+
// code in jdk 9:
48+
// https://hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/java.base/share/classes/java/net/InetAddress.java#l783
49+
// code in jdk 11:
50+
// https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/java.base/share/classes/java/net/InetAddress.java#l787
51+
final Constructor<?> constructor = clazz.getDeclaredConstructors()[0];
52+
constructor.setAccessible(true);
53+
54+
constructorOfInetAddress$CachedAddresses = constructor;
55+
return constructor;
56+
}
57+
}
58+
59+
public static void removeInetAddressCache(String host) throws NoSuchFieldException, IllegalAccessException {
60+
getCacheOfInetAddress().remove(host);
61+
removeHostFromExpirySetOfInetAddress(host);
62+
}
63+
64+
/**
65+
* @see #getExpirySetOfInetAddress()
66+
*/
67+
private static void removeHostFromExpirySetOfInetAddress(String host)
68+
throws NoSuchFieldException, IllegalAccessException {
69+
for (Iterator<Object> iterator = getExpirySetOfInetAddress().iterator(); iterator.hasNext(); ) {
70+
Object cachedAddresses = iterator.next();
71+
if (getHostOfInetAddress$CacheAddress(cachedAddresses).equals(host)) {
72+
iterator.remove();
73+
}
74+
}
75+
}
76+
77+
private static volatile Field hostFieldOfInetAddress$CacheAddress = null;
78+
79+
private static String getHostOfInetAddress$CacheAddress(Object cachedAddresses)
80+
throws NoSuchFieldException, IllegalAccessException {
81+
if (hostFieldOfInetAddress$CacheAddress == null) {
82+
synchronized (CacheUtil_J21.class) {
83+
if (hostFieldOfInetAddress$CacheAddress == null) { // double check
84+
final Field f = cachedAddresses.getClass().getDeclaredField("host");
85+
f.setAccessible(true);
86+
hostFieldOfInetAddress$CacheAddress = f;
87+
}
88+
}
89+
}
90+
return (String) hostFieldOfInetAddress$CacheAddress.get(cachedAddresses);
91+
}
92+
93+
94+
//////////////////////////////////////////////////////////////////////////////
95+
// getters of static cache related fields of InetAddress
96+
//////////////////////////////////////////////////////////////////////////////
97+
98+
@SuppressWarnings("unchecked")
99+
private static ConcurrentMap<String, Object> getCacheOfInetAddress()
100+
throws NoSuchFieldException, IllegalAccessException {
101+
return (ConcurrentMap<String, Object>) getCacheAndExpirySetOfInetAddress0()[0];
102+
}
103+
104+
@SuppressWarnings("unchecked")
105+
private static ConcurrentSkipListSet<Object> getExpirySetOfInetAddress()
106+
throws NoSuchFieldException, IllegalAccessException {
107+
return (ConcurrentSkipListSet<Object>) getCacheAndExpirySetOfInetAddress0()[1];
108+
}
109+
110+
private static volatile Object[] ADDRESS_CACHE_AND_EXPIRY_SET = null;
111+
112+
private static Object[] getCacheAndExpirySetOfInetAddress0()
113+
throws NoSuchFieldException, IllegalAccessException {
114+
if (ADDRESS_CACHE_AND_EXPIRY_SET != null) return ADDRESS_CACHE_AND_EXPIRY_SET;
115+
116+
synchronized (CacheUtil_J21.class) {
117+
if (ADDRESS_CACHE_AND_EXPIRY_SET != null) return ADDRESS_CACHE_AND_EXPIRY_SET;
118+
119+
final Field cacheField = InetAddress.class.getDeclaredField("cache");
120+
cacheField.setAccessible(true);
121+
122+
final Field expirySetField = InetAddress.class.getDeclaredField("expirySet");
123+
expirySetField.setAccessible(true);
124+
125+
ADDRESS_CACHE_AND_EXPIRY_SET = new Object[]{
126+
cacheField.get(InetAddress.class),
127+
expirySetField.get(InetAddress.class)
128+
};
129+
130+
return ADDRESS_CACHE_AND_EXPIRY_SET;
131+
}
132+
}
133+
134+
//////////////////////////////////////////////////////////////////////////////
135+
136+
private static final String inetAddress$CachedAddresses_ClassName = "java.net.InetAddress$CachedLookup";
137+
public static void clearInetAddressCache() throws NoSuchFieldException, IllegalAccessException {
138+
getCacheOfInetAddress().clear();
139+
getExpirySetOfInetAddress().clear();
140+
}
141+
142+
private CacheUtil_J21() {
143+
}
144+
145+
}

0 commit comments

Comments
 (0)