/*
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang.invoke;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.function.IntFunction;

An ordered sequence of constants, some of which may not yet be present. This type is used by BootstrapCallInfo to represent the sequence of bootstrap arguments associated with a bootstrap method, without forcing their immediate resolution.

If you use the simple get method, the constant will be resolved, if this has not already happened. An occasional side effect of resolution is a LinkageError, which happens if the system could not resolve the constant in question.

In order to peek at a constant without necessarily resolving it, use the non-throwing get method. This method will never throw a resolution error. Instead, if the resolution would result in an error, or if the implementation elects not to attempt resolution at this point, then the method will return the user-supplied sentinel value.

To iterate through the constants, resolving as you go, use the iterator provided on the List-typed view. If you supply a sentinel, resolution will be suppressed.

Typically the constant is drawn from a constant pool entry in the virtual machine. Constant pool entries undergo a one-time state transition from unresolved to resolved, with a permanently recorded result. Usually that result is the desired constant value, but it may also be an error. In any case, the results displayed by a ConstantGroup are stable in the same way. If a query to a particular constant in a ConstantGroup throws an exception once, it will throw the same kind of exception forever after. If the query returns a constant value once, it will return the same value forever after.

The only possible change in the status of a constant is from the unresolved to the resolved state, and that happens exactly once. A constant will never revert to an unlinked state. However, from the point of view of this interface, constants may appear to spontaneously resolve. This is so because constant pools are global structures shared across threads, and because prefetching of some constants may occur, there are no strong guarantees when the virtual machine may resolve constants.

When choosing sentinel values, be aware that a constant pool which has CONSTANT_Dynamic entries can contain potentially any representable value, and arbitrary implementations of ConstantGroup are also free to produce arbitrary values. This means some obvious choices for sentinel values, such as null, may sometimes fail to distinguish a resolved from an unresolved constant in the group. The most reliable sentinel is a privately created object, or perhaps the ConstantGroup itself.

Since:1.10
/** * An ordered sequence of constants, some of which may not yet * be present. This type is used by {@link BootstrapCallInfo} * to represent the sequence of bootstrap arguments associated * with a bootstrap method, without forcing their immediate * resolution. * <p> * If you use the * {@linkplain ConstantGroup#get(int) simple get method}, * the constant will be resolved, if this has not already * happened. An occasional side effect of resolution is a * {@code LinkageError}, which happens if the system * could not resolve the constant in question. * <p> * In order to peek at a constant without necessarily * resolving it, use the * {@linkplain ConstantGroup#get(int,Object) * non-throwing get method}. * This method will never throw a resolution error. * Instead, if the resolution would result in an error, * or if the implementation elects not to attempt * resolution at this point, then the method will * return the user-supplied sentinel value. * <p> * To iterate through the constants, resolving as you go, * use the iterator provided on the {@link List}-typed view. * If you supply a sentinel, resolution will be suppressed. * <p> * Typically the constant is drawn from a constant pool entry * in the virtual machine. Constant pool entries undergo a * one-time state transition from unresolved to resolved, * with a permanently recorded result. Usually that result * is the desired constant value, but it may also be an error. * In any case, the results displayed by a {@code ConstantGroup} * are stable in the same way. If a query to a particular * constant in a {@code ConstantGroup} throws an exception once, * it will throw the same kind of exception forever after. * If the query returns a constant value once, it will return * the same value forever after. * <p> * The only possible change in the status of a constant is * from the unresolved to the resolved state, and that * happens exactly once. A constant will never revert to * an unlinked state. However, from the point of view of * this interface, constants may appear to spontaneously * resolve. This is so because constant pools are global * structures shared across threads, and because * prefetching of some constants may occur, there are no * strong guarantees when the virtual machine may resolve * constants. * <p> * When choosing sentinel values, be aware that a constant * pool which has {@code CONSTANT_Dynamic} entries * can contain potentially any representable value, * and arbitrary implementations of {@code ConstantGroup} * are also free to produce arbitrary values. * This means some obvious choices for sentinel values, * such as {@code null}, may sometimes fail to distinguish * a resolved from an unresolved constant in the group. * The most reliable sentinel is a privately created object, * or perhaps the {@code ConstantGroup} itself. * @since 1.10 */
// public interface ConstantGroup { /// Access
Returns the number of constants in this group. This value never changes, for any particular group.
Returns:the number of constants in this group
/** * Returns the number of constants in this group. * This value never changes, for any particular group. * @return the number of constants in this group */
int size();
Returns the selected constant, resolving it if necessary. Throws a linkage error if resolution proves impossible.
Params:
  • index – which constant to select
Throws:
  • LinkageError – if the selected constant needs resolution and cannot be resolved
Returns:the selected constant
/** * Returns the selected constant, resolving it if necessary. * Throws a linkage error if resolution proves impossible. * @param index which constant to select * @return the selected constant * @throws LinkageError if the selected constant needs resolution and cannot be resolved */
Object get(int index) throws LinkageError;
Returns the selected constant, or the given sentinel value if there is none available. If the constant cannot be resolved, the sentinel will be returned. If the constant can (perhaps) be resolved, but has not yet been resolved, then the sentinel may be returned, at the implementation's discretion. To force resolution (and a possible exception), call get(int).
Params:
  • index – the selected constant
  • ifNotPresent – the sentinel value to return if the constant is not present
Returns:the selected constant, if available, else the sentinel value
/** * Returns the selected constant, * or the given sentinel value if there is none available. * If the constant cannot be resolved, the sentinel will be returned. * If the constant can (perhaps) be resolved, but has not yet been resolved, * then the sentinel <em>may</em> be returned, at the implementation's discretion. * To force resolution (and a possible exception), call {@link #get(int)}. * @param index the selected constant * @param ifNotPresent the sentinel value to return if the constant is not present * @return the selected constant, if available, else the sentinel value */
Object get(int index, Object ifNotPresent);
Returns an indication of whether a constant may be available. If it returns true, it will always return true in the future, and a call to get(int) will never throw an exception.

After a normal return from get(int) or a present value is reported from get(int, Object), this method must always return true.

If this method returns false, nothing in particular can be inferred, since the query only concerns the internal logic of the ConstantGroup object which ensures that a successful * query to a constant will always remain successful. The only way to force a permanent decision about whether a constant is available is to call get(int) and be ready for an exception if the constant is unavailable.

Params:
  • index – the selected constant
Returns:true if the selected constant is known by this object to be present, false if it is known not to be present or
/** * Returns an indication of whether a constant may be available. * If it returns {@code true}, it will always return true in the future, * and a call to {@link #get(int)} will never throw an exception. * <p> * After a normal return from {@link #get(int)} or a present * value is reported from {@link #get(int,Object)}, this method * must always return true. * <p> * If this method returns {@code false}, nothing in particular * can be inferred, since the query only concerns the internal * logic of the {@code ConstantGroup} object which ensures that a successful * query to a constant will always remain successful. * The only way to force a permanent decision about whether * a constant is available is to call {@link #get(int)} and * be ready for an exception if the constant is unavailable. * @param index the selected constant * @return {@code true} if the selected constant is known by * this object to be present, {@code false} if it is known * not to be present or */
boolean isPresent(int index); /// Views
Create a view on this group as a List view. Any request for a constant through this view will force resolution.
Returns:a List view on this group which will force resolution
/** * Create a view on this group as a {@link List} view. * Any request for a constant through this view will * force resolution. * @return a {@code List} view on this group which will force resolution */
default List<Object> asList() { return new AbstractConstantGroup.AsList(this, 0, size()); }
Create a view on this group as a List view. Any request for a constant through this view will return the given sentinel value, if the corresponding call to get(int, Object) would do so.
Params:
  • ifNotPresent – the sentinel value to return if a constant is not present
Returns:a List view on this group which will not force resolution
/** * Create a view on this group as a {@link List} view. * Any request for a constant through this view will * return the given sentinel value, if the corresponding * call to {@link #get(int,Object)} would do so. * @param ifNotPresent the sentinel value to return if a constant is not present * @return a {@code List} view on this group which will not force resolution */
default List<Object> asList(Object ifNotPresent) { return new AbstractConstantGroup.AsList(this, 0, size(), ifNotPresent); }
Create a view on a sub-sequence of this group.
Params:
  • start – the index to begin the view
  • end – the index to end the view
Returns:a view on the selected sub-group
/** * Create a view on a sub-sequence of this group. * @param start the index to begin the view * @param end the index to end the view * @return a view on the selected sub-group */
default ConstantGroup subGroup(int start, int end) { return new AbstractConstantGroup.SubGroup(this, start, end); } /// Bulk operations
Copy a sequence of constant values into a given buffer. This is equivalent to end-offset separate calls to get, for each index in the range from offset up to but not including end. For the first constant that cannot be resolved, a LinkageError is thrown, but only after preceding constant value have been stored.
Params:
  • start – index of first constant to retrieve
  • end – limiting index of constants to retrieve
  • buf – array to receive the requested values
  • pos – position in the array to offset storing the values
