133 * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread |
133 * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread |
134 * context class loader at the time of {@link #createLinker()} invocation will be used. |
134 * context class loader at the time of {@link #createLinker()} invocation will be used. |
135 * |
135 * |
136 * @param classLoader the class loader used for the autodiscovery of available linkers. |
136 * @param classLoader the class loader used for the autodiscovery of available linkers. |
137 */ |
137 */ |
138 public void setClassLoader(ClassLoader classLoader) { |
138 public void setClassLoader(final ClassLoader classLoader) { |
139 this.classLoader = classLoader; |
139 this.classLoader = classLoader; |
140 classLoaderExplicitlySet = true; |
140 classLoaderExplicitlySet = true; |
141 } |
141 } |
142 |
142 |
143 /** |
143 /** |
147 * linkers, it will be ignored and the explicit prioritized instance will be used. |
147 * linkers, it will be ignored and the explicit prioritized instance will be used. |
148 * |
148 * |
149 * @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers |
149 * @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers |
150 * (this is also the default value). |
150 * (this is also the default value). |
151 */ |
151 */ |
152 public void setPrioritizedLinkers(List<? extends GuardingDynamicLinker> prioritizedLinkers) { |
152 public void setPrioritizedLinkers(final List<? extends GuardingDynamicLinker> prioritizedLinkers) { |
153 this.prioritizedLinkers = |
153 this.prioritizedLinkers = |
154 prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers); |
154 prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers); |
155 } |
155 } |
156 |
156 |
157 /** |
157 /** |
160 * autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the prioritized |
160 * autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the prioritized |
161 * linkers, it will be ignored and the explicit prioritized instance will be used. |
161 * linkers, it will be ignored and the explicit prioritized instance will be used. |
162 * |
162 * |
163 * @param prioritizedLinkers a list of prioritized linkers. |
163 * @param prioritizedLinkers a list of prioritized linkers. |
164 */ |
164 */ |
165 public void setPrioritizedLinkers(GuardingDynamicLinker... prioritizedLinkers) { |
165 public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) { |
166 setPrioritizedLinkers(Arrays.asList(prioritizedLinkers)); |
166 setPrioritizedLinkers(Arrays.asList(prioritizedLinkers)); |
167 } |
167 } |
168 |
168 |
169 /** |
169 /** |
170 * Sets a single prioritized linker. Identical to calling {@link #setPrioritizedLinkers(List)} with a single-element |
170 * Sets a single prioritized linker. Identical to calling {@link #setPrioritizedLinkers(List)} with a single-element |
171 * list. |
171 * list. |
172 * |
172 * |
173 * @param prioritizedLinker the single prioritized linker. Must not be null. |
173 * @param prioritizedLinker the single prioritized linker. Must not be null. |
174 * @throws IllegalArgumentException if null is passed. |
174 * @throws IllegalArgumentException if null is passed. |
175 */ |
175 */ |
176 public void setPrioritizedLinker(GuardingDynamicLinker prioritizedLinker) { |
176 public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) { |
177 if(prioritizedLinker == null) { |
177 if(prioritizedLinker == null) { |
178 throw new IllegalArgumentException("prioritizedLinker == null"); |
178 throw new IllegalArgumentException("prioritizedLinker == null"); |
179 } |
179 } |
180 this.prioritizedLinkers = Collections.singletonList(prioritizedLinker); |
180 this.prioritizedLinkers = Collections.singletonList(prioritizedLinker); |
181 } |
181 } |
186 * linkers, it will be ignored and the explicit fallback instance will be used. |
186 * linkers, it will be ignored and the explicit fallback instance will be used. |
187 * |
187 * |
188 * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no |
188 * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no |
189 * fallback linkers. |
189 * fallback linkers. |
190 */ |
190 */ |
191 public void setFallbackLinkers(List<? extends GuardingDynamicLinker> fallbackLinkers) { |
191 public void setFallbackLinkers(final List<? extends GuardingDynamicLinker> fallbackLinkers) { |
192 this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers); |
192 this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers); |
193 } |
193 } |
194 |
194 |
195 /** |
195 /** |
196 * Sets the fallback linkers. These linkers will be consulted last in the resulting composite linker, after any |
196 * Sets the fallback linkers. These linkers will be consulted last in the resulting composite linker, after any |
198 * linkers, it will be ignored and the explicit fallback instance will be used. |
198 * linkers, it will be ignored and the explicit fallback instance will be used. |
199 * |
199 * |
200 * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no |
200 * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no |
201 * fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used. |
201 * fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used. |
202 */ |
202 */ |
203 public void setFallbackLinkers(GuardingDynamicLinker... fallbackLinkers) { |
203 public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) { |
204 setFallbackLinkers(Arrays.asList(fallbackLinkers)); |
204 setFallbackLinkers(Arrays.asList(fallbackLinkers)); |
205 } |
205 } |
206 |
206 |
207 /** |
207 /** |
208 * Sets the number of arguments in the call sites that represent the stack context of the language runtime creating |
208 * Sets the number of arguments in the call sites that represent the stack context of the language runtime creating |
212 * advisable to only pass one context-specific argument, though, of an easily recognizable, runtime specific type |
212 * advisable to only pass one context-specific argument, though, of an easily recognizable, runtime specific type |
213 * encapsulating the runtime thread local state. |
213 * encapsulating the runtime thread local state. |
214 * |
214 * |
215 * @param runtimeContextArgCount the number of language runtime context arguments in call sites. |
215 * @param runtimeContextArgCount the number of language runtime context arguments in call sites. |
216 */ |
216 */ |
217 public void setRuntimeContextArgCount(int runtimeContextArgCount) { |
217 public void setRuntimeContextArgCount(final int runtimeContextArgCount) { |
218 if(runtimeContextArgCount < 0) { |
218 if(runtimeContextArgCount < 0) { |
219 throw new IllegalArgumentException("runtimeContextArgCount < 0"); |
219 throw new IllegalArgumentException("runtimeContextArgCount < 0"); |
220 } |
220 } |
221 this.runtimeContextArgCount = runtimeContextArgCount; |
221 this.runtimeContextArgCount = runtimeContextArgCount; |
222 } |
222 } |
225 * Sets whether the linker created by this factory will invoke {@link MutableCallSite#syncAll(MutableCallSite[])} |
225 * Sets whether the linker created by this factory will invoke {@link MutableCallSite#syncAll(MutableCallSite[])} |
226 * after a call site is relinked. Defaults to false. You probably want to set it to true if your runtime supports |
226 * after a call site is relinked. Defaults to false. You probably want to set it to true if your runtime supports |
227 * multithreaded execution of dynamically linked code. |
227 * multithreaded execution of dynamically linked code. |
228 * @param syncOnRelink true for invoking sync on relink, false otherwise. |
228 * @param syncOnRelink true for invoking sync on relink, false otherwise. |
229 */ |
229 */ |
230 public void setSyncOnRelink(boolean syncOnRelink) { |
230 public void setSyncOnRelink(final boolean syncOnRelink) { |
231 this.syncOnRelink = syncOnRelink; |
231 this.syncOnRelink = syncOnRelink; |
232 } |
232 } |
233 |
233 |
234 /** |
234 /** |
235 * Sets the unstable relink threshold; the number of times a call site is relinked after which it will be |
235 * Sets the unstable relink threshold; the number of times a call site is relinked after which it will be |
236 * considered unstable, and subsequent link requests for it will indicate this. |
236 * considered unstable, and subsequent link requests for it will indicate this. |
237 * @param unstableRelinkThreshold the new threshold. Must not be less than zero. The value of zero means that |
237 * @param unstableRelinkThreshold the new threshold. Must not be less than zero. The value of zero means that |
238 * call sites will never be considered unstable. |
238 * call sites will never be considered unstable. |
239 * @see LinkRequest#isCallSiteUnstable() |
239 * @see LinkRequest#isCallSiteUnstable() |
240 */ |
240 */ |
241 public void setUnstableRelinkThreshold(int unstableRelinkThreshold) { |
241 public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) { |
242 if(unstableRelinkThreshold < 0) { |
242 if(unstableRelinkThreshold < 0) { |
243 throw new IllegalArgumentException("unstableRelinkThreshold < 0"); |
243 throw new IllegalArgumentException("unstableRelinkThreshold < 0"); |
244 } |
244 } |
245 this.unstableRelinkThreshold = unstableRelinkThreshold; |
245 this.unstableRelinkThreshold = unstableRelinkThreshold; |
246 } |
246 } |
273 new ArrayList<>(prioritizedLinkers.size() + discovered.size() |
273 new ArrayList<>(prioritizedLinkers.size() + discovered.size() |
274 + fallbackLinkers.size()); |
274 + fallbackLinkers.size()); |
275 // ... prioritized linkers, ... |
275 // ... prioritized linkers, ... |
276 linkers.addAll(prioritizedLinkers); |
276 linkers.addAll(prioritizedLinkers); |
277 // ... filtered discovered linkers, ... |
277 // ... filtered discovered linkers, ... |
278 for(GuardingDynamicLinker linker: discovered) { |
278 for(final GuardingDynamicLinker linker: discovered) { |
279 if(!knownLinkerClasses.contains(linker.getClass())) { |
279 if(!knownLinkerClasses.contains(linker.getClass())) { |
280 linkers.add(linker); |
280 linkers.add(linker); |
281 } |
281 } |
282 } |
282 } |
283 // ... and finally fallback linkers. |
283 // ... and finally fallback linkers. |
317 return Thread.currentThread().getContextClassLoader(); |
317 return Thread.currentThread().getContextClassLoader(); |
318 } |
318 } |
319 }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); |
319 }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); |
320 } |
320 } |
321 |
321 |
322 private static void addClasses(Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses, |
322 private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses, |
323 List<? extends GuardingDynamicLinker> linkers) { |
323 final List<? extends GuardingDynamicLinker> linkers) { |
324 for(GuardingDynamicLinker linker: linkers) { |
324 for(final GuardingDynamicLinker linker: linkers) { |
325 knownLinkerClasses.add(linker.getClass()); |
325 knownLinkerClasses.add(linker.getClass()); |
326 } |
326 } |
327 } |
327 } |
328 } |
328 } |