View Javadoc
1   /*
2    * Copyright 2025 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package io.netty.util.internal;
18  
19  import java.lang.invoke.MethodHandle;
20  import java.lang.invoke.MethodHandles;
21  import java.lang.invoke.MethodType;
22  import java.lang.invoke.VarHandle;
23  import java.nio.ByteOrder;
24  
25  final class VarHandleFactory {
26  
27      private VarHandleFactory() {
28      }
29  
30      private static final MethodHandle FIND_VAR_HANDLE;
31      private static final MethodHandle PRIVATE_LOOKUP_IN;
32      private static final VarHandle LONG_LE_ARRAY_VIEW;
33      private static final VarHandle LONG_BE_ARRAY_VIEW;
34      private static final VarHandle INT_LE_ARRAY_VIEW;
35      private static final VarHandle INT_BE_ARRAY_VIEW;
36      private static final VarHandle SHORT_LE_ARRAY_VIEW;
37      private static final VarHandle SHORT_BE_ARRAY_VIEW;
38      private static final VarHandle LONG_LE_BYTE_BUFFER_VIEW;
39      private static final VarHandle LONG_BE_BYTE_BUFFER_VIEW;
40      private static final VarHandle INT_LE_BYTE_BUFFER_VIEW;
41      private static final VarHandle INT_BE_BYTE_BUFFER_VIEW;
42      private static final VarHandle SHORT_LE_BYTE_BUFFER_VIEW;
43      private static final VarHandle SHORT_BE_BYTE_BUFFER_VIEW;
44      private static final Throwable UNAVAILABILITY_CAUSE;
45  
46      static {
47          MethodHandle findVarHandle = null;
48          MethodHandle privateLookupIn = null;
49          VarHandle longLeArrayViewHandle = null;
50          VarHandle longBeArrayViewHandle = null;
51          VarHandle intLeArrayViewHandle = null;
52          VarHandle intBeArrayViewHandle = null;
53          VarHandle shortLeArrayViewHandle = null;
54          VarHandle shortBeArrayViewHandle = null;
55          VarHandle longLeByteBufferViewHandle = null;
56          VarHandle longBeByteBufferViewHandle = null;
57          VarHandle intLeByteBufferViewHandle = null;
58          VarHandle intBeByteBufferViewHandle = null;
59          VarHandle shortLeByteBufferViewHandle = null;
60          VarHandle shortBeByteBufferViewHandle = null;
61          Throwable error = null;
62          try {
63              MethodHandles.Lookup lookup = MethodHandles.lookup();
64              findVarHandle = lookup.findVirtual(MethodHandles.Lookup.class, "findVarHandle",
65                      MethodType.methodType(VarHandle.class, Class.class, String.class, Class.class));
66              privateLookupIn = lookup.findStatic(MethodHandles.class, "privateLookupIn",
67                      MethodType.methodType(MethodHandles.Lookup.class, Class.class, MethodHandles.Lookup.class));
68              MethodHandle byteArrayViewHandle = lookup.findStatic(MethodHandles.class, "byteArrayViewVarHandle",
69                      MethodType.methodType(VarHandle.class, Class.class, ByteOrder.class));
70              longLeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(long[].class, ByteOrder.LITTLE_ENDIAN);
71              longBeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(long[].class, ByteOrder.BIG_ENDIAN);
72              intLeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(int[].class, ByteOrder.LITTLE_ENDIAN);
73              intBeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(int[].class, ByteOrder.BIG_ENDIAN);
74              shortLeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(
75                      short[].class, ByteOrder.LITTLE_ENDIAN);
76              shortBeArrayViewHandle = (VarHandle) byteArrayViewHandle.invokeExact(short[].class, ByteOrder.BIG_ENDIAN);
77              MethodHandle byteBufferViewHandle = lookup.findStatic(MethodHandles.class, "byteBufferViewVarHandle",
78                      MethodType.methodType(VarHandle.class, Class.class, ByteOrder.class));
79              longLeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
80                      long[].class, ByteOrder.LITTLE_ENDIAN);
81              longBeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
82                      long[].class, ByteOrder.BIG_ENDIAN);
83              intLeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
84                      int[].class, ByteOrder.LITTLE_ENDIAN);
85              intBeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
86                      int[].class, ByteOrder.BIG_ENDIAN);
87              shortLeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
88                      short[].class, ByteOrder.LITTLE_ENDIAN);
89              shortBeByteBufferViewHandle = (VarHandle) byteBufferViewHandle.invokeExact(
90                      short[].class, ByteOrder.BIG_ENDIAN);
91              error = null;
92          } catch (Throwable e) {
93              error = e;
94              findVarHandle = null;
95              privateLookupIn = null;
96              longLeArrayViewHandle = null;
97              longBeArrayViewHandle = null;
98              intLeArrayViewHandle = null;
99              intBeArrayViewHandle = null;
100             shortLeArrayViewHandle = null;
101             longLeByteBufferViewHandle = null;
102             longBeByteBufferViewHandle = null;
103             intLeByteBufferViewHandle = null;
104             intBeByteBufferViewHandle = null;
105             shortLeByteBufferViewHandle = null;
106             shortBeByteBufferViewHandle = null;
107         } finally {
108             FIND_VAR_HANDLE = findVarHandle;
109             PRIVATE_LOOKUP_IN = privateLookupIn;
110             LONG_LE_ARRAY_VIEW = longLeArrayViewHandle;
111             LONG_BE_ARRAY_VIEW = longBeArrayViewHandle;
112             INT_LE_ARRAY_VIEW = intLeArrayViewHandle;
113             INT_BE_ARRAY_VIEW = intBeArrayViewHandle;
114             SHORT_LE_ARRAY_VIEW = shortLeArrayViewHandle;
115             SHORT_BE_ARRAY_VIEW = shortBeArrayViewHandle;
116             LONG_LE_BYTE_BUFFER_VIEW = longLeByteBufferViewHandle;
117             LONG_BE_BYTE_BUFFER_VIEW = longBeByteBufferViewHandle;
118             INT_LE_BYTE_BUFFER_VIEW = intLeByteBufferViewHandle;
119             INT_BE_BYTE_BUFFER_VIEW = intBeByteBufferViewHandle;
120             SHORT_LE_BYTE_BUFFER_VIEW = shortLeByteBufferViewHandle;
121             SHORT_BE_BYTE_BUFFER_VIEW = shortBeByteBufferViewHandle;
122             UNAVAILABILITY_CAUSE = error;
123         }
124     }
125 
126     public static boolean isSupported() {
127         return UNAVAILABILITY_CAUSE == null;
128     }
129 
130     public static Throwable unavailableCause() {
131         return UNAVAILABILITY_CAUSE;
132     }
133 
134     private static MethodHandles.Lookup privateLookup(MethodHandles.Lookup lookup, Class<?> targetClass) {
135         try {
136             return (MethodHandles.Lookup) PRIVATE_LOOKUP_IN.invokeExact(targetClass, lookup);
137         } catch (Throwable e) {
138             throw new RuntimeException(e);
139         }
140     }
141 
142     public static VarHandle privateFindVarHandle(MethodHandles.Lookup lookup, Class<?> declaringClass,
143                                                  String name, Class<?> type) {
144         try {
145             return (VarHandle) FIND_VAR_HANDLE.invokeExact(privateLookup(lookup, declaringClass),
146                     declaringClass, name, type);
147         } catch (Throwable e) {
148             throw new RuntimeException(e);
149         }
150     }
151 
152     public static VarHandle longLeArrayView() {
153         return LONG_LE_ARRAY_VIEW;
154     }
155 
156     public static VarHandle longBeArrayView() {
157         return LONG_BE_ARRAY_VIEW;
158     }
159 
160     public static VarHandle intLeArrayView() {
161         return INT_LE_ARRAY_VIEW;
162     }
163 
164     public static VarHandle intBeArrayView() {
165         return INT_BE_ARRAY_VIEW;
166     }
167 
168     public static VarHandle shortLeArrayView() {
169         return SHORT_LE_ARRAY_VIEW;
170     }
171 
172     public static VarHandle shortBeArrayView() {
173         return SHORT_BE_ARRAY_VIEW;
174     }
175 
176     public static VarHandle longLeByteBufferView() {
177         return LONG_LE_BYTE_BUFFER_VIEW;
178     }
179 
180     public static VarHandle longBeByteBufferView() {
181         return LONG_BE_BYTE_BUFFER_VIEW;
182     }
183 
184     public static VarHandle intLeByteBufferView() {
185         return INT_LE_BYTE_BUFFER_VIEW;
186     }
187 
188     public static VarHandle intBeByteBufferView() {
189         return INT_BE_BYTE_BUFFER_VIEW;
190     }
191 
192     public static VarHandle shortLeByteBufferView() {
193         return SHORT_LE_BYTE_BUFFER_VIEW;
194     }
195 
196     public static VarHandle shortBeByteBufferView() {
197         return SHORT_BE_BYTE_BUFFER_VIEW;
198     }
199 }