Throws:
Returns:the limiting index, end
/** * Copy a sequence of constant values into a given buffer. * This is equivalent to {@code end-offset} separate calls to {@code get}, * for each index in the range from {@code offset} up to but not including {@code end}. * For the first constant that cannot be resolved, * a {@code LinkageError} is thrown, but only after * preceding constant value have been stored. * @param start index of first constant to retrieve * @param end limiting index of constants to retrieve * @param buf array to receive the requested values * @param pos position in the array to offset storing the values * @return the limiting index, {@code end} * @throws LinkageError if a constant cannot be resolved */
default int copyConstants(int start, int end, Object[] buf, int pos) throws LinkageError { int bufBase = pos - start; // buf[bufBase + i] = get(i) for (int i = start; i < end; i++) { buf[bufBase + i] = get(i); } return end; }
Copy a sequence of constant values into a given buffer. This is equivalent to end-offset separate calls to get, for each index in the range from offset up to but not including end. Any constants that cannot be resolved are replaced by the given sentinel value.
Params:
  • start – index of first constant to retrieve
  • end – limiting index of constants to retrieve
  • buf – array to receive the requested values
  • pos – position in the array to offset storing the values
  • ifNotPresent – sentinel value to store if a value is not available
Throws:
  • LinkageError – if resolve is true and a constant cannot be resolved
Returns:the limiting index, end
/** * Copy a sequence of constant values into a given buffer. * This is equivalent to {@code end-offset} separate calls to {@code get}, * for each index in the range from {@code offset} up to but not including {@code end}. * Any constants that cannot be resolved are replaced by the * given sentinel value. * @param start index of first constant to retrieve * @param end limiting index of constants to retrieve * @param buf array to receive the requested values * @param pos position in the array to offset storing the values * @param ifNotPresent sentinel value to store if a value is not available * @return the limiting index, {@code end} * @throws LinkageError if {@code resolve} is true and a constant cannot be resolved */
default int copyConstants(int start, int end, Object[] buf, int pos, Object ifNotPresent) { int bufBase = pos - start; // buf[bufBase + i] = get(i) for (int i = start; i < end; i++) { buf[bufBase + i] = get(i, ifNotPresent); } return end; }
Make a new constant group with the given constants. The value of ifNotPresent may be any reference. If this value is encountered as an element of the constants list, the new constant group will regard that element of the list as logically missing. If the new constant group is called upon to resolve a missing element of the group, it will refer to the given constantProvider, by calling it on the index of the missing element. The constantProvider must be stable, in the sense that the outcome of calling it on the same index twice will produce equivalent results. If constantProvider is the null reference, then it will be treated as if it were a function which raises NoSuchElementException.
Params:
  • constants – the elements of this constant group
  • ifNotPresent – sentinel value provided instead of a missing constant
  • constantProvider – function to call when a missing constant is resolved
Returns:a new constant group with the given constants and resolution behavior
/** * Make a new constant group with the given constants. * The value of {@code ifNotPresent} may be any reference. * If this value is encountered as an element of the * {@code constants} list, the new constant group will * regard that element of the list as logically missing. * If the new constant group is called upon to resolve * a missing element of the group, it will refer to the * given {@code constantProvider}, by calling it on the * index of the missing element. * The {@code constantProvider} must be stable, in the sense * that the outcome of calling it on the same index twice * will produce equivalent results. * If {@code constantProvider} is the null reference, then * it will be treated as if it were a function which raises * {@link NoSuchElementException}. * @param constants the elements of this constant group * @param ifNotPresent sentinel value provided instead of a missing constant * @param constantProvider function to call when a missing constant is resolved * @return a new constant group with the given constants and resolution behavior */
static ConstantGroup makeConstantGroup(List<Object> constants, Object ifNotPresent, IntFunction<Object> constantProvider) { class Impl extends AbstractConstantGroup.WithCache { Impl() { super(constants.size()); initializeCache(constants, ifNotPresent); } @Override Object fillCache(int index) { if (constantProvider == null) super.fillCache(index); return constantProvider.apply(index); } } return new Impl(); }
Make a new constant group with the given constant values. The constants will be copied from the given list into the new constant group, forcing resolution if any are missing.
Params:
  • constants – the constants of this constant group
Returns:a new constant group with the given constants
/** * Make a new constant group with the given constant values. * The constants will be copied from the given list into the * new constant group, forcing resolution if any are missing. * @param constants the constants of this constant group * @return a new constant group with the given constants */
static ConstantGroup makeConstantGroup(List<Object> constants) { final Object NP = AbstractConstantGroup.WithCache.NOT_PRESENT; assert(!constants.contains(NP)); // secret value return makeConstantGroup(constants, NP, null); } }