-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lazily recompute InetAddress subclasses fields at runtime
- Loading branch information
Showing
5 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
core/runtime/src/main/java/io/quarkus/runtime/graal/CidrAddressSubstitutions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package io.quarkus.runtime.graal; | ||
|
||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.net.InetAddress; | ||
|
||
import org.wildfly.common.net.CidrAddress; | ||
import org.wildfly.common.net.Inet; | ||
|
||
import com.oracle.svm.core.annotate.Alias; | ||
import com.oracle.svm.core.annotate.InjectAccessors; | ||
import com.oracle.svm.core.annotate.TargetClass; | ||
|
||
/* | ||
* The following substitutions are required because of a new restriction in GraalVM 19.3.0 that prohibits the presence of | ||
* java.net.Inet4Address and java.net.Inet6Address in the image heap. Each field annotated with @InjectAccessors is lazily | ||
* recomputed at runtime on first access while CidrAddress.class can still be initialized during the native image build. | ||
*/ | ||
@TargetClass(CidrAddress.class) | ||
final class Target_org_wildfly_common_net_CidrAddress { | ||
|
||
@Alias | ||
@InjectAccessors(Inet4AnyCidrAccessor.class) | ||
public static CidrAddress INET4_ANY_CIDR; | ||
|
||
@Alias | ||
@InjectAccessors(Inet6AnyCidrAccessor.class) | ||
public static CidrAddress INET6_ANY_CIDR; | ||
} | ||
|
||
class Inet4AnyCidrAccessor { | ||
|
||
private static volatile CidrAddress INET4_ANY_CIDR; | ||
|
||
static CidrAddress get() { | ||
CidrAddress result = INET4_ANY_CIDR; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized CidrAddress initializeOnce() { | ||
CidrAddress result = INET4_ANY_CIDR; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = CidrAddressUtil.newInstance(Inet.INET4_ANY, 0); | ||
INET4_ANY_CIDR = result; | ||
return result; | ||
} | ||
} | ||
|
||
class Inet6AnyCidrAccessor { | ||
|
||
private static volatile CidrAddress INET6_ANY_CIDR; | ||
|
||
static CidrAddress get() { | ||
CidrAddress result = INET6_ANY_CIDR; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized CidrAddress initializeOnce() { | ||
CidrAddress result = INET6_ANY_CIDR; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = CidrAddressUtil.newInstance(Inet.INET6_ANY, 0); | ||
INET6_ANY_CIDR = result; | ||
return result; | ||
} | ||
} | ||
|
||
class CidrAddressUtil { | ||
|
||
public static CidrAddress newInstance(InetAddress networkAddress, int netmaskBits) { | ||
try { | ||
Constructor<CidrAddress> ctor = CidrAddress.class.getDeclaredConstructor(InetAddress.class, int.class); | ||
ctor.setAccessible(true); | ||
return ctor.newInstance(networkAddress, netmaskBits); | ||
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | ||
| IllegalArgumentException | InvocationTargetException e) { | ||
throw new RuntimeException("CidrAddress instanciation failed", e); | ||
} | ||
} | ||
} |
164 changes: 164 additions & 0 deletions
164
core/runtime/src/main/java/io/quarkus/runtime/graal/InetSubstitutions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package io.quarkus.runtime.graal; | ||
|
||
import java.net.Inet4Address; | ||
import java.net.Inet6Address; | ||
|
||
import org.wildfly.common.net.Inet; | ||
|
||
import com.oracle.svm.core.annotate.Alias; | ||
import com.oracle.svm.core.annotate.InjectAccessors; | ||
import com.oracle.svm.core.annotate.TargetClass; | ||
|
||
/* | ||
* The following substitutions are required because of a new restriction in GraalVM 19.3.0 that prohibits the presence of | ||
* java.net.Inet4Address and java.net.Inet6Address in the image heap. Each field annotated with @InjectAccessors is lazily | ||
* recomputed at runtime on first access while Inet.class can still be initialized during the native image build. | ||
*/ | ||
@TargetClass(Inet.class) | ||
final class Target_org_wildfly_common_net_Inet { | ||
|
||
@Alias | ||
@InjectAccessors(Inet4AnyAccessor.class) | ||
public static Inet4Address INET4_ANY; | ||
|
||
@Alias | ||
@InjectAccessors(Inet4LoopbackAccessor.class) | ||
public static Inet4Address INET4_LOOPBACK; | ||
|
||
@Alias | ||
@InjectAccessors(Inet4BroadcastAccessor.class) | ||
public static Inet4Address INET4_BROADCAST; | ||
|
||
@Alias | ||
@InjectAccessors(Inet6AnyAccessor.class) | ||
public static Inet6Address INET6_ANY; | ||
|
||
@Alias | ||
@InjectAccessors(Inet6LoopbackAccessor.class) | ||
public static Inet6Address INET6_LOOPBACK; | ||
} | ||
|
||
class Inet4AnyAccessor { | ||
|
||
private static volatile Inet4Address INET4_ANY; | ||
|
||
static Inet4Address get() { | ||
Inet4Address result = INET4_ANY; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized Inet4Address initializeOnce() { | ||
Inet4Address result = INET4_ANY; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = Inet.getInet4Address(0, 0, 0, 0); | ||
INET4_ANY = result; | ||
return result; | ||
} | ||
} | ||
|
||
class Inet4LoopbackAccessor { | ||
|
||
private static volatile Inet4Address INET4_LOOPBACK; | ||
|
||
static Inet4Address get() { | ||
Inet4Address result = INET4_LOOPBACK; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized Inet4Address initializeOnce() { | ||
Inet4Address result = INET4_LOOPBACK; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = Inet.getInet4Address(127, 0, 0, 1); | ||
INET4_LOOPBACK = result; | ||
return result; | ||
} | ||
} | ||
|
||
class Inet4BroadcastAccessor { | ||
|
||
private static volatile Inet4Address INET4_BROADCAST; | ||
|
||
static Inet4Address get() { | ||
Inet4Address result = INET4_BROADCAST; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized Inet4Address initializeOnce() { | ||
Inet4Address result = INET4_BROADCAST; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = Inet.getInet4Address(255, 255, 255, 255); | ||
INET4_BROADCAST = result; | ||
return result; | ||
} | ||
} | ||
|
||
class Inet6AnyAccessor { | ||
|
||
private static volatile Inet6Address INET6_ANY; | ||
|
||
static Inet6Address get() { | ||
Inet6Address result = INET6_ANY; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized Inet6Address initializeOnce() { | ||
Inet6Address result = INET6_ANY; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = Inet.getInet6Address(0, 0, 0, 0, 0, 0, 0, 0); | ||
INET6_ANY = result; | ||
return result; | ||
} | ||
} | ||
|
||
class Inet6LoopbackAccessor { | ||
|
||
private static volatile Inet6Address INET6_LOOPBACK; | ||
|
||
static Inet6Address get() { | ||
Inet6Address result = INET6_LOOPBACK; | ||
if (result == null) { | ||
// Lazy initialization on first access. | ||
result = initializeOnce(); | ||
} | ||
return result; | ||
} | ||
|
||
private static synchronized Inet6Address initializeOnce() { | ||
Inet6Address result = INET6_LOOPBACK; | ||
if (result != null) { | ||
// Double-checked locking is OK because INSTANCE is volatile. | ||
return result; | ||
} | ||
result = Inet.getInet6Address(0, 0, 0, 0, 0, 0, 0, 1); | ||
INET6_LOOPBACK = result; | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters