DynamicLinkerFactory.java revision 1643:133ea8746b37
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file, and Oracle licenses the original version of this file under the BSD
31 * license:
32 */
33/*
34   Copyright 2009-2013 Attila Szegedi
35
36   Licensed under both the Apache License, Version 2.0 (the "Apache License")
37   and the BSD License (the "BSD License"), with licensee being free to
38   choose either of the two at their discretion.
39
40   You may not use this file except in compliance with either the Apache
41   License or the BSD License.
42
43   If you choose to use this file in compliance with the Apache License, the
44   following notice applies to you:
45
46       You may obtain a copy of the Apache License at
47
48           http://www.apache.org/licenses/LICENSE-2.0
49
50       Unless required by applicable law or agreed to in writing, software
51       distributed under the License is distributed on an "AS IS" BASIS,
52       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
53       implied. See the License for the specific language governing
54       permissions and limitations under the License.
55
56   If you choose to use this file in compliance with the BSD License, the
57   following notice applies to you:
58
59       Redistribution and use in source and binary forms, with or without
60       modification, are permitted provided that the following conditions are
61       met:
62       * Redistributions of source code must retain the above copyright
63         notice, this list of conditions and the following disclaimer.
64       * Redistributions in binary form must reproduce the above copyright
65         notice, this list of conditions and the following disclaimer in the
66         documentation and/or other materials provided with the distribution.
67       * Neither the name of the copyright holder nor the names of
68         contributors may be used to endorse or promote products derived from
69         this software without specific prior written permission.
70
71       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
72       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
73       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
74       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
75       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
78       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
79       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
80       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
81       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
82*/
83
84package jdk.dynalink;
85
86import java.lang.invoke.MethodHandle;
87import java.lang.invoke.MethodType;
88import java.lang.invoke.MutableCallSite;
89import java.security.AccessControlContext;
90import java.security.AccessController;
91import java.security.PrivilegedAction;
92import java.util.ArrayList;
93import java.util.Arrays;
94import java.util.Collections;
95import java.util.HashSet;
96import java.util.Iterator;
97import java.util.LinkedList;
98import java.util.List;
99import java.util.Objects;
100import java.util.ServiceConfigurationError;
101import java.util.ServiceLoader;
102import java.util.Set;
103import java.util.function.Supplier;
104import jdk.dynalink.beans.BeansLinker;
105import jdk.dynalink.internal.AccessControlContextFactory;
106import jdk.dynalink.linker.GuardedInvocation;
107import jdk.dynalink.linker.GuardedInvocationTransformer;
108import jdk.dynalink.linker.GuardingDynamicLinker;
109import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
110import jdk.dynalink.linker.GuardingTypeConverterFactory;
111import jdk.dynalink.linker.LinkRequest;
112import jdk.dynalink.linker.LinkerServices;
113import jdk.dynalink.linker.MethodHandleTransformer;
114import jdk.dynalink.linker.MethodTypeConversionStrategy;
115import jdk.dynalink.linker.support.CompositeGuardingDynamicLinker;
116import jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker;
117import jdk.dynalink.linker.support.DefaultInternalObjectFilter;
118import jdk.dynalink.linker.support.TypeUtilities;
119
120/**
121 * A factory class for creating {@link DynamicLinker} objects. Dynamic linkers
122 * are the central objects in Dynalink; these are composed of several
123 * {@link GuardingDynamicLinker} objects and coordinate linking of call sites
124 * with them. The usual dynamic linker is a linker
125 * composed of all {@link GuardingDynamicLinker} objects explicitly pre-created
126 * by the user of the factory and configured with
127 * {@link #setPrioritizedLinkers(List)}, as well as any
128 * {@link #setClassLoader(ClassLoader) automatically discovered} ones, and
129 * finally the ones configured with {@link #setFallbackLinkers(List)}; this last
130 * category usually includes {@link BeansLinker}.
131 */
132public final class DynamicLinkerFactory {
133    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
134            AccessControlContextFactory.createAccessControlContext("getClassLoader");
135
136    /**
137     * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink
138     * threshold}.
139     */
140    private static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8;
141
142    private boolean classLoaderExplicitlySet = false;
143    private ClassLoader classLoader;
144
145    private List<? extends GuardingDynamicLinker> prioritizedLinkers;
146    private List<? extends GuardingDynamicLinker> fallbackLinkers;
147    private boolean syncOnRelink = false;
148    private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
149    private GuardedInvocationTransformer prelinkTransformer;
150    private MethodTypeConversionStrategy autoConversionStrategy;
151    private MethodHandleTransformer internalObjectsFilter;
152
153    private List<ServiceConfigurationError> autoLoadingErrors = Collections.emptyList();
154
155    /**
156     * Creates a new dynamic linker factory with default configuration. Upon
157     * creation, the factory can be configured using various {@code setXxx()}
158     * methods and used to create one or more dynamic linkers according to its
159     * current configuration using {@link #createLinker()}.
160     */
161    public DynamicLinkerFactory() {
162    }
163
164    /**
165     * Sets the class loader for automatic discovery of available guarding
166     * dynamic linkers. {@link GuardingDynamicLinkerExporter} implementations
167     * available through this class loader will be automatically instantiated
168     * using the {@link ServiceLoader} mechanism and the linkers they provide
169     * will be incorporated into {@code DynamicLinker}s that this factory
170     * creates. This allows for cross-language interoperability where call sites
171     * belonging to this language runtime can be linked by linkers from these
172     * automatically discovered runtimes if their native objects are passed to
173     * this runtime. If class loader is not set explicitly by invoking this
174     * method, then the thread context class loader of the thread invoking
175     * {@link #createLinker()} will be used. If this method is invoked
176     * explicitly with null then {@link ServiceLoader#loadInstalled(Class)} will
177     * be used to load the linkers.
178     *
179     * @param classLoader the class loader used for the automatic discovery of
180     * available linkers.
181     */
182    public void setClassLoader(final ClassLoader classLoader) {
183        this.classLoader = classLoader;
184        classLoaderExplicitlySet = true;
185    }
186
187    /**
188     * Sets the prioritized guarding dynamic linkers. Language runtimes using
189     * Dynalink will usually have at least one linker for their own language.
190     * These linkers will be consulted first by the resulting dynamic linker
191     * when it is linking call sites, before any autodiscovered and fallback
192     * linkers. If the factory also autodiscovers a linker class matching one
193     * of the prioritized linkers, the autodiscovered class will be ignored and
194     * the explicit prioritized instance will be used.
195     *
196     * @param prioritizedLinkers the list of prioritized linkers. Can be null.
197     * @throws NullPointerException if any of the list elements are null.
198     */
199    public void setPrioritizedLinkers(final List<? extends GuardingDynamicLinker> prioritizedLinkers) {
200        this.prioritizedLinkers = copyListRequireNonNullElements(prioritizedLinkers);
201    }
202
203    /**
204     * Sets the prioritized guarding dynamic linkers. Identical to calling
205     * {@link #setPrioritizedLinkers(List)} with
206     * {@code Arrays.asList(prioritizedLinkers)}.
207     *
208     * @param prioritizedLinkers an array of prioritized linkers. Can be null.
209     * @throws NullPointerException if any of the array elements are null.
210     */
211    public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) {
212        setPrioritizedLinkers(prioritizedLinkers == null ? null : Arrays.asList(prioritizedLinkers));
213    }
214
215    /**
216     * Sets a single prioritized linker. Identical to calling
217     * {@link #setPrioritizedLinkers(List)} with a single-element list.
218     *
219     * @param prioritizedLinker the single prioritized linker. Must not be null.
220     * @throws NullPointerException if null is passed.
221     */
222    public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) {
223        this.prioritizedLinkers = Collections.singletonList(Objects.requireNonNull(prioritizedLinker));
224    }
225
226    /**
227     * Sets the fallback guarding dynamic linkers. These linkers will be
228     * consulted last by the resulting dynamic linker when it is linking call
229     * sites, after any autodiscovered and prioritized linkers. If the factory
230     * also autodiscovers a linker class matching one of the fallback linkers,
231     * the autodiscovered class will be ignored and the explicit fallback
232     * instance will be used.
233     *
234     * @param fallbackLinkers the list of fallback linkers. Can be empty to
235     * indicate the caller wishes to set no fallback linkers. Note that if this
236     * method is not invoked explicitly or is passed null, then the factory
237     * will create an instance of {@link BeansLinker} to serve as the default
238     * fallback linker.
239     * @throws NullPointerException if any of the list elements are null.
240     */
241    public void setFallbackLinkers(final List<? extends GuardingDynamicLinker> fallbackLinkers) {
242        this.fallbackLinkers = copyListRequireNonNullElements(fallbackLinkers);
243    }
244
245    /**
246     * Sets the fallback guarding dynamic linkers. Identical to calling
247     * {@link #setFallbackLinkers(List)} with
248     * {@code Arrays.asList(fallbackLinkers)}.
249     *
250     * @param fallbackLinkers an array of fallback linkers. Can be empty to
251     * indicate the caller wishes to set no fallback linkers. Note that if this
252     * method is not invoked explicitly or is passed null, then the factory
253     * will create an instance of {@link BeansLinker} to serve as the default
254     * fallback linker.
255     * @throws NullPointerException if any of the array elements are null.
256     */
257    public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) {
258        setFallbackLinkers(fallbackLinkers == null ? null : Arrays.asList(fallbackLinkers));
259    }
260
261    /**
262     * Sets whether the dynamic linker created by this factory will invoke
263     * {@link MutableCallSite#syncAll(MutableCallSite[])} after a call site is
264     * relinked. Defaults to false. You probably want to set it to true if your
265     * runtime supports multithreaded execution of dynamically linked code.
266     * @param syncOnRelink true for invoking sync on relink, false otherwise.
267     */
268    public void setSyncOnRelink(final boolean syncOnRelink) {
269        this.syncOnRelink = syncOnRelink;
270    }
271
272    /**
273     * Sets the unstable relink threshold; the number of times a call site is
274     * relinked after which it will be considered unstable, and subsequent link
275     * requests for it will indicate this. Defaults to 8 when not set explicitly.
276     * @param unstableRelinkThreshold the new threshold. Must not be less than
277     * zero. The value of zero means that call sites will never be considered
278     * unstable.
279     * @see LinkRequest#isCallSiteUnstable()
280     */
281    public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) {
282        if(unstableRelinkThreshold < 0) {
283            throw new IllegalArgumentException("unstableRelinkThreshold < 0");
284        }
285        this.unstableRelinkThreshold = unstableRelinkThreshold;
286    }
287
288    /**
289     * Set the pre-link transformer. This is a
290     * {@link GuardedInvocationTransformer} that will get the final chance to
291     * modify the guarded invocation after it has been created by a component
292     * linker and before the dynamic linker links it into the call site. It is
293     * normally used to adapt the return value type of the invocation to the
294     * type of the call site. When not set explicitly, a default pre-link
295     * transformer will be used that simply calls
296     * {@link GuardedInvocation#asType(LinkerServices, MethodType)}. Customized
297     * pre-link transformers are rarely needed; they are mostly used as a
298     * building block for implementing advanced techniques such as code
299     * deoptimization strategies.
300     * @param prelinkTransformer the pre-link transformer for the dynamic
301     * linker. Can be null to have the factory use the default transformer.
302     */
303    public void setPrelinkTransformer(final GuardedInvocationTransformer prelinkTransformer) {
304        this.prelinkTransformer = prelinkTransformer;
305    }
306
307    /**
308     * Sets an object representing the conversion strategy for automatic type
309     * conversions. After
310     * {@link LinkerServices#asType(MethodHandle, MethodType)} has applied all
311     * custom conversions to a method handle, it still needs to effect
312     * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method
313     * invocation conversions} that can usually be automatically applied as per
314     * {@link MethodHandle#asType(MethodType)}. However, sometimes language
315     * runtimes will want to customize even those conversions for their own call
316     * sites. A typical example is allowing unboxing of null return values,
317     * which is by default prohibited by ordinary
318     * {@code MethodHandles.asType()}. In this case, a language runtime can
319     * install its own custom automatic conversion strategy, that can deal with
320     * null values. Note that when the strategy's
321     * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}
322     * is invoked, the custom language conversions will already have been
323     * applied to the method handle, so by design the difference between the
324     * handle's current method type and the desired final type will always only
325     * be ones that can be subjected to method invocation conversions. The
326     * strategy also doesn't need to invoke a final
327     * {@code MethodHandle.asType()} as that will be done internally as the
328     * final step.
329     * @param autoConversionStrategy the strategy for applying method invocation
330     * conversions for the linker created by this factory. Can be null for no
331     * custom strategy.
332     */
333    public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) {
334        this.autoConversionStrategy = autoConversionStrategy;
335    }
336
337    /**
338     * Sets a method handle transformer that is supposed to act as the
339     * implementation of
340     * {@link LinkerServices#filterInternalObjects(MethodHandle)} for linker
341     * services of dynamic linkers created by this factory. Some language
342     * runtimes can have internal objects that should not escape their scope.
343     * They can add a transformer here that will modify the method handle so
344     * that any parameters that can receive potentially internal language
345     * runtime objects will have a filter added on them to prevent them from
346     * escaping, potentially by wrapping them. The transformer can also
347     * potentially add an unwrapping filter to the return value.
348     * {@link DefaultInternalObjectFilter} is provided as a convenience class
349     * for easily creating such filtering transformers.
350     * @param internalObjectsFilter a method handle transformer filtering out
351     * internal objects, or null.
352     */
353    public void setInternalObjectsFilter(final MethodHandleTransformer internalObjectsFilter) {
354        this.internalObjectsFilter = internalObjectsFilter;
355    }
356
357    /**
358     * Creates a new dynamic linker based on the current configuration. This
359     * method can be invoked more than once to create multiple dynamic linkers.
360     * Automatically discovered linkers are newly instantiated on every
361     * invocation of this method. It is allowed to change the factory's
362     * configuration between invocations. The method is not thread safe. After
363     * invocation, callers can invoke {@link #getAutoLoadingErrors()} to
364     * retrieve a list of {@link ServiceConfigurationError}s that occurred while
365     * trying to load automatically discovered linkers. These are never thrown
366     * from the call to this method as it makes every effort to recover from
367     * them and ignore the failing linkers.
368     * @return the new dynamic Linker
369     */
370    public DynamicLinker createLinker() {
371        // Treat nulls appropriately
372        if(prioritizedLinkers == null) {
373            prioritizedLinkers = Collections.emptyList();
374        }
375        if(fallbackLinkers == null) {
376            fallbackLinkers = Collections.singletonList(new BeansLinker());
377        }
378
379        // Gather classes of all precreated (prioritized and fallback) linkers.
380        // We'll filter out any discovered linkers of the same class.
381        final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses =
382                new HashSet<>();
383        addClasses(knownLinkerClasses, prioritizedLinkers);
384        addClasses(knownLinkerClasses, fallbackLinkers);
385
386        final List<GuardingDynamicLinker> discovered = discoverAutoLoadLinkers();
387        // Now, concatenate ...
388        final List<GuardingDynamicLinker> linkers =
389                new ArrayList<>(prioritizedLinkers.size() + discovered.size()
390                        + fallbackLinkers.size());
391        // ... prioritized linkers, ...
392        linkers.addAll(prioritizedLinkers);
393        // ... filtered discovered linkers, ...
394        for(final GuardingDynamicLinker linker: discovered) {
395            if(!knownLinkerClasses.contains(linker.getClass())) {
396                linkers.add(linker);
397            }
398        }
399        // ... and finally fallback linkers.
400        linkers.addAll(fallbackLinkers);
401        final List<GuardingDynamicLinker> optimized = CompositeTypeBasedGuardingDynamicLinker.optimize(linkers);
402        final GuardingDynamicLinker composite;
403        switch(linkers.size()) {
404            case 0: {
405                composite = (r, s) -> null; // linker that can't link anything
406                break;
407            }
408            case 1: {
409                composite = optimized.get(0);
410                break;
411            }
412            default: {
413                composite = new CompositeGuardingDynamicLinker(optimized);
414                break;
415            }
416        }
417
418        final List<GuardingTypeConverterFactory> typeConverters = new LinkedList<>();
419        for(final GuardingDynamicLinker linker: linkers) {
420            if(linker instanceof GuardingTypeConverterFactory) {
421                typeConverters.add((GuardingTypeConverterFactory)linker);
422            }
423        }
424
425        if(prelinkTransformer == null) {
426            prelinkTransformer = (inv, request, linkerServices) -> inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType());
427        }
428
429        return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters,
430                autoConversionStrategy), composite, internalObjectsFilter), prelinkTransformer,
431                syncOnRelink, unstableRelinkThreshold);
432    }
433
434    /**
435     * Returns a list of {@link ServiceConfigurationError}s that were
436     * encountered while loading automatically discovered linkers during the
437     * last invocation of {@link #createLinker()}. They can be any non-Dynalink
438     * specific service configuration issues, as well as some Dynalink-specific
439     * errors when an exporter that the factory tried to automatically load:
440     * <ul>
441     * <li>did not have the runtime permission named
442     * {@link GuardingDynamicLinkerExporter#AUTOLOAD_PERMISSION_NAME} in a
443     * system with a security manager, or</li>
444     * <li>returned null from {@link GuardingDynamicLinkerExporter#get()}, or</li>
445     * <li>the list returned from {@link GuardingDynamicLinkerExporter#get()}
446     * had a null element.</li>
447     * </ul>
448     * @return an immutable list of encountered
449     * {@link ServiceConfigurationError}s. Can be empty.
450     */
451    public List<ServiceConfigurationError> getAutoLoadingErrors() {
452        return Collections.unmodifiableList(autoLoadingErrors);
453    }
454
455    private List<GuardingDynamicLinker> discoverAutoLoadLinkers() {
456        autoLoadingErrors = new LinkedList<>();
457        final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader();
458        final List<GuardingDynamicLinker> discovered = new LinkedList<>();
459        try {
460            final ServiceLoader<GuardingDynamicLinkerExporter> linkerLoader =
461                    AccessController.doPrivileged((PrivilegedAction<ServiceLoader<GuardingDynamicLinkerExporter>>)()-> {
462                        if (effectiveClassLoader == null) {
463                            return ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class);
464                        }
465                        return ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader);
466                    });
467
468            for(final Iterator<GuardingDynamicLinkerExporter> it = linkerLoader.iterator(); it.hasNext();) {
469                try {
470                    final GuardingDynamicLinkerExporter autoLoader = it.next();
471                    try {
472                        discovered.addAll(requireNonNullElements(
473                                Objects.requireNonNull(autoLoader.get(),
474                                        ()->(autoLoader.getClass().getName() + " returned null from get()")),
475                                ()->(autoLoader.getClass().getName() + " returned a list with at least one null element")));
476                    } catch (final ServiceConfigurationError|VirtualMachineError e) {
477                        // Don't wrap a SCE in another SCE. Also, don't ignore
478                        // any VME (e.g. StackOverflowError or OutOfMemoryError).
479                        throw e;
480                    } catch (final Throwable t) {
481                        throw new ServiceConfigurationError(t.getMessage(), t);
482                    }
483                } catch (final ServiceConfigurationError e) {
484                    // Catch SCE with an individual exporter, carry on with it.hasNext().
485                    autoLoadingErrors.add(e);
486                }
487            }
488        } catch (final ServiceConfigurationError e) {
489            // Catch a top-level SCE; one either in ServiceLoader.load(),
490            // ServiceLoader.iterator(), or Iterator.hasNext().
491            autoLoadingErrors.add(e);
492        }
493        return discovered;
494    }
495
496    private static ClassLoader getThreadContextClassLoader() {
497        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
498            @Override
499            public ClassLoader run() {
500                return Thread.currentThread().getContextClassLoader();
501            }
502        }, GET_CLASS_LOADER_CONTEXT);
503    }
504
505    private static void addClasses(final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
506            final List<? extends GuardingDynamicLinker> linkers) {
507        for(final GuardingDynamicLinker linker: linkers) {
508            knownLinkerClasses.add(linker.getClass());
509        }
510    }
511
512    private static <T> List<T> copyListRequireNonNullElements(final List<T> list) {
513        if (list == null) {
514            return null;
515        }
516        return new ArrayList<>(requireNonNullElements(list, ()->"List has at least one null element"));
517    }
518
519    private static <T> List<T> requireNonNullElements(final List<T> list, final Supplier<String> msgSupplier) {
520        for(final T t: list) {
521            Objects.requireNonNull(t, msgSupplier);
522        }
523        return list;
524    }
525
526}
527