This commit is contained in:
Lana Steuck 2016-04-07 11:03:59 -07:00
commit 50abd159dd
565 changed files with 51919 additions and 5116 deletions
jdk
make
src
java.base/share
java.compact3/share/classes
java.desktop/macosx/classes

@ -1,129 +0,0 @@
/*
* Copyright (c) 1998, 2015, 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 @(BeanPackageName);
import java.beans.BeanDescriptor;
import java.beans.PropertyDescriptor;
import java.awt.Image;
import sun.swing.BeanInfoUtils;
/**
* Descriptive information about the @(BeanClassName) class for Java
* Beans application builders. This BeanInfo class provides descriptions
* of each property, of the bean itself, it indicates which
* @(BeanClassName) properties are bound, and it provides other
* information and icons useful to builders.
*
* @author Auto-Generated Source Code
*/
public class @(BeanClassName)BeanInfo extends javax.swing.SwingBeanInfoBase {
private static final Class<?> class@(BeanClassName) = @(BeanClassObject);
/**
* @return a @(BeanClassName) BeanDescriptor
*/
public BeanDescriptor getBeanDescriptor() {
return BeanInfoUtils.createBeanDescriptor(class@(BeanClassName),
new Object[] {
BeanInfoUtils.PREFERRED, Boolean.TRUE,
@(ClassDescriptors)
BeanInfoUtils.SHORTDESCRIPTION, "@(BeanDescription)"
});
}
/**
* Create a @(BeanClassName) PropertyDescriptor. This is just an internal
* convenience method that allows one to leave the @(BeanClassName).class
* argument out of the createPropertyDescriptor() class in the
* getPropertyDescriptors() method below.
*
* @param name the name of the property
* @param args an array java.beans.PropertyDescriptor property names and values
* @return a @(BeanClassName) PropertyDescriptor.
* @see BeanInfoUtils#createPropertyDescriptor
*/
private PropertyDescriptor createPropertyDescriptor(String name, Object[] args) {
return BeanInfoUtils.createPropertyDescriptor(class@(BeanClassName), name, args);
}
/**
* This method returns a list of bean PropertyDescriptors, one for each public
* property in @(BeanClassName). The first property is the "default" property.
*
* @return a complete list of bean PropertyDescriptors for @(BeanClassName)
* @see SwingBeanInfo
* @see java.beans.BeanInfo#getDefaultPropertyIndex
*/
public PropertyDescriptor[] getPropertyDescriptors() {
@(EnumVariables)
return new PropertyDescriptor[] {
@(BeanPropertyDescriptors)
};
}
/**
* @return an icon of the specified kind for @(BeanClassName)
*/
public Image getIcon(final int kind) {
Image i;
switch (kind){
case ICON_COLOR_32x32:
i = loadStandardImage("beaninfo/images/@(BeanClassName)Color32.gif");
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor32.gif") : i);
case ICON_COLOR_16x16:
i = loadStandardImage("beaninfo/images/@(BeanClassName)Color16.gif");
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor16.gif") : i);
case ICON_MONO_32x32:
i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono32.gif");
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono32.gif") : i);
case ICON_MONO_16x16:
i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono16.gif");
return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono16.gif") : i);
default:
return super.getIcon(kind);
}
}
/**
* This is a utility method to help in loading standard icon images.
*
* @param resourceName A pathname relative to the directory holding the
* class file of the current class
* @return an image object. May be null if the load failed.
* @see java.beans.SimpleBeanInfo#loadImage(String)
*/
private Image loadStandardImage(final String resourceName) {
return java.security.AccessController.doPrivileged(
(java.security.PrivilegedAction<Image>) () -> loadImage(resourceName));
}
}

@ -1,82 +0,0 @@
/*
* Copyright (c) 1997, 2014, 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 javax.swing;
import java.beans.*;
import java.lang.reflect.*;
import java.awt.Image;
/**
* The superclass for all Swing BeanInfo classes. It provides
* default implementations of <code>getIcon</code> and
* <code>getDefaultPropertyIndex</code> as well as utility
* methods, like createPropertyDescriptor, for writing BeanInfo
* implementations. This classes is intended to be used along
* with <code>GenSwingBeanInfo</code> a BeanInfo class code generator.
*
* @see GenSwingBeanInfo
* @author Hans Muller
*/
public class SwingBeanInfoBase extends SimpleBeanInfo
{
/**
* The default index is always 0. In other words the first property
* listed in the getPropertyDescriptors() method is the one
* to show a (JFC builder) user in a situation where just a single
* property will be shown.
*/
public int getDefaultPropertyIndex() {
return 0;
}
/**
* Returns a generic Swing icon, all icon "kinds" are supported.
* Subclasses should defer to this method when they don't have
* a particular beans icon kind.
*/
public Image getIcon(int kind) {
// PENDING(hmuller) need generic swing icon images.
return null;
}
/**
* Returns the BeanInfo for the superclass of our bean, so that
* its PropertyDescriptors will be included.
*/
public BeanInfo[] getAdditionalBeanInfo() {
Class<?> superClass = getBeanDescriptor().getBeanClass().getSuperclass();
BeanInfo superBeanInfo = null;
try {
superBeanInfo = Introspector.getBeanInfo(superClass);
} catch (IntrospectionException ie) {}
if (superBeanInfo != null) {
BeanInfo[] ret = new BeanInfo[1];
ret[0] = superBeanInfo;
return ret;
}
return null;
}
}

@ -1,111 +0,0 @@
Name: javax/swing/JApplet.class
Java-Bean: True
Name: javax/swing/JButton.class
Java-Bean: True
Name: javax/swing/JCheckBox.class
Java-Bean: True
Name: javax/swing/JCheckBoxMenuItem.class
Java-Bean: True
Name: javax/swing/JComboBox.class
Java-Bean: True
Name: javax/swing/JDialog.class
Java-Bean: True
Name: javax/swing/JEditorPane.class
Java-Bean: True
Name: javax/swing/JFormattedTextField.class
Java-Bean: True
Name: javax/swing/JInternalFrame.class
Java-Bean: True
Name: javax/swing/JFrame.class
Java-Bean: True
Name: javax/swing/JLabel.class
Java-Bean: True
Name: javax/swing/JList.class
Java-Bean: True
Name: javax/swing/JMenu.class
Java-Bean: True
Name: javax/swing/JMenuBar.class
Java-Bean: True
Name: javax/swing/JMenuItem.class
Java-Bean: True
Name: javax/swing/JOptionPane.class
Java-Bean: True
Name: javax/swing/JPanel.class
Java-Bean: True
Name: javax/swing/JPasswordField.class
Java-Bean: True
Name: javax/swing/JPopupMenu.class
Java-Bean: True
Name: javax/swing/JProgressBar.class
Java-Bean: True
Name: javax/swing/JRadioButton.class
Java-Bean: True
Name: javax/swing/JRadioButtonMenuItem.class
Java-Bean: True
Name: javax/swing/JScrollBar.class
Java-Bean: True
Name: javax/swing/JScrollPane.class
Java-Bean: True
Name: javax/swing/JSeparator.class
Java-Bean: True
Name: javax/swing/JSlider.class
Java-Bean: True
Name: javax/swing/JSpinner.class
Java-Bean: True
Name: javax/swing/JSplitPane.class
Java-Bean: True
Name: javax/swing/JTabbedPane.class
Java-Bean: True
Name: javax/swing/JTextArea.class
Java-Bean: True
Name: javax/swing/JTextField.class
Java-Bean: True
Name: javax/swing/JTextPane.class
Java-Bean: True
Name: javax/swing/JToolBar.class
Java-Bean: True
Name: javax/swing/JTree.class
Java-Bean: True
Name: javax/swing/JTable.class
Java-Bean: True
Name: javax/swing/JToggleButton.class
Java-Bean: True
Name: javax/swing/JWindow.class
Java-Bean: True

@ -1,293 +0,0 @@
/*
* Copyright (c) 1998, 2014, 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 sun.swing;
import java.beans.*;
import java.lang.reflect.Method;
public class BeanInfoUtils
{
/* The values of these createPropertyDescriptor() and
* createBeanDescriptor() keywords are the names of the
* properties they're used to set.
*/
public static final String BOUND = "bound";
public static final String CONSTRAINED = "constrained";
public static final String PROPERTYEDITORCLASS = "propertyEditorClass";
public static final String READMETHOD = "readMethod";
public static final String WRITEMETHOD = "writeMethod";
public static final String DISPLAYNAME = "displayName";
public static final String EXPERT = "expert";
public static final String HIDDEN = "hidden";
public static final String PREFERRED = "preferred";
public static final String SHORTDESCRIPTION = "shortDescription";
public static final String CUSTOMIZERCLASS = "customizerClass";
static private void initFeatureDescriptor(FeatureDescriptor fd, String key, Object value)
{
if (DISPLAYNAME.equals(key)) {
fd.setDisplayName((String)value);
}
if (EXPERT.equals(key)) {
fd.setExpert(((Boolean)value).booleanValue());
}
if (HIDDEN.equals(key)) {
fd.setHidden(((Boolean)value).booleanValue());
}
if (PREFERRED.equals(key)) {
fd.setPreferred(((Boolean)value).booleanValue());
}
else if (SHORTDESCRIPTION.equals(key)) {
fd.setShortDescription((String)value);
}
/* Otherwise assume that we have an arbitrary FeatureDescriptor
* "attribute".
*/
else {
fd.setValue(key, value);
}
}
/**
* Create a beans PropertyDescriptor given an of keyword/value
* arguments. The following sample call shows all of the supported
* keywords:
*<pre>
* createPropertyDescriptor("contentPane", new Object[] {
* BOUND, Boolean.TRUE,
* CONSTRAINED, Boolean.TRUE,
* PROPERTYEDITORCLASS, package.MyEditor.class,
* READMETHOD, "getContentPane",
* WRITEMETHOD, "setContentPane",
* DISPLAYNAME, "contentPane",
* EXPERT, Boolean.FALSE,
* HIDDEN, Boolean.FALSE,
* PREFERRED, Boolean.TRUE,
* SHORTDESCRIPTION, "A top level window with a window manager border",
* "random attribute","random object value"
* }
* );
* </pre>
* The keywords correspond to <code>java.beans.PropertyDescriptor</code> and
* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
* Using createPropertyDescriptor instead of the PropertyDescriptor
* constructor and set methods is preferrable in that it regularizes
* the code in a <code>java.beans.BeanInfo.getPropertyDescriptors()</code>
* method implementation. One can use <code>createPropertyDescriptor</code>
* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
* "random object value".
* <p>
* All properties should provide a reasonable value for the
* <code>SHORTDESCRIPTION</code> keyword and should set <code>BOUND</code>
* to <code>Boolean.TRUE</code> if neccessary. The remaining keywords
* are optional. There's no need to provide values for keywords like
* READMETHOD if the correct value can be computed, i.e. if the properties
* get/is method follows the standard beans pattern.
* <p>
* The PREFERRED keyword is not supported by the JDK1.1 java.beans package.
* It's still worth setting it to true for properties that are most
* likely to be interested to the average developer, e.g. AbstractButton.title
* is a preferred property, AbstractButton.focusPainted is not.
*
* @see java.beans#BeanInfo
* @see java.beans#PropertyDescriptor
* @see java.beans#FeatureDescriptor
*/
public static PropertyDescriptor createPropertyDescriptor(Class<?> cls, String name, Object[] args)
{
PropertyDescriptor pd = null;
try {
pd = new PropertyDescriptor(name, cls);
} catch (IntrospectionException e) {
// Try creating a read-only property, in case setter isn't defined.
try {
pd = createReadOnlyPropertyDescriptor(name, cls);
} catch (IntrospectionException ie) {
throwError(ie, "Can't create PropertyDescriptor for " + name + " ");
}
}
for(int i = 0; i < args.length; i += 2) {
String key = (String)args[i];
Object value = args[i + 1];
if (BOUND.equals(key)) {
pd.setBound(((Boolean)value).booleanValue());
}
else if (CONSTRAINED.equals(key)) {
pd.setConstrained(((Boolean)value).booleanValue());
}
else if (PROPERTYEDITORCLASS.equals(key)) {
pd.setPropertyEditorClass((Class)value);
}
else if (READMETHOD.equals(key)) {
String methodName = (String)value;
Method method;
try {
method = cls.getMethod(methodName, new Class<?>[0]);
pd.setReadMethod(method);
}
catch(Exception e) {
throwError(e, cls + " no such method as \"" + methodName + "\"");
}
}
else if (WRITEMETHOD.equals(key)) {
String methodName = (String)value;
Method method;
try {
Class<?> type = pd.getPropertyType();
method = cls.getMethod(methodName, new Class<?>[]{type});
pd.setWriteMethod(method);
}
catch(Exception e) {
throwError(e, cls + " no such method as \"" + methodName + "\"");
}
}
else {
initFeatureDescriptor(pd, key, value);
}
}
return pd;
}
/**
* Create a BeanDescriptor object given an of keyword/value
* arguments. The following sample call shows all of the supported
* keywords:
*<pre>
* createBeanDescriptor(JWindow..class, new Object[] {
* CUSTOMIZERCLASS, package.MyCustomizer.class,
* DISPLAYNAME, "JFrame",
* EXPERT, Boolean.FALSE,
* HIDDEN, Boolean.FALSE,
* PREFERRED, Boolean.TRUE,
* SHORTDESCRIPTION, "A top level window with a window manager border",
* "random attribute","random object value"
* }
* );
* </pre>
* The keywords correspond to <code>java.beans.BeanDescriptor</code> and
* <code>java.beans.FeatureDescriptor</code> properties, e.g. providing a value
* for displayName is comparable to <code>FeatureDescriptor.setDisplayName()</code>.
* Using createBeanDescriptor instead of the BeanDescriptor
* constructor and set methods is preferrable in that it regularizes
* the code in a <code>java.beans.BeanInfo.getBeanDescriptor()</code>
* method implementation. One can use <code>createBeanDescriptor</code>
* to set <code>FeatureDescriptor</code> attributes, as in "random attribute"
* "random object value".
*
* @see java.beans#BeanInfo
* @see java.beans#PropertyDescriptor
*/
public static BeanDescriptor createBeanDescriptor(Class<?> cls, Object[] args)
{
Class<?> customizerClass = null;
/* For reasons I don't understand, customizerClass is a
* readOnly property. So we have to find it and pass it
* to the constructor here.
*/
for(int i = 0; i < args.length; i += 2) {
if (CUSTOMIZERCLASS.equals((String)args[i])) {
customizerClass = (Class)args[i + 1];
break;
}
}
BeanDescriptor bd = new BeanDescriptor(cls, customizerClass);
for(int i = 0; i < args.length; i += 2) {
String key = (String)args[i];
Object value = args[i + 1];
initFeatureDescriptor(bd, key, value);
}
return bd;
}
static private PropertyDescriptor createReadOnlyPropertyDescriptor(
String name, Class<?> cls) throws IntrospectionException {
Method readMethod = null;
String base = capitalize(name);
Class<?>[] parameters = new Class<?>[0];
// Is it a boolean?
try {
readMethod = cls.getMethod("is" + base, parameters);
} catch (Exception ex) {}
if (readMethod == null) {
try {
// Try normal accessor pattern.
readMethod = cls.getMethod("get" + base, parameters);
} catch (Exception ex2) {}
}
if (readMethod != null) {
return new PropertyDescriptor(name, readMethod, null);
}
try {
// Try indexed accessor pattern.
parameters = new Class<?>[1];
parameters[0] = int.class;
readMethod = cls.getMethod("get" + base, parameters);
} catch (NoSuchMethodException nsme) {
throw new IntrospectionException(
"cannot find accessor method for " + name + " property.");
}
return new IndexedPropertyDescriptor(name, null, null, readMethod, null);
}
// Modified methods from java.beans.Introspector
private static String capitalize(String s) {
if (s.length() == 0) {
return s;
}
char chars[] = s.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
}
/**
* Fatal errors are handled by calling this method.
*/
public static void throwError(Exception e, String s) {
throw new Error(e.toString() + " " + s);
}
}

@ -33,6 +33,7 @@ include GensrcCharsetMapping.gmk
include GensrcCharsetCoder.gmk
include GensrcBuffer.gmk
include GensrcExceptions.gmk
include GensrcVarHandles.gmk
include GensrcModuleLoaderMap.gmk
################################################################################

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2016, 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
@ -62,7 +62,9 @@ endif
ifeq ($(OPENJDK_TARGET_OS), windows)
PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/classes/sun/awt/windows
else
endif
ifeq ($(filter $(OPENJDK_TARGET_OS), windows macosx), )
PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources
endif

@ -0,0 +1,162 @@
#
# Copyright (c) 2015, 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.
#
GENSRC_VARHANDLES :=
VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
VARHANDLES_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/invoke
################################################################################
# Setup a rule for generating a VarHandle java class
# Param 1 - Variable declaration prefix
# Param 2 - Type with first letter capitalized
define GenerateVarHandle
$1_Type := $2
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
ifneq ($$(findstring $$($1_Type), Object Int Long), )
$1_ARGS += -KCAS
endif
ifneq ($$(findstring $$($1_Type), Int Long), )
$1_ARGS += -KAtomicAdd
endif
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
ifeq ($$($1_Type), Object)
$$(eval $1_type := $$($1_Type))
else
$$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
endif
$$(call MakeDir, $$(@D))
$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
$$($1_ARGS) < $$< > $$@
GENSRC_VARHANDLES += $$($1_FILENAME)
endef
################################################################################
################################################################################
# Setup a rule for generating a VarHandleByteArray java class
# Param 1 - Variable declaration prefix
# Param 2 - Type with first letter capitalized
define GenerateVarHandleByteArray
$1_Type := $2
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
ifeq ($$($1_Type), Short)
$1_type := short
$1_BoxType := $$($1_Type)
$1_rawType := $$($1_type)
$1_RawType := $$($1_Type)
$1_RawBoxType := $$($1_BoxType)
endif
ifeq ($$($1_Type), Char)
$1_type := char
$1_BoxType := Character
$1_rawType := $$($1_type)
$1_RawType := $$($1_Type)
$1_RawBoxType := $$($1_BoxType)
endif
ifeq ($$($1_Type), Int)
$1_type := int
$1_BoxType := Integer
$1_rawType := $$($1_type)
$1_RawType := $$($1_Type)
$1_RawBoxType := $$($1_BoxType)
$1_ARGS += -KCAS
$1_ARGS += -KAtomicAdd
endif
ifeq ($$($1_Type), Long)
$1_type := long
$1_BoxType := $$($1_Type)
$1_rawType := $$($1_type)
$1_RawType := $$($1_Type)
$1_RawBoxType := $$($1_BoxType)
$1_ARGS += -KCAS
$1_ARGS += -KAtomicAdd
endif
ifeq ($$($1_Type), Float)
$1_type := float
$1_BoxType := $$($1_Type)
$1_rawType := int
$1_RawType := Int
$1_RawBoxType := Integer
$1_ARGS += -KCAS
$1_ARGS += -KfloatingPoint
endif
ifeq ($$($1_Type), Double)
$1_type := double
$1_BoxType := $$($1_Type)
$1_rawType := long
$1_RawType := Long
$1_RawBoxType := Long
$1_ARGS += -KCAS
$1_ARGS += -KfloatingPoint
endif
$$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
$$(call MakeDir, $$(@D))
$(TOOL_SPP) -nel -K$$($1_type) \
-Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
-DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
$$($1_ARGS) < $$< > $$@
GENSRC_VARHANDLES += $$($1_FILENAME)
endef
################################################################################
# List the types to generate source for, with capitalized first letter
VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Object
$(foreach t, $(VARHANDLES_TYPES), \
$(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
# List the types to generate source for, with capitalized first letter
VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
GENSRC_JAVA_BASE += $(GENSRC_VARHANDLES)

@ -204,6 +204,7 @@ endif
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \
# Why does libawt need java.base headers?
LIBAWT_CFLAGS += -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
-I$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
@ -311,6 +312,10 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
#
ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
LIBAWT_XAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
endif
LIBAWT_XAWT_EXCLUDES := medialib
LIBAWT_XAWT_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBAWT_XAWT_DIRS) -type d)) \
@ -883,6 +888,13 @@ ifndef BUILD_HEADLESS_ONLY
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/macosx/native/libsplashscreen
endif
ifneq ($(filter $(OPENJDK_TARGET_OS),linux solaris aix), )
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/unix/native/common/awt/systemscale
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/native/common/awt/systemscale
endif
LIBSPLASHSCREEN_CFLAGS += -DSPLASHSCREEN -DPNG_NO_MMX_CODE -DPNG_ARM_NEON_OPT=0 \
$(addprefix -I, $(LIBSPLASHSCREEN_DIRS)) \
$(LIBJAVA_HEADER_FLAGS) \
@ -923,7 +935,7 @@ ifndef BUILD_HEADLESS_ONLY
-framework JavaNativeFoundation
else ifeq ($(OPENJDK_TARGET_OS), windows)
LIBSPLASHSCREEN_LDFLAGS := -delayload:user32.dll
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib
LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib
else
LIBSPLASHSCREEN_LIBS += $(X_LIBS) -lX11 -lXext $(LIBM) -lpthread
endif

@ -0,0 +1,53 @@
#
# Copyright (c) 2016, 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.
#
include LibCommon.gmk
################################################################################
$(eval $(call SetupNativeCompilation,BUILD_LIBRMI, \
LIBRARY := rmi, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(JDK_TOPDIR)/src/java.rmi/share/native/librmi, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.rmi, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/librmi/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS_unix := -ljvm, \
LIBS_windows := jvm.lib, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=rmi.dll" \
-D "JDK_INTERNAL_NAME=rmi" \
-D "JDK_FTYPE=0x2L", \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/librmi, \
))
$(BUILD_LIBRMI): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBRMI)
################################################################################

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2016, 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
@ -150,6 +150,12 @@ SUNWprivate_1.1 {
Java_sun_awt_X11_XlibWrapper_XdbeEndIdiom;
Java_sun_awt_X11_XDesktopPeer_init;
Java_sun_awt_X11_XDesktopPeer_gnome_1url_1show;
Java_sun_awt_X11_XTaskbarPeer_init;
Java_sun_awt_X11_XTaskbarPeer_runloop;
Java_sun_awt_X11_XTaskbarPeer_setBadge;
Java_sun_awt_X11_XTaskbarPeer_setUrgent;
Java_sun_awt_X11_XTaskbarPeer_updateProgress;
Java_sun_awt_X11_XTaskbarPeer_setNativeMenu;
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl;
Java_sun_awt_X11_XRobotPeer_keyPressImpl;
Java_sun_awt_X11_XRobotPeer_keyReleaseImpl;

@ -259,7 +259,6 @@ SUNWprivate_1.1 {
Java_java_io_Console_istty;
Java_java_io_Console_encoding;
Java_java_io_Console_echo;
Java_sun_misc_GC_maxObjectInspectionAge;
Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
Java_sun_reflect_NativeMethodAccessorImpl_invoke0;
Java_sun_reflect_Reflection_getCallerClass__;
@ -283,8 +282,8 @@ SUNWprivate_1.1 {
Java_jdk_internal_loader_BootLoader_getSystemPackageNames;
Java_jdk_internal_loader_BootLoader_setBootLoaderUnnamedModule0;
Java_sun_misc_VMSupport_initAgentProperties;
Java_sun_misc_VMSupport_getVMTemporaryDirectory;
Java_jdk_internal_vm_VMSupport_initAgentProperties;
Java_jdk_internal_vm_VMSupport_getVMTemporaryDirectory;
# ZipFile.c needs this one
throwFileNotFoundException;

@ -0,0 +1,31 @@
#
# Copyright (c) 2016, 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.
#
SUNWprivate_1.1 {
global:
Java_sun_rmi_transport_GC_maxObjectInspectionAge;
local:
*;
};

@ -42,6 +42,8 @@ SUNWprivate_1.1 {
SplashInit;
SplashClose;
SplashSetFileJarName;
SplashSetScaleFactor;
SplashGetScaledImageName;
local:
*;
};

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, 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
@ -786,10 +786,10 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
return keyName;
}
private String getTarget(String qName, String path, String calType, String context, String width) {
// qName
private String getTarget(String path, String calType, String context, String width) {
// Target qName
int lastSlash = path.lastIndexOf('/');
qName = path.substring(lastSlash+1);
String qName = path.substring(lastSlash+1);
int bracket = qName.indexOf('[');
if (bracket != -1) {
qName = qName.substring(0, bracket);
@ -885,7 +885,7 @@ class LDMLParseHandler extends AbstractLDMLHandler<Object> {
String[] tmp = keyName.split(",", 3);
String calType = currentCalendarType.lname();
String src = calType+"."+tmp[0];
String target = getTarget(containerqName,
String target = getTarget(
entry.getKey(),
calType,
tmp[1].length()>0 ? tmp[1] : currentContext,

@ -1,101 +0,0 @@
/*
* Copyright (c) 1998, 2013, 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 build.tools.swingbeaninfo;
import java.util.HashMap;
/**
* Class that holds information for populating a FeatureDescriptor. For the class,
* This information represents the BeanDescriptor, for a property, it represents
* a PropertyDescriptor.
*/
public class DocBeanInfo {
// Values of the BeanFlags
public static final int BOUND = 1;
public static final int EXPERT = 2;
public static final int CONSTRAINED = 4;
public static final int HIDDEN = 8;
public static final int PREFERRED = 16 ;
public String name;
public int beanflags;
public String desc;
public String displayname;
public String propertyeditorclass;
public String customizerclass;
public HashMap attribs;
public HashMap enums;
public DocBeanInfo(){}
public DocBeanInfo(String p, int flags, String d,
String displayname, String pec, String cc,
HashMap attribs, HashMap enums) {
this.name = p;
this.beanflags = flags;
this.desc = d;
this.displayname = displayname;
this.propertyeditorclass = pec;
this.customizerclass = cc;
this.attribs = attribs;
this.enums = enums;
}
public String toString() {
StringBuffer buffer = new StringBuffer("*****");
buffer.append("\nProperty: " + name);
buffer.append("\tDescription: " + desc);
buffer.append("\nDisplayname: " + displayname);
buffer.append("\nPropertyEditorClass: " + propertyeditorclass);
buffer.append("\nCustomizerClass: " + customizerclass);
if ((beanflags & BOUND) != 0)
buffer.append("\nBound: true");
if ((beanflags & EXPERT) != 0)
buffer.append("\nExpert: true");
if ((beanflags & CONSTRAINED) != 0)
buffer.append("\nConstrained: true");
if ((beanflags & HIDDEN) !=0)
buffer.append("\nHidden: true");
if ((beanflags & PREFERRED) !=0)
if (attribs != null)
buffer.append(attribs.toString());
if (enums != null)
buffer.append(enums.toString());
return buffer.toString();
}
}

@ -1,447 +0,0 @@
/*
* Copyright (c) 1998, 2013, 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 build.tools.swingbeaninfo;
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.RootDoc;
import com.sun.javadoc.Tag;
import java.beans.Introspector;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.StringTokenizer;
/**
* Properties supported and tag syntax:
*
* @beaninfo
* bound: flag
* constrained: flag
* expert: flag
* hidden: flag
* preferred: flag
* description: string
* displayname: string
* propertyeditorclass: string (with dots: foo.bar.MyPropertyEditor
* customizerclass: string (w/dots: foo.bar.MyCustomizer)
* attribute: key1 value1
* attribute: key2 value2
*
* TODO: getValue and genDocletInfo needs some cleaning.
*
* @author Hans Muller
* @author Rich Schiavi
* @author Mark Davidson
*/
public class GenDocletBeanInfo {
static String[] ATTRIBUTE_NAMES = { "bound",
"constrained",
"expert",
"hidden",
"preferred",
"displayname",
"propertyeditorclass",
"customizerclass",
"displayname",
"description",
"enum",
"attribute" };
private static boolean DEBUG = false;
private static String fileDir = "";
private static String templateDir = "";
public static final String TRUE = "true";
public static final String FALSE = "false";
/**
* Method called from the javadoc environment to determint the options length.
* Doclet options:
* -t template location
* -d outputdir
* -x true Enable debug output.
*/
public static int optionLength(String option) {
// remind: this needs to be cleaned up
if (option.equals("-t"))
return 2;
if (option.equals("-d"))
return 2;
if (option.equals("-x"))
return 2;
return 0;
}
/** @beaninfo
* bound:true
* constrained:false
* expert:true
* hidden:true
* preferred:false
* description: the description of this method can
* do all sorts of funky things. if it \n
* is indented like this, we have to remove
* all char spaces greater than 2 and also any hard-coded \n
* newline characters and all newlines
* displayname: theString
* propertyeditorclass: foo.bar.MyPropertyEditorClass
* customizerclass: foo.bar.MyCustomizerClass
* attribute:key1 value1
* attribute: key2 value2
*
*/
public static boolean start(RootDoc doc) {
readOptions(doc.options());
if (templateDir.length() == 0) {
System.err.println("-t option not specified");
return false;
}
if (fileDir.length() == 0) {
System.err.println("-d option not specified");
return false;
}
GenSwingBeanInfo generator = new GenSwingBeanInfo(fileDir, templateDir, DEBUG);
Hashtable dochash = new Hashtable();
DocBeanInfo dbi;
/* "javadoc Foo.java Bar.java" will return:
* "Foo Foo.I1 Foo.I2 Bar Bar.I1 Bar.I2"
* i.e., with all the innerclasses of classes specified in the command
* line. We don't want to generate BeanInfo for any of these inner
* classes, so we ignore these by remembering what the last outer
* class was. A hack, I admit, but makes the build faster.
*/
String previousClass = null;
ClassDoc[] classes = doc.classes();
for (int cnt = 0; cnt < classes.length; cnt++) {
String className = classes[cnt].qualifiedName();
if (previousClass != null &&
className.startsWith(previousClass) &&
className.charAt(previousClass.length()) == '.') {
continue;
}
previousClass = className;
// XXX - debug
System.out.println("\n>>> Generating beaninfo for " + className + "...");
// Examine the javadoc tags and look for the the @beaninfo tag
// This first block looks at the javadoc for the class
Tag[] tags = classes[cnt].tags();
for (int i = 0; i < tags.length; i++) {
if (tags[i].kind().equalsIgnoreCase("@beaninfo")) {
if (DEBUG)
System.out.println("GenDocletBeanInfo: found @beaninfo tagged Class: " + tags[i].text());
dbi = genDocletInfo(tags[i].text(), classes[cnt].name());
dochash.put(dbi.name, dbi);
break;
}
}
// This block looks at the javadoc for the class methods.
int startPos = -1;
MethodDoc[] methods = classes[cnt].methods();
for (int j = 0; j < methods.length; j++) {
// actually don't "introspect" - look for all
// methods with a @beaninfo tag
tags = methods[j].tags();
for (int x = 0; x < tags.length; x++){
if (tags[x].kind().equalsIgnoreCase("@beaninfo")){
if ((methods[j].name().startsWith("get")) ||
(methods[j].name().startsWith("set")))
startPos = 3;
else if (methods[j].name().startsWith("is"))
startPos = 2;
else
startPos = 0;
String propDesc =
Introspector.decapitalize((methods[j].name()).substring(startPos));
if (DEBUG)
System.out.println("GenDocletBeanInfo: found @beaninfo tagged Method: " + tags[x].text());
dbi = genDocletInfo(tags[x].text(), propDesc);
dochash.put(dbi.name, dbi);
break;
}
}
}
if (DEBUG) {
// dump our classes doc beaninfo
System.out.println(">>>>DocletBeanInfo for class: " + classes[cnt].name());
Enumeration e = dochash.elements();
while (e.hasMoreElements()) {
DocBeanInfo db = (DocBeanInfo)e.nextElement();
System.out.println(db.toString());
}
}
// Use the generator to create the beaninfo code for the class.
generator.genBeanInfo(classes[cnt].containingPackage().name(),
classes[cnt].name(), dochash);
// reset the values!
dochash.clear();
} // end for loop
return true;
}
/**
* Reads the command line options.
* Side Effect, sets class variables templateDir, fileDir and DEBUG
*/
private static void readOptions(String[][] options) {
// Parse the command line args
for (int i = 0; i < options.length; i++){
if (options[i][0].equals("-t")) {
templateDir = options[i][1];
} else if (options[i][0].equals("-d")) {
fileDir = options[i][1];
} else if (options[i][0].equals("-x")){
if (options[i][1].equals("true"))
DEBUG=true;
else
DEBUG=false;
}
}
}
/**
* Create a "BeanInfo" data structure from the tag. This is a data structure
* which contains all beaninfo data for a method or a class.
*
* @param text All the text after the @beaninfo tag.
* @param name Name of the property i.e., mnemonic for setMnemonic
*/
private static DocBeanInfo genDocletInfo(String text, String name) {
int beanflags = 0;
String desc = "null";
String displayname = "null";
String propertyeditorclass = "null";
String customizerclass = "null";
String value = "null";
HashMap attribs = null;
HashMap enums = null;
int index;
for (int j = 0; j < ATTRIBUTE_NAMES.length; j++){
index = 0;
if ((index = text.indexOf(ATTRIBUTE_NAMES[j])) != -1){
value = getValue((text).substring(index),ATTRIBUTE_NAMES[j]);
if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("attribute")) {
attribs = getAttributeMap(value, " ");
}
if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("enum")) {
enums = getAttributeMap(value, " \n");
}
else if (ATTRIBUTE_NAMES[j].equals("displayname")){
displayname = value;
}
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("propertyeditorclass")) {
propertyeditorclass = value;
}
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("customizerclass")){
customizerclass = value;
}
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("bound"))
&& (value.equalsIgnoreCase(TRUE)))
beanflags = beanflags | DocBeanInfo.BOUND;
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("expert"))
&& (value.equalsIgnoreCase(TRUE)))
beanflags = beanflags | DocBeanInfo.EXPERT;
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("constrained"))
&& (value.equalsIgnoreCase(TRUE)))
beanflags = beanflags | DocBeanInfo.CONSTRAINED;
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("hidden"))
&& (value.equalsIgnoreCase(TRUE)))
beanflags = beanflags | DocBeanInfo.HIDDEN;
else if ((ATTRIBUTE_NAMES[j].equalsIgnoreCase("preferred"))
&& (value.equalsIgnoreCase(TRUE)))
beanflags = beanflags | DocBeanInfo.PREFERRED;
else if (ATTRIBUTE_NAMES[j].equalsIgnoreCase("description")){
desc = value;
}
}
}
/** here we create our doclet-beaninfo data structure, which we read in
* later if it has anything worthwhile
*/
// Construct a new Descriptor class
return new DocBeanInfo(name, beanflags, desc,displayname,
propertyeditorclass, customizerclass,
attribs, enums);
}
/**
* Parses the substring and returns the cleaned up value for the attribute.
* @param substring Full String of the attrib tag.
* i.e., "attribute: visualUpdate true" will return "visualUpdate true";
*/
private static String getValue(String substring, String prop) {
StringTokenizer t;
String value = "null";
try {
/** if the ATTRIBUTE_NAMES is NOT the description, then we
* parse until newline
* if it is the description we read until the next token
* and then look for a match in the last MAXMATCH index
* and truncate the description
* if it is the attribute we wead until no more
*/
if (prop.equalsIgnoreCase("attribute")){
StringBuffer tmp = new StringBuffer();
try {
t = new StringTokenizer(substring, " :\n");
t.nextToken().trim();//the prop
// we want to return : key1 value1 key2 value2
while (t.hasMoreTokens()){
tmp.append(t.nextToken().trim()).append(" ");
tmp.append(t.nextToken().trim()).append(" ");
String test = t.nextToken().trim();
if (!(test.equalsIgnoreCase("attribute")))
break;
}
} catch (Exception e){
}
value = tmp.toString();
}
else if (prop.equalsIgnoreCase("enum")){
t = new StringTokenizer(substring, ":");
t.nextToken().trim(); // the prop we already know
StringBuffer tmp = new StringBuffer(t.nextToken().trim());
for (int i = 0; i < ATTRIBUTE_NAMES.length; i++){
if (tmp.toString().endsWith(ATTRIBUTE_NAMES[i])){
int len = ATTRIBUTE_NAMES[i].length();
// trim off that
tmp.setLength(tmp.length() - len);
break;
}
}
value = tmp.toString();
}
else if (prop.equalsIgnoreCase("description")){
t = new StringTokenizer(substring, ":");
t.nextToken().trim(); // the prop we already know
StringBuffer tmp = new StringBuffer(t.nextToken().trim());
for (int i = 0; i < ATTRIBUTE_NAMES.length; i++){
if (tmp.toString().endsWith(ATTRIBUTE_NAMES[i])){
int len = ATTRIBUTE_NAMES[i].length();
// trim off that
tmp.setLength(tmp.length() - len);
break;
}
}
value = hansalizeIt(tmp.toString());
}
else {
// Single value properties like bound: true
t = new StringTokenizer(substring, ":\n");
t.nextToken().trim(); // the prop we already know
value = t.nextToken().trim();
}
// now we need to look for a match of any of the
// property
return value;
}
catch (Exception e){
return "invalidValue";
}
}
/**
* Creates a HashMap containing the key value pair for the parsed values
* of the "attributes" and "enum" tags.
* ie. For attribute value: visualUpdate true
* The HashMap will have key: visualUpdate, value: true
*/
private static HashMap getAttributeMap(String str, String delim) {
StringTokenizer t = new StringTokenizer(str, delim);
HashMap map = null;
String key;
String value;
int num = t.countTokens()/2;
if (num > 0) {
map = new HashMap();
for (int i = 0; i < num; i++) {
key = t.nextToken().trim();
value = t.nextToken().trim();
map.put(key, value);
}
}
return map;
}
// looks for extra spaces, \n hard-coded and invisible,etc
private static String hansalizeIt(String from){
char [] chars = from.toCharArray();
int len = chars.length;
int toss = 0;
// remove double spaces
for (int i = 0; i < len; i++){
if ((chars[i] == ' ')) {
if (i+1 < len) {
if ((chars[i+1] == ' ' ) || (chars[i+1] == '\n'))
{
--len;
System.arraycopy(chars,i+1,chars,i,len-i);
--i;
}
}
}
if (chars[i] == '\n'){
chars[i] = ' ';
i -= 2;
}
if (chars[i] == '\\') {
if (i+1 < len) {
if (chars[i+1] == 'n'){
chars[i+1] = ' ';
--len;
System.arraycopy(chars,i+1, chars,i, len-i);
--i;
}
}
}
}
return new String(chars,0,len);
}
}

@ -1,532 +0,0 @@
/*
* Copyright (c) 1998, 2013, 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 build.tools.swingbeaninfo;
import java.beans.BeanInfo;
import java.beans.BeanDescriptor;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Iterator;
/**
* A utlity for generating a BeanInfo source file from a template and a
* Hashtable with hints that were generated from a doclet.
* it's neccessary to write things like the per property descriptions
* by hand. To run the application:
* <pre>
* java GenSwingBeanInfo <class name>
* </pre>
* Code for a bean info class is written to out. If the class is
* swing package, you don't need to fully specify its name.
*
* @author Hans Muller
* @author Rich Schiavi
* @author Mark Davidson
*/
public class GenSwingBeanInfo {
private final static String BEANINFO_SUFFIX = "BeanInfo.java";
// Tokens in @(...)
private final static String TOK_BEANPACKAGE = "BeanPackageName";
private final static String TOK_BEANCLASS = "BeanClassName";
private final static String TOK_BEANOBJECT = "BeanClassObject";
private final static String TOK_CLASSDESC = "ClassDescriptors";
private final static String TOK_BEANDESC = "BeanDescription";
private final static String TOK_PROPDESC = "BeanPropertyDescriptors";
private final static String TOK_ENUMVARS = "EnumVariables";
private String enumcode; // Generated code for enumerated properties.
private boolean DEBUG = false;
private String fileDir;
private String templateFilename;
/**
* Public constructor
* @param fileDir Location to put the generated source files.
* @param templateFilename Location of the BeanInfo template
* @param debug Flag to turn on debugging
*/
public GenSwingBeanInfo(String fileDir, String templateFilename, boolean debug) {
this.fileDir = fileDir;
this.templateFilename = templateFilename;
this.DEBUG = debug;
}
/**
* Opens a BeanInfo PrintStream for the class.
*/
private PrintStream initOutputFile(String classname) {
try {
OutputStream out = new FileOutputStream(fileDir + File.separator + classname + BEANINFO_SUFFIX);
BufferedOutputStream bout = new BufferedOutputStream(out);
return new PrintStream(out);
} catch (IOException e){
// System.err.println("GenSwingBeanInfo: " + e.toString());
}
return null;
}
private static void messageAndExit(String msg) {
System.err.println("\n" + msg);
System.exit(1);
}
/**
* Load the contents of the BeanInfo template into a string and
* return the string.
*/
private String loadTemplate() {
String template = "<no template>";
try {
File file = new File(templateFilename);
DataInputStream stream = new DataInputStream(new FileInputStream(file));
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
int c;
while((c = reader.read()) != -1) {
buffer.append((char)c);
}
template = buffer.toString();
reader.close();
} catch (IOException e) {
System.out.println(e.getMessage());
messageAndExit("GenSwingBeanInfo: Couldn't load template: " + templateFilename + e);
}
return template;
}
/**
* Generates a string for the BeanDescriptor
*/
private String genBeanDescriptor(DocBeanInfo dbi) {
String code = "";
int beanflags = dbi.beanflags;
// we support export, hidden, preferred
if ((beanflags & DocBeanInfo.EXPERT) != 0)
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
/* 1.2 only - make sure build flag build using 1.2 */
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
if (!(dbi.customizerclass.equals("null")))
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
if (dbi.attribs != null) {
code += genAttributes(dbi.attribs);
}
return code;
}
/**
* Generates the code for the attributes table.
*/
private String genAttributes(HashMap attribs) {
StringBuffer code = new StringBuffer();
String key;
String value;
Iterator iterator = attribs.keySet().iterator();
while(iterator.hasNext()) {
key = (String)iterator.next();
value = (String)attribs.get(key);
if (value.equals("true") || value.equals("false")) {
// Substitute the "true" and "false" for codegen Boolean values.
if(value.equals("true"))
value = "Boolean.TRUE";
else
value = "Boolean.FALSE";
code.append(" \"").append(key).append("\", ").append(value).append(",\n");
} else {
code.append(" \"").append(key).append("\", \"").append(value).append("\",\n");
}
}
return code.toString();
}
/**
* Generates the code for the enumeration.
* XXX - side effect: Modifies the enumcode field variable.
*/
private String genEnumeration(String propName, HashMap enums) {
String objectName = propName + "Enumeration";
String key;
String value;
StringBuffer code = new StringBuffer("\n\t\tObject[] ");
code.append(objectName).append(" = new Object[] { \n");
Iterator iterator = enums.keySet().iterator();
while(iterator.hasNext()) {
key = (String)iterator.next();
value = (String)enums.get(key);
code.append("\t\t\t\"").append(key).append("\" , new Integer(");
code.append(value).append("), \"").append(value).append("\",\n");
}
// Close the statically initialized Object[]
code.replace(code.length() - 2, code.length(), "\n\t\t};\n");
// Add this string to the enumeration code.
enumcode += code.toString();
// Return the PropertyDescriptor init string;
return " \"enumerationValues\", " + objectName + ",\n";
}
/**
* Generate the createPropertyDescriptor() calls, one per property.
* A fully specified createPropertyDescriptor() call looks like this:
* <pre>
* createPropertyDescriptor("contentPane", new Object[] {
* BOUND, Boolean.TRUE,
* CONSTRAINED, Boolean.TRUE,
* PROPERTYEDITORCLASS, package.MyEditor.cl
* WRITEMETHOD, "setContentPane",
* DISPLAYNAME, "contentPane",
* EXPERT, Boolean.FALSE,
* HIDDEN, Boolean.FALSE,
* PREFERRED, Boolean.TRUE,
* SHORTDESCRIPTION, "A top level window with a window manager border",
* "random attribute","random value"
* }
* );
* </pre>
*
* @param info The actual BeanInfo class generated from from the Intospector.
* @param dochash Set of DocBeanInfo pairs for each property. This information
* is used to suplement the instrospected properties.
* @return A snippet of source code which would construct all the PropertyDescriptors.
*/
private String genPropertyDescriptors(BeanInfo info, Hashtable dochash) {
String code = "";
enumcode = " "; // code for enumerated properties.
PropertyDescriptor[] pds = info.getPropertyDescriptors();
boolean hash_match = false;
DocBeanInfo dbi = null;
for(int i = 0; i < pds.length; i++) {
if (pds[i].getReadMethod() != null) {
code += "\ncreatePropertyDescriptor(\"" + pds[i].getName() + "\", new Object[] {\n";
if (DEBUG)
System.out.println("Introspected propertyDescriptor: " + pds[i].getName());
if (dochash.size() > 0 && dochash.containsKey(pds[i].getName())) {
dbi = (DocBeanInfo)dochash.remove(pds[i].getName());
// override/set properties on this *introspected*
// BeanInfo pds using our DocBeanInfo class values
setDocInfoProps(dbi, pds[i]);
hash_match = true;
if (DEBUG)
System.out.println("DocBeanInfo class exists for propertyDescriptor: " + pds[i].getName() + "\n");
} else {
hash_match = false;
}
// Do I need to do anything with this property descriptor
if (hash_match) {
if ((dbi.beanflags & DocBeanInfo.BOUND) != 0) {
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.TRUE,\n";
} else {
code += " sun.swing.BeanInfoUtils.BOUND, Boolean.FALSE,\n";
}
}
if (pds[i].isConstrained()) {
code += " sun.swing.BeanInfoUtils.CONSTRAINED, Boolean.TRUE,\n";
}
if (pds[i].getPropertyEditorClass() != null) {
String className = pds[i].getPropertyEditorClass().getName();
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + className + ".class,\n";
} else if ((hash_match) && (!(dbi.propertyeditorclass.equals("null")))) {
code += " sun.swing.BeanInfoUtils.PROPERTYEDITORCLASS, " + dbi.propertyeditorclass + ".class,\n";
}
if ((hash_match) && (!(dbi.customizerclass.equals("null")))) {
code += " sun.swing.BeanInfoUtils.CUSTOMIZERCLASS, " + dbi.customizerclass + ".class,\n";
}
if ((hash_match) && (dbi.enums != null)) {
code += genEnumeration(pds[i].getName(), dbi.enums);
}
if (!pds[i].getDisplayName().equals(pds[i].getName())) {
code += " sun.swing.BeanInfoUtils.DISPLAYNAME, \"" + pds[i].getDisplayName() + "\",\n";
}
if (pds[i].isExpert()) {
code += " sun.swing.BeanInfoUtils.EXPERT, Boolean.TRUE,\n";
}
if (pds[i].isHidden()) {
code += " sun.swing.BeanInfoUtils.HIDDEN, Boolean.TRUE,\n";
}
if (pds[i].isPreferred()) {
code += " sun.swing.BeanInfoUtils.PREFERRED, Boolean.TRUE,\n";
}
// user attributes
if (hash_match) {
if (dbi.attribs != null) {
code += genAttributes(dbi.attribs);
}
}
code += " sun.swing.BeanInfoUtils.SHORTDESCRIPTION, \"" + pds[i].getShortDescription() + "\",\n";
// Print the closing brackets. If this is the last array initializer,
// don't print the trailing comma.
if (i == (pds.length - 1)) {
code += " }\n)\n";
} else {
code += " }\n),\n";
}
} // end if ( readMethod != null )
} // end for
return code;
}
/**
* Sets properties from the BeanInfo supplement on the
* introspected PropertyDescriptor
*/
private void setDocInfoProps(DocBeanInfo dbi, PropertyDescriptor pds) {
int beanflags = dbi.beanflags;
if ((beanflags & DocBeanInfo.BOUND) != 0)
pds.setBound(true);
if ((beanflags & DocBeanInfo.EXPERT) != 0)
pds.setExpert(true);
if ((beanflags & DocBeanInfo.CONSTRAINED) != 0)
pds.setConstrained(true);
if ((beanflags & DocBeanInfo.HIDDEN) !=0)
pds.setHidden(true);
if ((beanflags & DocBeanInfo.PREFERRED) !=0)
pds.setPreferred(true);
if (!(dbi.desc.equals("null"))){
pds.setShortDescription(dbi.desc);
}
if (!(dbi.displayname.equals("null"))){
pds.setDisplayName(dbi.displayname);
}
}
/**
* Generates the BeanInfo source file using instrospection and a
* Hashtable full of hints. This the only public method in this class.
*
* @param classname Root name of the class. i.e., JButton
* @param dochash A hashtable containing the DocBeanInfo.
*/
public void genBeanInfo(String packageName, String classname, Hashtable dochash) {
// The following initial values are just examples. All of these
// fields are initialized below.
String beanClassName = "JInternalFrame";
String beanClassObject = "javax.swing.JInternalFrame.class";
String beanDescription = "<A description of this component>.";
String beanPropertyDescriptors = "<createSwingPropertyDescriptor code>";
String classPropertyDescriptors = "<createSwingClassPropertyDescriptor code>";
Class cls = getClass(packageName, classname);
if (cls == null){
messageAndExit("Can't find class: " + classname);
}
// Get the output stream.
PrintStream out = initOutputFile(classname);
// Run the Introspector and initialize the variables
BeanInfo beanInfo = null;
BeanDescriptor beanDescriptor = null;
try {
if (cls == javax.swing.JComponent.class) {
// Go all the way up the heirarchy for JComponent
beanInfo = Introspector.getBeanInfo(cls);
} else {
beanInfo = Introspector.getBeanInfo(cls, cls.getSuperclass());
}
beanDescriptor = beanInfo.getBeanDescriptor();
beanDescription = beanDescriptor.getShortDescription();
} catch (IntrospectionException e) {
messageAndExit("Introspection failed for " + cls.getName() + " " + e);
}
beanClassName = beanDescriptor.getName();
beanClassObject = cls.getName() + ".class";
if (DEBUG){
System.out.println(">>>>GenSwingBeanInfo class: " + beanClassName);
}
// Generate the Class BeanDescriptor information first
if (dochash.size() > 0) {
if (dochash.containsKey(beanClassName)) {
DocBeanInfo dbi = (DocBeanInfo)dochash.remove(beanClassName);
classPropertyDescriptors = genBeanDescriptor(dbi);
if (DEBUG)
System.out.println("ClassPropertyDescriptors: " + classPropertyDescriptors);
if (!(dbi.desc.equals("null")))
beanDescription = dbi.desc;
} else
beanDescription = beanDescriptor.getShortDescription();
} else
beanDescription = beanDescriptor.getShortDescription();
// Generate the Property descriptors
beanPropertyDescriptors = genPropertyDescriptors(beanInfo,dochash);
// Dump the template to out, substituting values for
// @(token) tokens as they're encountered.
int currentIndex = 0;
// not loading this to get around build issue for now
String template = loadTemplate();
// This loop substitutes the "@(...)" tags in the template with the ones for the
// current class.
while (currentIndex < template.length()) {
// Find the Token
int tokenStart = template.indexOf("@(", currentIndex);
if (tokenStart != -1) {
out.print(template.substring(currentIndex, tokenStart));
int tokenEnd = template.indexOf(")", tokenStart);
if (tokenEnd == -1) {
messageAndExit("Bad @(<token>) beginning at " + tokenStart);
}
String token = template.substring(tokenStart+2, tokenEnd);
if (token.equals(TOK_BEANCLASS)) {
out.print(beanClassName);
} else if (token.equals(TOK_CLASSDESC)) {
if (!(classPropertyDescriptors.equals("<createSwingClassPropertyDescriptor code>"))) {
printDescriptors(out, classPropertyDescriptors, template, tokenStart);
}
} else if (token.equals(TOK_BEANPACKAGE)){
out.print(packageName);
} else if (token.equals(TOK_BEANOBJECT)) {
out.print(beanClassObject);
} else if (token.equals(TOK_BEANDESC)) {
out.print(beanDescription);
} else if (token.equals(TOK_ENUMVARS)){
out.print(enumcode);
} else if (token.equals(TOK_PROPDESC)) {
printDescriptors(out, beanPropertyDescriptors, template, tokenStart);
} else if (token.equals("#")) {
// Ignore the @(#) Version Control tag if it exists.
} else {
messageAndExit("Unrecognized token @(" + token + ")");
}
currentIndex = tokenEnd + 1;
} else {
// tokenStart == -1 - We are finsihed.
out.print(template.substring(currentIndex, template.length()));
break;
}
}
out.close();
}
/**
* Returns the class from the package name and the class root name.
*
* @param packageName The name of the package of the containing class.
* @param rootname The root name of the class. i.e, JButton
* @return The class instance or null.
*/
private Class getClass(String packageName, String rootname) {
Class cls = null;
String classname = rootname;
if (packageName != null || !packageName.equals("")) {
classname = packageName + "." + rootname;
}
try {
cls = Class.forName(classname);
} catch (ClassNotFoundException e) {
// Fail silently.
}
return cls;
}
/**
* Prints the formated descriptors to the PrintStream
* @param out Open PrintStream
* @param s String descriptor
* @param template Template
* @param tokenStart Index into the template
*/
private void printDescriptors(PrintStream out, String s,
String template, int tokenStart) {
String indent = "";
// Find the newline that preceeds @(BeanPropertyDescriptors) to
// calculate the indent.
for (int i = tokenStart; i >= 0; i--) {
if (template.charAt(i) == '\n') {
char[] chars = new char[tokenStart - i];
for (int j = 0; j < chars.length; j++) {
chars[j] = ' ';
}
indent = new String(chars);
break;
}
}
int i = 0;
while(i < s.length()) {
int nlIndex = s.indexOf('\n', i);
out.print(s.substring(i, nlIndex+1));
out.print(indent);
i = nlIndex + 1;
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2016, 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
@ -146,7 +146,7 @@ class StringCoding {
}
@HotSpotIntrinsicCandidate
private static boolean hasNegatives(byte[] ba, int off, int len) {
public static boolean hasNegatives(byte[] ba, int off, int len) {
for (int i = off; i < off + len; i++) {
if (ba[i] < 0) {
return true;

@ -41,7 +41,7 @@ class InfoFromMemberName implements MethodHandleInfo {
private final int referenceKind;
InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
assert(member.isResolved() || member.isMethodHandleInvoke());
assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());
assert(member.referenceKindIsConsistentWith(referenceKind));
this.member = member;
this.referenceKind = referenceKind;
@ -79,7 +79,8 @@ class InfoFromMemberName implements MethodHandleInfo {
@Override
public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
if (member.isMethodHandleInvoke() && !member.isVarargs()) {
if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())
&& !member.isVarargs()) {
// This member is an instance of a signature-polymorphic method, which cannot be reflected
// A method handle invoker can come in either of two forms:
// A generic placeholder (present in the source code, and varargs)

@ -93,6 +93,16 @@ class Invokers {
return setCachedInvoker(INV_BASIC, invoker);
}
/*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
// TODO cache invoker
return makeVarHandleMethodInvoker(ak);
}
/*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
// TODO cache invoker
return makeVarHandleMethodExactInvoker(ak);
}
private MethodHandle cachedInvoker(int idx) {
return invokers[idx];
}
@ -117,6 +127,36 @@ class Invokers {
return invoker;
}
private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
MethodType mtype = targetType;
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.name(), mtype);
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
assert(checkVarHandleInvoker(invoker));
maybeCompileToBytecode(invoker);
return invoker;
}
private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
MethodType mtype = targetType;
MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.name(), mtype);
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
assert(checkVarHandleInvoker(invoker));
maybeCompileToBytecode(invoker);
return invoker;
}
/** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
private void maybeCompileToBytecode(MethodHandle invoker) {
final int EAGER_COMPILE_ARITY_LIMIT = 10;
@ -146,6 +186,16 @@ class Invokers {
return true;
}
private boolean checkVarHandleInvoker(MethodHandle invoker) {
MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class);
assert(invokerType.equals(invoker.type()))
: java.util.Arrays.asList(targetType, invokerType, invoker);
assert(invoker.internalMemberName() == null ||
invoker.internalMemberName().getMethodType().equals(targetType));
assert(!invoker.isVarargsCollector());
return true;
}
/**
* Find or create an invoker which passes unchanged a given number of arguments
* and spreads the rest from a trailing array argument.
@ -193,9 +243,9 @@ class Invokers {
Object[] appendixResult) {
int which;
switch (name) {
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
default: throw new InternalError("not invoker: "+name);
case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
default: throw new InternalError("not invoker: "+name);
}
LambdaForm lform;
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
@ -296,6 +346,199 @@ class Invokers {
return lform;
}
static MemberName varHandleInvokeLinkerMethod(String name,
MethodType mtype) {
LambdaForm lform;
if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
lform = varHandleMethodGenericLinkerHandleForm(name, mtype);
} else {
// TODO
throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
}
return lform.vmentry;
}
private static LambdaForm varHandleMethodGenericLinkerHandleForm(String name, MethodType mtype) {
// TODO Cache form?
final int THIS_VH = 0;
final int ARG_BASE = THIS_VH + 1;
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
int nameCursor = ARG_LIMIT;
final int VAD_ARG = nameCursor++;
final int CHECK_TYPE = nameCursor++;
final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
final int LINKER_CALL = nameCursor++;
Name[] names = new Name[LINKER_CALL + 1];
names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
for (int i = 0; i < mtype.parameterCount(); i++) {
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
}
names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[THIS_VH], names[VAD_ARG]);
Object[] outArgs = new Object[ARG_LIMIT + 1];
outArgs[0] = names[CHECK_TYPE];
for (int i = 0; i < ARG_LIMIT; i++) {
outArgs[i + 1] = names[i];
}
if (CHECK_CUSTOM != -1) {
names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
}
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
.basicType();
names[LINKER_CALL] = new Name(outCallType, outArgs);
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
ARG_LIMIT + 1, names);
lform.prepare();
return lform;
}
private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
// TODO Cache form?
final int THIS_MH = 0;
final int CALL_VH = THIS_MH + 1;
final int ARG_BASE = CALL_VH + 1;
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
int nameCursor = ARG_LIMIT;
final int VAD_ARG = nameCursor++;
final int CHECK_TYPE = nameCursor++;
final int GET_MEMBER = nameCursor++;
final int LINKER_CALL = nameCursor++;
MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
.basicType()
.appendParameterTypes(MemberName.class);
MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
try {
linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
Name[] names = new Name[LINKER_CALL + 1];
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
for (int i = 0; i < mtype.parameterCount(); i++) {
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
}
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
NamedFunction getter = speciesData.getterFunction(0);
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
outArgs[outArgs.length - 1] = names[GET_MEMBER];
names[LINKER_CALL] = new Name(linker, outArgs);
LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
ARG_LIMIT, names);
lform.prepare();
return lform;
}
private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
// TODO Cache form?
final int THIS_MH = 0;
final int CALL_VH = THIS_MH + 1;
final int ARG_BASE = CALL_VH + 1;
final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
int nameCursor = ARG_LIMIT;
final int VAD_ARG = nameCursor++;
final int CHECK_TYPE = nameCursor++;
final int LINKER_CALL = nameCursor++;
Name[] names = new Name[LINKER_CALL + 1];
names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
for (int i = 0; i < mtype.parameterCount(); i++) {
names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
}
BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
NamedFunction getter = speciesData.getterFunction(0);
names[VAD_ARG] = new Name(getter, names[THIS_MH]);
names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
Object[] outArgs = new Object[ARG_LIMIT];
outArgs[0] = names[CHECK_TYPE];
for (int i = 1; i < ARG_LIMIT; i++) {
outArgs[i] = names[i];
}
MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
.basicType();
names[LINKER_CALL] = new Name(outCallType, outArgs);
LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
ARG_LIMIT, names);
lform.prepare();
return lform;
}
/*non-public*/ static
@ForceInline
MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
MethodType expected = vad.symbolicMethodType;
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
if (mn == null)
throw vh.unsupported();
// TODO the following MH is not constant, cache in stable field array
// on VarForm?
MethodHandle mh = DirectMethodHandle.make(mn);
if (actual == expected) {
return mh;
}
else {
// Adapt to the actual (which should never fail since mh's method
// type is in the basic form), then to the expected (which my fail
// if the symbolic type descriptor does not match)
// TODO optimize for the case of actual.erased() == expected.erased()
return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
asType(expected.insertParameterTypes(0, VarHandle.class));
}
}
/*non-public*/ static
@ForceInline
void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
MethodType expected = vad.symbolicMethodType;
MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
if (actual != expected)
throw newWrongMethodTypeException(expected, actual);
}
/*non-public*/ static
@ForceInline
MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
if (mn == null) {
throw vh.unsupported();
}
return mn;
}
/*non-public*/ static
WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
// FIXME: merge with JVM logic for throwing WMTE
@ -415,7 +658,10 @@ class Invokers {
NF_checkExactType,
NF_checkGenericType,
NF_getCallSiteTarget,
NF_checkCustomized;
NF_checkCustomized,
NF_checkVarHandleGenericType,
NF_checkVarHandleExactType,
NF_getVarHandleMemberName;
static {
try {
NamedFunction nfs[] = {
@ -426,7 +672,13 @@ class Invokers {
NF_getCallSiteTarget = new NamedFunction(Invokers.class
.getDeclaredMethod("getCallSiteTarget", CallSite.class)),
NF_checkCustomized = new NamedFunction(Invokers.class
.getDeclaredMethod("checkCustomized", MethodHandle.class))
.getDeclaredMethod("checkCustomized", MethodHandle.class)),
NF_checkVarHandleGenericType = new NamedFunction(Invokers.class
.getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
NF_checkVarHandleExactType = new NamedFunction(Invokers.class
.getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
NF_getVarHandleMemberName = new NamedFunction(Invokers.class
.getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
};
// Each nf must be statically invocable or we get tied up in our bootstraps.
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));

@ -363,6 +363,23 @@ import java.util.Objects;
return false;
}
}
public boolean isVarHandleMethodInvoke() {
final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
final int negs = Modifier.STATIC;
if (testFlags(bits | negs, bits) &&
clazz == VarHandle.class) {
return isVarHandleMethodInvokeName(name);
}
return false;
}
public static boolean isVarHandleMethodInvokeName(String name) {
try {
VarHandle.AccessMode.valueOf(name);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
/** Utility method to query the modifier flags of this member. */
@ -538,6 +555,17 @@ import java.util.Objects;
if (isMethodHandleInvoke())
return;
}
if (m.getDeclaringClass() == VarHandle.class &&
isVarHandleMethodInvokeName(m.getName())) {
// The JVM did not reify this signature-polymorphic instance.
// Need a special case here.
// See comments on MethodHandleNatives.linkMethod.
MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
init(VarHandle.class, m.getName(), type, flags);
if (isVarHandleMethodInvoke())
return;
}
throw new LinkageError(m.toString());
}
assert(isResolved() && this.clazz != null);
@ -666,6 +694,16 @@ import java.util.Objects;
return mem;
}
static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
}
static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
mem.flags |= mods; // it's not resolved, but add these modifiers anyway
assert(mem.isVarHandleMethodInvoke()) : mem;
return mem;
}
// bare-bones constructor; the JVM will fill it in
MemberName() { }

@ -26,9 +26,11 @@
package java.lang.invoke;
import java.util.*;
import jdk.internal.HotSpotIntrinsicCandidate;
import java.util.Arrays;
import java.util.Objects;
import static java.lang.invoke.MethodHandleStatics.*;
/**
@ -92,14 +94,16 @@ import static java.lang.invoke.MethodHandleStatics.*;
* and {@code invoke} compile to an {@code invokevirtual} instruction.
* More unusually, the compiler must record the actual argument types,
* and may not perform method invocation conversions on the arguments.
* Instead, it must push them on the stack according to their own unconverted types.
* The method handle object itself is pushed on the stack before the arguments.
* The compiler then calls the method handle with a symbolic type descriptor which
* describes the argument and return types.
* Instead, it must generate instructions that push them on the stack according
* to their own unconverted types. The method handle object itself is pushed on
* the stack before the arguments.
* The compiler then generates an {@code invokevirtual} instruction that invokes
* the method handle with a symbolic type descriptor which describes the argument
* and return types.
* <p>
* To issue a complete symbolic type descriptor, the compiler must also determine
* the return type. This is based on a cast on the method invocation expression,
* if there is one, or else {@code Object} if the invocation is an expression
* if there is one, or else {@code Object} if the invocation is an expression,
* or else {@code void} if the invocation is a statement.
* The cast may be to a primitive type (but not {@code void}).
* <p>
@ -109,12 +113,12 @@ import static java.lang.invoke.MethodHandleStatics.*;
* {@code Void} except the null reference.
*
* <h1>Method handle invocation</h1>
* The first time a {@code invokevirtual} instruction is executed
* it is linked, by symbolically resolving the names in the instruction
* The first time an {@code invokevirtual} instruction is executed
* it is linked by symbolically resolving the names in the instruction
* and verifying that the method call is statically legal.
* This is true of calls to {@code invokeExact} and {@code invoke}.
* This also holds for calls to {@code invokeExact} and {@code invoke}.
* In this case, the symbolic type descriptor emitted by the compiler is checked for
* correct syntax and names it contains are resolved.
* correct syntax, and names it contains are resolved.
* Thus, an {@code invokevirtual} instruction which invokes
* a method handle will always link, as long
* as the symbolic type descriptor is syntactically well-formed
@ -163,7 +167,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* in a program which uses method handles.
* <p>
* Because method types contain "live" {@code Class} objects,
* method type matching takes into account both types names and class loaders.
* method type matching takes into account both type names and class loaders.
* Thus, even if a method handle {@code M} is created in one
* class loader {@code L1} and used in another {@code L2},
* method handle calls are type-safe, because the caller's symbolic type
@ -174,7 +178,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* and its type is assigned, while the resolution in {@code L2} happens
* when the {@code invokevirtual} instruction is linked.
* <p>
* Apart from the checking of type descriptors,
* Apart from type descriptor checks,
* a method handle's capability to call its underlying method is unrestricted.
* If a method handle is formed on a non-public method by a class
* that has access to that method, the resulting handle can be used
@ -196,7 +200,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
* Java code can create a method handle that directly accesses
* any method, constructor, or field that is accessible to that code.
* This is done via a reflective, capability-based API called
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
* {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}.
* For example, a static method handle can be obtained
* from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
* There are also conversion methods from Core Reflection API objects,

@ -1060,6 +1060,19 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
return mh;
}
static MethodHandle fakeVarHandleInvoke(MemberName method) {
// TODO caching, is it necessary?
MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
VarHandle.class, Object[].class);
MethodHandle mh = throwException(type);
mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
if (!method.getInvocationType().equals(mh.type()))
throw new InternalError(method.toString());
mh = mh.withInternalMemberName(method, false);
mh = mh.asVarargsCollector(Object[].class);
assert(method.isVarargs());
return mh;
}
/**
* Create an alias for the method handle which, when called,

@ -25,12 +25,15 @@
package java.lang.invoke;
import jdk.internal.ref.CleanerFactory;
import sun.invoke.util.Wrapper;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
import jdk.internal.ref.CleanerFactory;
/**
* The JVM interface for the method handles package is all here.
@ -367,8 +370,14 @@ class MethodHandleNatives {
Class<?> defc, String name, Object type,
Object[] appendixResult) {
try {
if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
if (refKind == REF_invokeVirtual) {
if (defc == MethodHandle.class) {
return Invokers.methodHandleInvokeLinkerMethod(
name, fixMethodType(callerClass, type), appendixResult);
} else if (defc == VarHandle.class) {
return varHandleOperationLinkerMethod(
name, fixMethodType(callerClass, type), appendixResult);
}
}
} catch (Throwable ex) {
if (ex instanceof LinkageError)
@ -400,6 +409,80 @@ class MethodHandleNatives {
}
}
/**
* Obtain the method to link to the VarHandle operation.
* This method is located here and not in Invokers to avoid
* intializing that and other classes early on in VM bootup.
*/
private static MemberName varHandleOperationLinkerMethod(String name,
MethodType mtype,
Object[] appendixResult) {
// Get the signature method type
MethodType sigType = mtype.basicType();
// Get the access kind from the method name
VarHandle.AccessMode ak;
try {
ak = VarHandle.AccessMode.valueOf(name);
} catch (IllegalArgumentException e) {
throw MethodHandleStatics.newInternalError(e);
}
// If not polymorphic in the return type, such as the compareAndSet
// methods that return boolean
if (ak.isPolyMorphicInReturnType) {
if (ak.returnType != mtype.returnType()) {
// The caller contains a different return type than that
// defined by the method
throw newNoSuchMethodErrorOnVarHandle(name, mtype);
}
// Adjust the return type of the signature method type
sigType = sigType.changeReturnType(ak.returnType);
}
// Get the guard method type for linking
MethodType guardType = sigType
// VarHandle at start
.insertParameterTypes(0, VarHandle.class)
// Access descriptor at end
.appendParameterTypes(VarHandle.AccessDescriptor.class);
// Create the appendix descriptor constant
VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
appendixResult[0] = ad;
if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
MemberName linker = new MemberName(
VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
guardType, REF_invokeStatic);
try {
return MemberName.getFactory().resolveOrFail(
REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
} catch (ReflectiveOperationException ex) {
// Fall back to lambda form linkage if guard method is not available
// TODO Optionally log fallback ?
}
}
return Invokers.varHandleInvokeLinkerMethod(name, mtype);
}
static String getVarHandleMethodSignature(MethodType mt) {
StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
for (int i = 0; i < mt.parameterCount(); i++) {
Class<?> pt = mt.parameterType(i);
sb.append(getCharType(pt));
}
sb.append('_').append(getCharType(mt.returnType()));
return sb.toString();
}
static char getCharType(Class<?> pt) {
return Wrapper.forBasicType(pt).basicTypeChar();
}
static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
return new NoSuchMethodError("VarHandle." + name + mtype);
}
/**
* The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.

@ -50,9 +50,10 @@ import jdk.internal.misc.Unsafe;
static final int PROFILE_LEVEL;
static final boolean PROFILE_GWT;
static final int CUSTOMIZE_THRESHOLD;
static final boolean VAR_HANDLE_GUARDS;
static {
final Object[] values = new Object[9];
final Object[] values = new Object[10];
AccessController.doPrivileged(new PrivilegedAction<>() {
public Void run() {
values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
@ -64,6 +65,7 @@ import jdk.internal.misc.Unsafe;
values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
return null;
}
});
@ -76,6 +78,7 @@ import jdk.internal.misc.Unsafe;
PROFILE_LEVEL = (Integer) values[6];
PROFILE_GWT = (Boolean) values[7];
CUSTOMIZE_THRESHOLD = (Integer) values[8];
VAR_HANDLE_GUARDS = (Boolean) values[9];
if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");

@ -53,6 +53,10 @@ import java.util.stream.Stream;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
/**
* This class consists exclusively of static methods that operate on or return
* method handles. They fall into several categories:
@ -873,7 +877,14 @@ assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
* {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
* {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
* with the same {@code type} argument.
*
* <p>
* If the class is {@code VarHandle} and the name string corresponds to
* the name of a signature-polymorphic access mode method, the resulting
* method handle is equivalent to one produced by
* {@link java.lang.invoke.MethodHandles#varHandleInvoker} with
* the access mode corresponding to the name string and with the same
* {@code type} arguments.
* <p>
* <b>Example:</b>
* <blockquote><pre>{@code
import static java.lang.invoke.MethodHandles.*;
@ -920,6 +931,9 @@ assertEquals("", (String) MH_newString.invokeExact());
if (refc == MethodHandle.class) {
MethodHandle mh = findVirtualForMH(name, type);
if (mh != null) return mh;
} else if (refc == VarHandle.class) {
MethodHandle mh = findVirtualForVH(name, type);
if (mh != null) return mh;
}
byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
MemberName method = resolveOrFail(refKind, refc, name, type);
@ -936,6 +950,13 @@ assertEquals("", (String) MH_newString.invokeExact());
assert(!MemberName.isMethodHandleInvokeName(name));
return null;
}
private MethodHandle findVirtualForVH(String name, MethodType type) {
try {
return varHandleInvoker(VarHandle.AccessMode.valueOf(name), type);
} catch (IllegalArgumentException e) {
return null;
}
}
/**
* Produces a method handle which creates an object and initializes it, using
@ -1135,6 +1156,7 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
* @see #findVarHandle(Class, String, Class)
*/
public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_getField, refc, name, type);
@ -1157,12 +1179,60 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
* @see #findVarHandle(Class, String, Class)
*/
public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName field = resolveOrFail(REF_putField, refc, name, type);
return getDirectField(REF_putField, refc, field);
}
/**
* Produces a VarHandle giving access to non-static fields of type
* {@code T} declared by a receiver class of type {@code R}, supporting
* shape {@code (R : T)}.
* <p>
* Access checking is performed immediately on behalf of the lookup
* class.
* <p>
* Certain access modes of the returned VarHandle are unsupported under
* the following conditions:
* <ul>
* <li>if the field is declared {@code final}, then the write, atomic
* update, and numeric atomic update access modes are unsupported.
* <li>if the field type is anything other than {@code int},
* {@code long} or a reference type, then atomic update access modes
* are unsupported. (Future major platform releases of the JDK may
* support additional types for certain currently unsupported access
* modes.)
* <li>if the field type is anything other than {@code int} or
* {@code long}, then numeric atomic update access modes are
* unsupported. (Future major platform releases of the JDK may
* support additional numeric types for certain currently
* unsupported access modes.)
* </ul>
* <p>
* If the field is declared {@code volatile} then the returned VarHandle
* will override access to the field (effectively ignore the
* {@code volatile} declaration) in accordance to it's specified
* access modes.
* @param recv the receiver class, of type {@code R}, that declares the
* non-static field
* @param name the field's name
* @param type the field's type, of type {@code T}
* @return a VarHandle giving access to non-static fields.
* @throws NoSuchFieldException if the field does not exist
* @throws IllegalAccessException if access checking fails, or if the field is {@code static}
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
* @since 9
*/
public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName getField = resolveOrFail(REF_getField, recv, name, type);
MemberName putField = resolveOrFail(REF_putField, recv, name, type);
return getFieldVarHandle(REF_getField, REF_putField, recv, getField, putField);
}
/**
* Produces a method handle giving read access to a static field.
* The type of the method handle will have a return type of the field's
@ -1211,6 +1281,55 @@ assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
return getDirectField(REF_putStatic, refc, field);
}
/**
* Produces a VarHandle giving access to a static field of type
* {@code T} declared by a given declaring class, supporting shape
* {@code ((empty) : T)}.
* <p>
* Access checking is performed immediately on behalf of the lookup
* class.
* <p>
* If the returned VarHandle is operated on, the declaring class will be
* initialized, if it has not already been initialized.
* <p>
* Certain access modes of the returned VarHandle are unsupported under
* the following conditions:
* <ul>
* <li>if the field is declared {@code final}, then the write, atomic
* update, and numeric atomic update access modes are unsupported.
* <li>if the field type is anything other than {@code int},
* {@code long} or a reference type, then atomic update access modes
* are unsupported. (Future major platform releases of the JDK may
* support additional types for certain currently unsupported access
* modes.)
* <li>if the field type is anything other than {@code int} or
* {@code long}, then numeric atomic update access modes are
* unsupported. (Future major platform releases of the JDK may
* support additional numeric types for certain currently
* unsupported access modes.)
* </ul>
* <p>
* If the field is declared {@code volatile} then the returned VarHandle
* will override access to the field (effectively ignore the
* {@code volatile} declaration) in accordance to it's specified
* access modes.
* @param decl the class that declares the static field
* @param name the field's name
* @param type the field's type, of type {@code T}
* @return a VarHandle giving access to a static field
* @throws NoSuchFieldException if the field does not exist
* @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
* @exception SecurityException if a security manager is present and it
* <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
* @throws NullPointerException if any argument is null
* @since 9
*/
public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
MemberName getField = resolveOrFail(REF_getStatic, decl, name, type);
MemberName putField = resolveOrFail(REF_putStatic, decl, name, type);
return getFieldVarHandle(REF_getStatic, REF_putStatic, decl, getField, putField);
}
/**
* Produces an early-bound method handle for a non-static method.
* The receiver must have a supertype {@code defc} in which a method
@ -1297,6 +1416,10 @@ return mh1;
MethodHandle mh = unreflectForMH(m);
if (mh != null) return mh;
}
if (m.getDeclaringClass() == VarHandle.class) {
MethodHandle mh = unreflectForVH(m);
if (mh != null) return mh;
}
MemberName method = new MemberName(m);
byte refKind = method.getReferenceKind();
if (refKind == REF_invokeSpecial)
@ -1311,6 +1434,12 @@ return mh1;
return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
return null;
}
private MethodHandle unreflectForVH(Method m) {
// these names require special lookups because they throw UnsupportedOperationException
if (MemberName.isVarHandleMethodInvokeName(m.getName()))
return MethodHandleImpl.fakeVarHandleInvoke(new MemberName(m));
return null;
}
/**
* Produces a method handle for a reflected method.
@ -1434,6 +1563,57 @@ return mh1;
return unreflectField(f, true);
}
/**
* Produces a VarHandle that accesses fields of type {@code T} declared
* by a class of type {@code R}, as described by the given reflected
* field.
* If the field is non-static the VarHandle supports a shape of
* {@code (R : T)}, otherwise supports a shape of {@code ((empty) : T)}.
* <p>
* Access checking is performed immediately on behalf of the lookup
* class, regardless of the value of the field's {@code accessible}
* flag.
* <p>
* If the field is static, and if the returned VarHandle is operated
* on, the field's declaring class will be initialized, if it has not
* already been initialized.
* <p>
* Certain access modes of the returned VarHandle are unsupported under
* the following conditions:
* <ul>
* <li>if the field is declared {@code final}, then the write, atomic
* update, and numeric atomic update access modes are unsupported.
* <li>if the field type is anything other than {@code int},
* {@code long} or a reference type, then atomic update access modes
* are unsupported. (Future major platform releases of the JDK may
* support additional types for certain currently unsupported access
* modes.)
* <li>if the field type is anything other than {@code int} or
* {@code long}, then numeric atomic update access modes are
* unsupported. (Future major platform releases of the JDK may
* support additional numeric types for certain currently
* unsupported access modes.)
* </ul>
* <p>
* If the field is declared {@code volatile} then the returned VarHandle
* will override access to the field (effectively ignore the
* {@code volatile} declaration) in accordance to it's specified
* access modes.
* @param f the reflected field, with a field of type {@code T}, and
* a declaring class of type {@code R}
* @return a VarHandle giving access to non-static fields or a static
* field
* @throws IllegalAccessException if access checking fails
* @throws NullPointerException if the argument is null
* @since 9
*/
public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
MemberName getField = new MemberName(f, false);
MemberName putField = new MemberName(f, true);
return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(),
f.getDeclaringClass(), getField, putField);
}
/**
* Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
* created by this lookup object or a similar one.
@ -1454,7 +1634,9 @@ return mh1;
*/
public MethodHandleInfo revealDirect(MethodHandle target) {
MemberName member = target.internalMemberName();
if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
if (member == null || (!member.isResolved() &&
!member.isMethodHandleInvoke() &&
!member.isVarHandleMethodInvoke()))
throw newIllegalArgumentException("not a direct method handle");
Class<?> defc = member.getDeclaringClass();
byte refKind = member.getReferenceKind();
@ -1829,6 +2011,52 @@ return mh1;
return restrictReceiver(field, dmh, lookupClass());
return dmh;
}
private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind,
Class<?> refc, MemberName getField, MemberName putField)
throws IllegalAccessException {
final boolean checkSecurity = true;
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
}
private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind,
Class<?> refc, MemberName getField, MemberName putField)
throws IllegalAccessException {
final boolean checkSecurity = false;
return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
}
private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind,
Class<?> refc, MemberName getField, MemberName putField,
boolean checkSecurity) throws IllegalAccessException {
assert getField.isStatic() == putField.isStatic();
assert getField.isGetter() && putField.isSetter();
assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind);
assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind);
checkField(getRefKind, refc, getField);
if (checkSecurity)
checkSecurityManager(refc, getField);
if (!putField.isFinal()) {
// A VarHandle does not support updates to final fields, any
// such VarHandle to a final field will be read-only and
// therefore the following write-based accessibility checks are
// only required for non-final fields
checkField(putRefKind, refc, putField);
if (checkSecurity)
checkSecurityManager(refc, putField);
}
boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
restrictProtectedReceiver(getField));
if (doRestrict) {
assert !getField.isStatic();
// receiver type of VarHandle is too wide; narrow to caller
if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
}
refc = lookupClass();
}
return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);
}
/** Check access and get the requested constructor. */
private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
final boolean checkSecurity = true;
@ -2018,6 +2246,205 @@ return mh1;
return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
}
/**
*
* Produces a VarHandle giving access to elements of an array type
* {@code T[]}, supporting shape {@code (T[], int : T)}.
* <p>
* Certain access modes of the returned VarHandle are unsupported under
* the following conditions:
* <ul>
* <li>if the component type is anything other than {@code int},
* {@code long} or a reference type, then atomic update access modes
* are unsupported. (Future major platform releases of the JDK may
* support additional types for certain currently unsupported access
* modes.)
* <li>if the component type is anything other than {@code int} or
* {@code long}, then numeric atomic update access modes are
* unsupported. (Future major platform releases of the JDK may
* support additional numeric types for certain currently
* unsupported access modes.)
* </ul>
* @param arrayClass the class of an array, of type {@code T[]}
* @return a VarHandle giving access to elements of an array
* @throws NullPointerException if the arrayClass is null
* @throws IllegalArgumentException if arrayClass is not an array type
* @since 9
*/
public static
VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
return VarHandles.makeArrayElementHandle(arrayClass);
}
/**
* Produces a VarHandle giving access to elements of a {@code byte[]} array
* viewed as if it were a different primitive array type, such as
* {@code int[]} or {@code long[]}. The shape of the resulting VarHandle is
* {@code (byte[], int : T)}, where the {@code int} coordinate type
* corresponds to an argument that is an index in a {@code byte[]} array,
* and {@code T} is the component type of the given view array class. The
* returned VarHandle accesses bytes at an index in a {@code byte[]} array,
* composing bytes to or from a value of {@code T} according to the given
* endianness.
* <p>
* The supported component types (variables types) are {@code short},
* {@code char}, {@code int}, {@code long}, {@code float} and
* {@code double}.
* <p>
* Access of bytes at a given index will result in an
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
* or greater than the {@code byte[]} array length minus the size (in bytes)
* of {@code T}.
* <p>
* Access of bytes at an index may be aligned or misaligned for {@code T},
* with respect to the underlying memory address, {@code A} say, associated
* with the array and index.
* If access is misaligned then access for anything other than the
* {@code get} and {@code set} access modes will result in an
* {@code IllegalStateException}. In such cases atomic access is only
* guaranteed with respect to the largest power of two that divides the GCD
* of {@code A} and the size (in bytes) of {@code T}.
* If access is aligned then following access modes are supported and are
* guaranteed to support atomic access:
* <ul>
* <li>read write access modes for all {@code T};
* <li>atomic update access modes for {@code int}, {@code long},
* {@code float} or {@code double}.
* (Future major platform releases of the JDK may support additional
* types for certain currently unsupported access modes.)
* <li>numeric atomic update access modes for {@code int} and {@code long}.
* (Future major platform releases of the JDK may support additional
* numeric types for certain currently unsupported access modes.)
* </ul>
* <p>
* Misaligned access, and therefore atomicity guarantees, may be determined
* for {@code byte[]} arrays without operating on a specific array. Given
* an {@code index}, {@code T} and it's corresponding boxed type,
* {@code T_BOX}, misalignment may be determined as follows:
* <pre>{@code
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
* int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
* alignmentOffset(0, sizeOfT);
* int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
* boolean isMisaligned = misalignedAtIndex != 0;
* }</pre>
*
* @implNote
* The variable types {@code float} and {@code double} are supported as if
* by transformation to and access with the variable types {@code int} and
* {@code long} respectively. For example, the transformation of a
* {@code double} value to a long value is performed as if using
* {@link Double#doubleToRawLongBits(double)}, and the reverse
* transformation is performed as if using
* {@link Double#longBitsToDouble(long)}.
*
* @param viewArrayClass the view array class, with a component type of
* type {@code T}
* @param bigEndian true if the endianness of the view array elements, as
* stored in the underlying {@code byte} array, is big endian, otherwise
* little endian
* @return a VarHandle giving access to elements of a {@code byte[]} array
* viewed as if elements corresponding to the components type of the view
* array class
* @throws NullPointerException if viewArrayClass is null
* @throws IllegalArgumentException if viewArrayClass is not an array type
* @throws UnsupportedOperationException if the component type of
* viewArrayClass is not supported as a variable type
* @since 9
*/
public static
VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
boolean bigEndian) throws IllegalArgumentException {
return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
}
/**
* Produces a VarHandle giving access to elements of a {@code ByteBuffer}
* viewed as if it were an array of elements of a different primitive
* component type to that of {@code byte}, such as {@code int[]} or
* {@code long[]}. The shape of the resulting VarHandle is
* {@code (ByteBuffer, int : T)}, where the {@code int} coordinate type
* corresponds to an argument that is an index in a {@code ByteBuffer}, and
* {@code T} is the component type of the given view array class. The
* returned VarHandle accesses bytes at an index in a {@code ByteBuffer},
* composing bytes to or from a value of {@code T} according to the given
* endianness.
* <p>
* The supported component types (variables types) are {@code short},
* {@code char}, {@code int}, {@code long}, {@code float} and
* {@code double}.
* <p>
* Access will result in a {@code ReadOnlyBufferException} for anything
* other than the read access modes if the {@code ByteBuffer} is read-only.
* <p>
* Access of bytes at a given index will result in an
* {@code IndexOutOfBoundsException} if the index is less than {@code 0}
* or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
* {@code T}.
* <p>
* Access of bytes at an index may be aligned or misaligned for {@code T},
* with respect to the underlying memory address, {@code A} say, associated
* with the {@code ByteBuffer} and index.
* If access is misaligned then access for anything other than the
* {@code get} and {@code set} access modes will result in an
* {@code IllegalStateException}. In such cases atomic access is only
* guaranteed with respect to the largest power of two that divides the GCD
* of {@code A} and the size (in bytes) of {@code T}.
* If access is aligned then following access modes are supported and are
* guaranteed to support atomic access:
* <ul>
* <li>read write access modes for all {@code T};
* <li>atomic update access modes for {@code int}, {@code long},
* {@code float} or {@code double}.
* (Future major platform releases of the JDK may support additional
* types for certain currently unsupported access modes.)
* <li>numeric atomic update access modes for {@code int} and {@code long}.
* (Future major platform releases of the JDK may support additional
* numeric types for certain currently unsupported access modes.)
* </ul>
* <p>
* Misaligned access, and therefore atomicity guarantees, may be determined
* for a {@code ByteBuffer}, {@code bb} (direct or otherwise), an
* {@code index}, {@code T} and it's corresponding boxed type,
* {@code T_BOX}, as follows:
* <pre>{@code
* int sizeOfT = T_BOX.BYTES; // size in bytes of T
* ByteBuffer bb = ...
* int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
* boolean isMisaligned = misalignedAtIndex != 0;
* }</pre>
*
* @implNote
* The variable types {@code float} and {@code double} are supported as if
* by transformation to and access with the variable types {@code int} and
* {@code long} respectively. For example, the transformation of a
* {@code double} value to a long value is performed as if using
* {@link Double#doubleToRawLongBits(double)}, and the reverse
* transformation is performed as if using
* {@link Double#longBitsToDouble(long)}.
*
* @param viewArrayClass the view array class, with a component type of
* type {@code T}
* @param bigEndian true if the endianness of the view array elements, as
* stored in the underlying {@code ByteBuffer}, is big endian, otherwise
* little endian (Note this overrides the endianness of a
* {@code ByteBuffer})
* @return a VarHandle giving access to elements of a {@code ByteBuffer}
* viewed as if elements corresponding to the components type of the view
* array class
* @throws NullPointerException if viewArrayClass is null
* @throws IllegalArgumentException if viewArrayClass is not an array type
* @throws UnsupportedOperationException if the component type of
* viewArrayClass is not supported as a variable type
* @since 9
*/
public static
VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
boolean bigEndian) throws IllegalArgumentException {
return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
}
/// method handle invocation (reflective style)
/**
@ -2153,6 +2580,54 @@ return invoker;
return type.invokers().genericInvoker();
}
/**
* Produces a special <em>invoker method handle</em> which can be used to
* invoke a signature-polymorphic access mode method on any VarHandle whose
* associated access mode type is compatible with the given type.
* The resulting invoker will have a type which is exactly equal to the
* desired given type, except that it will accept an additional leading
* argument of type {@code VarHandle}.
*
* @param accessMode the VarHandle access mode
* @param type the desired target type
* @return a method handle suitable for invoking an access mode method of
* any VarHandle whose access mode type is of the given type.
* @since 9
*/
static public
MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
return type.invokers().varHandleMethodExactInvoker(accessMode);
}
/**
* Produces a special <em>invoker method handle</em> which can be used to
* invoke a signature-polymorphic access mode method on any VarHandle whose
* associated access mode type is compatible with the given type.
* The resulting invoker will have a type which is exactly equal to the
* desired given type, except that it will accept an additional leading
* argument of type {@code VarHandle}.
* <p>
* Before invoking its target, if the access mode type differs from the
* desired given type, the invoker will apply reference casts as necessary
* and box, unbox, or widen primitive values, as if by
* {@link MethodHandle#asType asType}. Similarly, the return value will be
* converted as necessary.
* <p>
* This method is equivalent to the following code (though it may be more
* efficient): {@code publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)}
*
* @param accessMode the VarHandle access mode
* @param type the desired target type
* @return a method handle suitable for invoking an access mode method of
* any VarHandle whose access mode type is convertible to the given
* type.
* @since 9
*/
static public
MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
return type.invokers().varHandleMethodInvoker(accessMode);
}
static /*non-public*/
MethodHandle basicInvoker(MethodType type) {
return type.invokers().basicInvoker();

@ -95,7 +95,7 @@ class MethodType implements java.io.Serializable {
// The rtype and ptypes fields define the structural identity of the method type:
private final Class<?> rtype;
private final Class<?>[] ptypes;
private final @Stable Class<?>[] ptypes;
// The remaining fields are caches of various sorts:
private @Stable MethodTypeForm form; // erased form, plus cached data about primitives

@ -0,0 +1,164 @@
/*
* Copyright (c) 2014, 2015, 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.lang.invoke.VarHandle.AccessMode;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
/**
* A var handle form containing a set of member name, one for each operation.
* Each member characterizes a static method.
*/
class VarForm {
// Holds VarForm for VarHandle implementation classes
private static final ClassValue<VarForm> VFORMS
= new ClassValue<VarForm>() {
@Override
protected VarForm computeValue(Class<?> impl) {
return new VarForm(link(staticMethodLinker(impl)));
}
};
final MemberName mbGet;
final MemberName mbSet;
final MemberName mbGetVolatile;
final MemberName mbSetVolatile;
final MemberName mbGetAcquire;
final MemberName mbSetRelease;
final MemberName mbCompareAndSet;
final MemberName mbCompareAndExchangeVolatile;
final MemberName mbCompareAndExchangeAcquire;
final MemberName mbCompareAndExchangeRelease;
final MemberName mbWeakCompareAndSet;
final MemberName mbWeakCompareAndSetAcquire;
final MemberName mbWeakCompareAndSetRelease;
final MemberName mbGetAndSet;
final MemberName mbGetAndAdd;
final MemberName mbAddAndGet;
final MemberName mbGetOpaque;
final MemberName mbSetOpaque;
VarForm(Map<AccessMode, MemberName> linkMap) {
mbGet = linkMap.get(AccessMode.get);
mbSet = linkMap.get(AccessMode.set);
mbGetVolatile = linkMap.get(AccessMode.getVolatile);
mbSetVolatile = linkMap.get(AccessMode.setVolatile);
mbGetOpaque = linkMap.get(AccessMode.getOpaque);
mbSetOpaque = linkMap.get(AccessMode.setOpaque);
mbGetAcquire = linkMap.get(AccessMode.getAcquire);
mbSetRelease = linkMap.get(AccessMode.setRelease);
mbCompareAndSet = linkMap.get(AccessMode.compareAndSet);
mbCompareAndExchangeVolatile = linkMap.get(AccessMode.compareAndExchangeVolatile);
mbCompareAndExchangeAcquire = linkMap.get(AccessMode.compareAndExchangeAcquire);
mbCompareAndExchangeRelease = linkMap.get(AccessMode.compareAndExchangeRelease);
mbWeakCompareAndSet = linkMap.get(AccessMode.weakCompareAndSet);
mbWeakCompareAndSetAcquire = linkMap.get(AccessMode.weakCompareAndSetAcquire);
mbWeakCompareAndSetRelease = linkMap.get(AccessMode.weakCompareAndSetRelease);
mbGetAndSet = linkMap.get(AccessMode.getAndSet);
mbGetAndAdd = linkMap.get(AccessMode.getAndAdd);
mbAddAndGet = linkMap.get(AccessMode.addAndGet);
}
/**
* Creates a var form given an VarHandle implementation class.
* Each signature polymorphic method is linked to a static method of the
* same name on the implementation class or a super class.
*/
static VarForm createFromStatic(Class<? extends VarHandle> impl) {
return VFORMS.get(impl);
}
/**
* Link all signature polymorphic methods.
*/
private static Map<AccessMode, MemberName> link(Function<AccessMode, MemberName> linker) {
Map<AccessMode, MemberName> links = new HashMap<>();
for (AccessMode ak : AccessMode.values()) {
links.put(ak, linker.apply(ak));
}
return links;
}
/**
* Returns a function that associates an AccessMode with a MemberName that
* is a static concrete method implementation for the access operation of
* the implementing class.
*/
private static Function<AccessMode, MemberName> staticMethodLinker(Class<?> implClass) {
// Find all declared static methods on the implementation class and
// all super classes up to but not including VarHandle
List<Method> staticMethods = new ArrayList<>(AccessMode.values().length);
for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
for (Method m : c.getDeclaredMethods()) {
if (Modifier.isStatic(m.getModifiers())) {
staticMethods.add(m);
}
}
}
// This needs to be an anonymous inner class and not a lambda expression
// The latter will cause the intialization of classes in java.lang.invoke
// resulting in circular dependencies if VarHandles are utilized early
// in the start up process. For example, if ConcurrentHashMap
// is modified to use VarHandles.
return new Function<>() {
@Override
public MemberName apply(AccessMode ak) {
Method m = null;
for (Method to_m : staticMethods) {
if (to_m.getName().equals(ak.name()) &&
Modifier.isStatic(to_m.getModifiers())) {
assert m == null : String.format(
"Two or more static methods named %s are present on " +
"class %s or a super class", ak.name(), implClass.getName());
m = to_m;
}
}
if (m == null)
return null;
MemberName linkedMethod = new MemberName(m);
try {
return MemberName.getFactory().resolveOrFail(
REF_invokeStatic, linkedMethod, m.getDeclaringClass(), NoSuchMethodException.class);
}
catch (ReflectiveOperationException e) {
throw new InternalError(e);
}
}
};
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,70 @@
/*
* Copyright (c) 2015, 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.nio.Buffer;
import java.nio.ByteBuffer;
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
/**
* The base class for generated byte array and byte buffer view
* implementations
*/
abstract class VarHandleByteArrayBase {
// Buffer.address
static final long BUFFER_ADDRESS;
// Buffer.limit
static final long BUFFER_LIMIT;
// ByteBuffer.hb
static final long BYTE_BUFFER_HB;
// ByteBuffer.isReadOnly
static final long BYTE_BUFFER_IS_READ_ONLY;
static {
try {
BUFFER_ADDRESS = UNSAFE.objectFieldOffset(
Buffer.class.getDeclaredField("address"));
BUFFER_LIMIT = UNSAFE.objectFieldOffset(
Buffer.class.getDeclaredField("limit"));
BYTE_BUFFER_HB = UNSAFE.objectFieldOffset(
ByteBuffer.class.getDeclaredField("hb"));
BYTE_BUFFER_IS_READ_ONLY = UNSAFE.objectFieldOffset(
ByteBuffer.class.getDeclaredField("isReadOnly"));
}
catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
static final boolean BE = UNSAFE.isBigEndian();
static IllegalStateException newIllegalStateExceptionForMisalignedAccess(int index) {
return new IllegalStateException("Misaligned access at index: " + index);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,533 @@
/*
* Copyright (c) 2014, 2016, 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 static java.lang.invoke.MethodHandleStatics.UNSAFE;
final class VarHandles {
static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
if (!f.isStatic()) {
long foffset = MethodHandleNatives.objectFieldOffset(f);
if (!type.isPrimitive()) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
: new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type);
}
else if (type == boolean.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
: new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
}
else if (type == byte.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
: new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
}
else if (type == short.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
: new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
}
else if (type == char.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
: new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
}
else if (type == int.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
: new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
}
else if (type == long.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
: new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
}
else if (type == float.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
: new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
}
else if (type == double.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
: new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
}
else {
throw new UnsupportedOperationException();
}
}
else {
// TODO This is not lazy on first invocation
// and might cause some circular initialization issues
// Replace with something similar to direct method handles
// where a barrier is used then elided after use
if (UNSAFE.shouldBeInitialized(refc))
UNSAFE.ensureClassInitialized(refc);
Object base = MethodHandleNatives.staticFieldBase(f);
long foffset = MethodHandleNatives.staticFieldOffset(f);
if (!type.isPrimitive()) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
: new VarHandleObjects.FieldStaticReadWrite(base, foffset, type);
}
else if (type == boolean.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
: new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
}
else if (type == byte.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
: new VarHandleBytes.FieldStaticReadWrite(base, foffset);
}
else if (type == short.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
: new VarHandleShorts.FieldStaticReadWrite(base, foffset);
}
else if (type == char.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleChars.FieldStaticReadOnly(base, foffset)
: new VarHandleChars.FieldStaticReadWrite(base, foffset);
}
else if (type == int.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleInts.FieldStaticReadOnly(base, foffset)
: new VarHandleInts.FieldStaticReadWrite(base, foffset);
}
else if (type == long.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
: new VarHandleLongs.FieldStaticReadWrite(base, foffset);
}
else if (type == float.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
: new VarHandleFloats.FieldStaticReadWrite(base, foffset);
}
else if (type == double.class) {
return f.isFinal() && !isWriteAllowedOnFinalFields
? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
: new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
}
else {
throw new UnsupportedOperationException();
}
}
}
static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
if (!arrayClass.isArray())
throw new IllegalArgumentException("not an array: " + arrayClass);
Class<?> componentType = arrayClass.getComponentType();
int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
int ascale = UNSAFE.arrayIndexScale(arrayClass);
int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
if (!componentType.isPrimitive()) {
return new VarHandleObjects.Array(aoffset, ashift, arrayClass);
}
else if (componentType == boolean.class) {
return new VarHandleBooleans.Array(aoffset, ashift);
}
else if (componentType == byte.class) {
return new VarHandleBytes.Array(aoffset, ashift);
}
else if (componentType == short.class) {
return new VarHandleShorts.Array(aoffset, ashift);
}
else if (componentType == char.class) {
return new VarHandleChars.Array(aoffset, ashift);
}
else if (componentType == int.class) {
return new VarHandleInts.Array(aoffset, ashift);
}
else if (componentType == long.class) {
return new VarHandleLongs.Array(aoffset, ashift);
}
else if (componentType == float.class) {
return new VarHandleFloats.Array(aoffset, ashift);
}
else if (componentType == double.class) {
return new VarHandleDoubles.Array(aoffset, ashift);
}
else {
throw new UnsupportedOperationException();
}
}
static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
boolean be) {
if (!viewArrayClass.isArray())
throw new IllegalArgumentException("not an array: " + viewArrayClass);
Class<?> viewComponentType = viewArrayClass.getComponentType();
if (viewComponentType == long.class) {
return new VarHandleByteArrayAsLongs.ArrayHandle(be);
}
else if (viewComponentType == int.class) {
return new VarHandleByteArrayAsInts.ArrayHandle(be);
}
else if (viewComponentType == short.class) {
return new VarHandleByteArrayAsShorts.ArrayHandle(be);
}
else if (viewComponentType == char.class) {
return new VarHandleByteArrayAsChars.ArrayHandle(be);
}
else if (viewComponentType == double.class) {
return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
}
else if (viewComponentType == float.class) {
return new VarHandleByteArrayAsFloats.ArrayHandle(be);
}
throw new UnsupportedOperationException();
}
static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
boolean be) {
if (!viewArrayClass.isArray())
throw new IllegalArgumentException("not an array: " + viewArrayClass);
Class<?> viewComponentType = viewArrayClass.getComponentType();
if (viewComponentType == long.class) {
return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
}
else if (viewComponentType == int.class) {
return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
}
else if (viewComponentType == short.class) {
return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
}
else if (viewComponentType == char.class) {
return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
}
else if (viewComponentType == double.class) {
return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
}
else if (viewComponentType == float.class) {
return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
}
throw new UnsupportedOperationException();
}
// /**
// * A helper program to generate the VarHandleGuards class with a set of
// * static guard methods each of which corresponds to a particular shape and
// * performs a type check of the symbolic type descriptor with the VarHandle
// * type descriptor before linking/invoking to the underlying operation as
// * characterized by the operation member name on the VarForm of the
// * VarHandle.
// * <p>
// * The generated class essentially encapsulates pre-compiled LambdaForms,
// * one for each method, for the most set of common method signatures.
// * This reduces static initialization costs, footprint costs, and circular
// * dependencies that may arise if a class is generated per LambdaForm.
// * <p>
// * A maximum of L*T*S methods will be generated where L is the number of
// * access modes kinds (or unique operation signatures) and T is the number
// * of variable types and S is the number of shapes (such as instance field,
// * static field, or array access).
// * If there are 4 unique operation signatures, 5 basic types (Object, int,
// * long, float, double), and 3 shapes then a maximum of 60 methods will be
// * generated. However, the number is likely to be less since there
// * be duplicate signatures.
// * <p>
// * Each method is annotated with @LambdaForm.Compiled to inform the runtime
// * that such methods should be treated as if a method of a class that is the
// * result of compiling a LambdaForm. Annotation of such methods is
// * important for correct evaluation of certain assertions and method return
// * type profiling in HotSpot.
// */
// public static class GuardMethodGenerator {
//
// static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
//
// static final String GUARD_METHOD_TEMPLATE =
// "@ForceInline\n" +
// "@LambdaForm.Compiled\n" +
// "final static <METHOD> throws Throwable {\n" +
// " MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
// " MethodType symbolic = ad.symbolicMethodType;\n" +
// " if (target == symbolic) {\n" +
// " <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
// " }\n" +
// " else if (target.erase() == symbolic.erase()) {\n" +
// " <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
// " }\n" +
// " else {\n" +
// " MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
// " <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
// " }\n" +
// "}";
//
// static final String GET_MEMBER_NAME_METHOD =
// "@ForceInline\n" +
// "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
// " MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
// " if (mn == null) {\n" +
// " throw handle.unsupported();\n" +
// " }\n" +
// " return mn;\n" +
// "}";
//
// // A template for deriving the operations
// // could be supported by annotating VarHandle directly with the
// // operation kind and shape
// interface VarHandleTemplate {
// Object get();
//
// void set(Object value);
//
// boolean compareAndSwap(Object actualValue, Object expectedValue);
//
// Object compareAndExchange(Object actualValue, Object expectedValue);
//
// Object getAndUpdate(Object value);
// }
//
// static class HandleType {
// final Class<?> receiver;
// final Class<?>[] intermediates;
// final Class<?> value;
//
// HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
// this.receiver = receiver;
// this.intermediates = intermediates;
// this.value = value;
// }
// }
//
// /**
// * @param args parameters
// */
// public static void main(String[] args) {
// System.out.println("package java.lang.invoke;");
// System.out.println();
// System.out.println("import jdk.internal.vm.annotation.ForceInline;");
// System.out.println();
// System.out.println("// This class is auto-generated by " +
// GuardMethodGenerator.class.getName() +
// ". Do not edit.");
// System.out.println("final class VarHandleGuards {");
//
// System.out.println();
// System.out.println(GET_MEMBER_NAME_METHOD);
// System.out.println();
//
// // Declare the stream of shapes
// Stream<HandleType> hts = Stream.of(
// // Object->Object
// new HandleType(Object.class, Object.class),
// // Object->int
// new HandleType(Object.class, int.class),
// // Object->long
// new HandleType(Object.class, long.class),
// // Object->float
// new HandleType(Object.class, float.class),
// // Object->double
// new HandleType(Object.class, double.class),
//
// // <static>->Object
// new HandleType(null, Object.class),
// // <static>->int
// new HandleType(null, int.class),
// // <static>->long
// new HandleType(null, long.class),
// // <static>->float
// new HandleType(null, float.class),
// // <static>->double
// new HandleType(null, double.class),
//
// // Array[int]->Object
// new HandleType(Object.class, Object.class, int.class),
// // Array[int]->int
// new HandleType(Object.class, int.class, int.class),
// // Array[int]->long
// new HandleType(Object.class, long.class, int.class),
// // Array[int]->float
// new HandleType(Object.class, float.class, int.class),
// // Array[int]->double
// new HandleType(Object.class, double.class, int.class),
//
// // Array[long]->int
// new HandleType(Object.class, int.class, long.class),
// // Array[long]->long
// new HandleType(Object.class, long.class, long.class)
// );
//
// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
// distinct().
// map(mt -> generateMethod(mt)).
// forEach(s -> {
// System.out.println(s);
// System.out.println();
// });
//
// System.out.println("}");
// }
//
// static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
// Class<?> returnType = m.getReturnType() == Object.class
// ? value : m.getReturnType();
//
// List<Class<?>> params = new ArrayList<>();
// if (receiver != null)
// params.add(receiver);
// for (int i = 0; i < intermediates.length; i++) {
// params.add(intermediates[i]);
// }
// for (Parameter p : m.getParameters()) {
// params.add(value);
// }
// return MethodType.methodType(returnType, params);
// }
//
// static String generateMethod(MethodType mt) {
// Class<?> returnType = mt.returnType();
//
// LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
// params.put("handle", VarHandle.class);
// for (int i = 0; i < mt.parameterCount(); i++) {
// params.put("arg" + i, mt.parameterType(i));
// }
// params.put("ad", VarHandle.AccessDescriptor.class);
//
// // Generate method signature line
// String RETURN = className(returnType);
// String NAME = "guard";
// String SIGNATURE = getSignature(mt);
// String PARAMS = params.entrySet().stream().
// map(e -> className(e.getValue()) + " " + e.getKey()).
// collect(joining(", "));
// String METHOD = GUARD_METHOD_SIG_TEMPLATE.
// replace("<RETURN>", RETURN).
// replace("<NAME>", NAME).
// replace("<SIGNATURE>", SIGNATURE).
// replace("<PARAMS>", PARAMS);
//
// // Generate method
// params.remove("ad");
//
// List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
// collect(toList());
// LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
//
// List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
// collect(toList());
//
// RETURN = returnType == void.class
// ? ""
// : returnType == Object.class
// ? "return "
// : "return (" + returnType.getName() + ") ";
//
// String RESULT_ERASED = returnType == void.class
// ? ""
// : returnType != Object.class
// ? "return (" + returnType.getName() + ") "
// : "Object r = ";
//
// String RETURN_ERASED = returnType != Object.class
// ? ""
// : " return symbolic.returnType().cast(r);";
//
// return GUARD_METHOD_TEMPLATE.
// replace("<METHOD>", METHOD).
// replace("<NAME>", NAME).
// replaceAll("<RETURN>", RETURN).
// replace("<RESULT_ERASED>", RESULT_ERASED).
// replace("<RETURN_ERASED>", RETURN_ERASED).
// replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
// collect(joining(", "))).
// replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
// collect(joining(", ")))
// ;
// }
//
// static String className(Class<?> c) {
// String n = c.getName();
// if (n.startsWith("java.lang.")) {
// n = n.replace("java.lang.", "");
// if (n.startsWith("invoke.")) {
// n = n.replace("invoke.", "");
// }
// }
// return n.replace('$', '.');
// }
//
// static String getSignature(MethodType m) {
// StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
//
// for (int i = 0; i < m.parameterCount(); i++) {
// Class<?> pt = m.parameterType(i);
// sb.append(getCharType(pt));
// }
//
// sb.append('_').append(getCharType(m.returnType()));
//
// return sb.toString();
// }
//
// static char getCharType(Class<?> pt) {
// if (pt == void.class) {
// return 'V';
// }
// else if (!pt.isPrimitive()) {
// return 'L';
// }
// else if (pt == boolean.class) {
// return 'Z';
// }
// else if (pt == int.class) {
// return 'I';
// }
// else if (pt == long.class) {
// return 'J';
// }
// else if (pt == float.class) {
// return 'F';
// }
// else if (pt == double.class) {
// return 'D';
// }
// else {
// throw new IllegalStateException(pt.getName());
// }
// }
// }
}

@ -0,0 +1,602 @@
/*
* Copyright (c) 2015, 2016, 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.Objects;
import jdk.internal.vm.annotation.ForceInline;
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
#warn
final class VarHandle$Type$s {
static class FieldInstanceReadOnly extends VarHandle {
final long fieldOffset;
final Class<?> receiverType;
#if[Object]
final Class<?> fieldType;
#end[Object]
FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
}
protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
Class<? extends FieldInstanceReadOnly> handle) {
super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
this.fieldOffset = fieldOffset;
this.receiverType = receiverType;
#if[Object]
this.fieldType = fieldType;
#end[Object]
}
@ForceInline
static $type$ get(FieldInstanceReadOnly handle, Object holder) {
return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset);
}
@ForceInline
static $type$ getVolatile(FieldInstanceReadOnly handle, Object holder) {
return UNSAFE.get$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset);
}
@ForceInline
static $type$ getOpaque(FieldInstanceReadOnly handle, Object holder) {
return UNSAFE.get$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset);
}
@ForceInline
static $type$ getAcquire(FieldInstanceReadOnly handle, Object holder) {
return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset);
}
}
static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
}
@ForceInline
static void set(FieldInstanceReadWrite handle, Object holder, $type$ value) {
UNSAFE.put$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setVolatile(FieldInstanceReadWrite handle, Object holder, $type$ value) {
UNSAFE.put$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setOpaque(FieldInstanceReadWrite handle, Object holder, $type$ value) {
UNSAFE.put$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setRelease(FieldInstanceReadWrite handle, Object holder, $type$ value) {
UNSAFE.put$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
#if[CAS]
@ForceInline
static boolean compareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ getAndSet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
return UNSAFE.getAndSet$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(FieldInstanceReadWrite handle, Object holder, $type$ value) {
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
value);
}
@ForceInline
static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
handle.fieldOffset,
value) + value;
}
#end[AtomicAdd]
}
static class FieldStaticReadOnly extends VarHandle {
final Object base;
final long fieldOffset;
#if[Object]
final Class<?> fieldType;
#end[Object]
FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
}
protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
Class<? extends FieldStaticReadOnly> handle) {
super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
this.base = base;
this.fieldOffset = fieldOffset;
#if[Object]
this.fieldType = fieldType;
#end[Object]
}
@ForceInline
static $type$ get(FieldStaticReadOnly handle) {
return UNSAFE.get$Type$(handle.base,
handle.fieldOffset);
}
@ForceInline
static $type$ getVolatile(FieldStaticReadOnly handle) {
return UNSAFE.get$Type$Volatile(handle.base,
handle.fieldOffset);
}
@ForceInline
static $type$ getOpaque(FieldStaticReadOnly handle) {
return UNSAFE.get$Type$Opaque(handle.base,
handle.fieldOffset);
}
@ForceInline
static $type$ getAcquire(FieldStaticReadOnly handle) {
return UNSAFE.get$Type$Acquire(handle.base,
handle.fieldOffset);
}
}
static class FieldStaticReadWrite extends FieldStaticReadOnly {
FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
}
@ForceInline
static void set(FieldStaticReadWrite handle, $type$ value) {
UNSAFE.put$Type$(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setVolatile(FieldStaticReadWrite handle, $type$ value) {
UNSAFE.put$Type$Volatile(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setOpaque(FieldStaticReadWrite handle, $type$ value) {
UNSAFE.put$Type$Opaque(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static void setRelease(FieldStaticReadWrite handle, $type$ value) {
UNSAFE.put$Type$Release(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
#if[CAS]
@ForceInline
static boolean compareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.compareAndSwap$Type$(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Acquire(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.compareAndExchange$Type$Release(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
return UNSAFE.weakCompareAndSwap$Type$Release(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(expected):expected},
{#if[Object]?handle.fieldType.cast(value):value});
}
@ForceInline
static $type$ getAndSet(FieldStaticReadWrite handle, $type$ value) {
return UNSAFE.getAndSet$Type$(handle.base,
handle.fieldOffset,
{#if[Object]?handle.fieldType.cast(value):value});
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(FieldStaticReadWrite handle, $type$ value) {
return UNSAFE.getAndAdd$Type$(handle.base,
handle.fieldOffset,
value);
}
@ForceInline
static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
return UNSAFE.getAndAdd$Type$(handle.base,
handle.fieldOffset,
value) + value;
}
#end[AtomicAdd]
}
static final class Array extends VarHandle {
final int abase;
final int ashift;
#if[Object]
final Class<{#if[Object]??:$type$[]}> arrayType;
final Class<?> componentType;
#end[Object]
Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
super(VarForm.createFromStatic(Array.class),
{#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
this.abase = abase;
this.ashift = ashift;
#if[Object]
this.arrayType = {#if[Object]?arrayType:$type$[].class};
this.componentType = arrayType.getComponentType();
#end[Object]
}
@ForceInline
static $type$ get(Array handle, Object oarray, int index) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return array[index];
}
@ForceInline
static void set(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
array[index] = {#if[Object]?handle.componentType.cast(value):value};
}
@ForceInline
static $type$ getVolatile(Array handle, Object oarray, int index) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.get$Type$Volatile(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
}
@ForceInline
static void setVolatile(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
UNSAFE.put$Type$Volatile(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ getOpaque(Array handle, Object oarray, int index) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.get$Type$Opaque(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
}
@ForceInline
static void setOpaque(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
UNSAFE.put$Type$Opaque(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ getAcquire(Array handle, Object oarray, int index) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.get$Type$Acquire(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
}
@ForceInline
static void setRelease(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
UNSAFE.put$Type$Release(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(value):value});
}
#if[CAS]
@ForceInline
static boolean compareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.compareAndSwap$Type$(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.compareAndExchange$Type$Volatile(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.compareAndExchange$Type$Acquire(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ compareAndExchangeRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.compareAndExchange$Type$Release(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.weakCompareAndSwap$Type$(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static boolean weakCompareAndSetRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.weakCompareAndSwap$Type$Release(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(expected):expected},
{#if[Object]?handle.componentType.cast(value):value});
}
@ForceInline
static $type$ getAndSet(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.getAndSet$Type$(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
{#if[Object]?handle.componentType.cast(value):value});
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.getAndAdd$Type$(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
value);
}
@ForceInline
static $type$ addAndGet(Array handle, Object oarray, int index, $type$ value) {
#if[Object]
Object[] array = (Object[]) handle.arrayType.cast(oarray);
#else[Object]
$type$[] array = ($type$[]) oarray;
#end[Object]
return UNSAFE.getAndAdd$Type$(array,
(((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
value) + value;
}
#end[AtomicAdd]
}
}

@ -0,0 +1,497 @@
/*
* Copyright (c) 2015, 2016, 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 jdk.internal.misc.Unsafe;
import jdk.internal.vm.annotation.ForceInline;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Objects;
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
#warn
final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static final int ALIGN = $BoxType$.BYTES - 1;
#if[floatingPoint]
@ForceInline
static $rawType$ convEndian(boolean big, $type$ v) {
$rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
}
@ForceInline
static $type$ convEndian(boolean big, $rawType$ rv) {
rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
return $Type$.$rawType$BitsTo$Type$(rv);
}
#else[floatingPoint]
@ForceInline
static $type$ convEndian(boolean big, $type$ n) {
return big == BE ? n : $BoxType$.reverseBytes(n);
}
#end[floatingPoint]
private static class ByteArrayViewVarHandle extends VarHandle {
final boolean be;
ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
Class<?> arrayType, Class<?> component, boolean be) {
super(VarForm.createFromStatic(implSubType),
arrayType, component, int.class);
this.be = be;
}
}
static final class ArrayHandle extends ByteArrayViewVarHandle {
ArrayHandle(boolean be) {
super(ArrayHandle.class, byte[].class, $type$.class, be);
}
@ForceInline
static int index(byte[] ba, int index) {
return Objects.checkIndex(index, ba.length - ALIGN, null);
}
@ForceInline
static long address(byte[] ba, int index) {
long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
if ((address & ALIGN) != 0)
throw newIllegalStateExceptionForMisalignedAccess(index);
return address;
}
@ForceInline
static $type$ get(ArrayHandle handle, Object oba, int index) {
byte[] ba = (byte[]) oba;
#if[floatingPoint]
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
ba,
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
handle.be);
return $Type$.$rawType$BitsTo$Type$(rawValue);
#else[floatingPoint]
return UNSAFE.get$Type$Unaligned(
ba,
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
handle.be);
#end[floatingPoint]
}
@ForceInline
static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
#if[floatingPoint]
UNSAFE.put$RawType$Unaligned(
ba,
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
$Type$.$type$ToRaw$RawType$Bits(value),
handle.be);
#else[floatingPoint]
UNSAFE.put$RawType$Unaligned(
ba,
((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
value,
handle.be);
#end[floatingPoint]
}
@ForceInline
static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Volatile(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Volatile(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Acquire(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.get$RawType$Opaque(
ba,
address(ba, index(ba, index))));
}
@ForceInline
static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
UNSAFE.put$RawType$Opaque(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value));
}
#if[CAS]
@ForceInline
static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return UNSAFE.compareAndSwap$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Volatile(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Acquire(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSwap$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
byte[] ba = (byte[]) oba;
return UNSAFE.weakCompareAndSwap$RawType$Release(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.getAndSet$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be,
UNSAFE.getAndAdd$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value)));
}
@ForceInline
static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
byte[] ba = (byte[]) oba;
return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
ba,
address(ba, index(ba, index)),
convEndian(handle.be, value))) + value;
}
#end[AtomicAdd]
}
static final class ByteBufferHandle extends ByteArrayViewVarHandle {
ByteBufferHandle(boolean be) {
super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
}
@ForceInline
static int index(ByteBuffer bb, int index) {
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
}
@ForceInline
static int indexRO(ByteBuffer bb, int index) {
if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
throw new ReadOnlyBufferException();
return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
}
@ForceInline
static long address(ByteBuffer bb, int index) {
long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
if ((address & ALIGN) != 0)
throw newIllegalStateExceptionForMisalignedAccess(index);
return address;
}
@ForceInline
static $type$ get(ByteBufferHandle handle, Object obb, int index) {
ByteBuffer bb = (ByteBuffer) obb;
#if[floatingPoint]
$rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
handle.be);
return $Type$.$rawType$BitsTo$Type$(rawValue);
#else[floatingPoint]
return UNSAFE.get$Type$Unaligned(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
handle.be);
#end[floatingPoint]
}
@ForceInline
static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
#if[floatingPoint]
UNSAFE.put$RawType$Unaligned(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
$Type$.$type$ToRaw$RawType$Bits(value),
handle.be);
#else[floatingPoint]
UNSAFE.put$Type$Unaligned(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
value,
handle.be);
#end[floatingPoint]
}
@ForceInline
static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.get$RawType$Volatile(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, index(bb, index))));
}
@ForceInline
static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
UNSAFE.put$RawType$Volatile(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.get$RawType$Acquire(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, index(bb, index))));
}
@ForceInline
static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
UNSAFE.put$RawType$Release(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@ForceInline
static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.get$RawType$Opaque(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, index(bb, index))));
}
@ForceInline
static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
UNSAFE.put$RawType$Opaque(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
#if[CAS]
@ForceInline
static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return UNSAFE.compareAndSwap$RawType$(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Volatile(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Acquire(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.compareAndExchange$RawType$Release(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@ForceInline
static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return UNSAFE.weakCompareAndSwap$RawType$(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return UNSAFE.weakCompareAndSwap$RawType$Acquire(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return UNSAFE.weakCompareAndSwap$RawType$Release(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@ForceInline
static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.getAndSet$RawType$(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
#end[CAS]
#if[AtomicAdd]
@ForceInline
static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.getAndAdd$RawType$(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
@ForceInline
static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
ByteBuffer bb = (ByteBuffer) obb;
return convEndian(handle.be,
UNSAFE.getAndAdd$RawType$(
UNSAFE.getObject(bb, BYTE_BUFFER_HB),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value))) + value;
}
#end[AtomicAdd]
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -32,7 +32,8 @@
* certain types in this package have special relations to dynamic
* language support in the virtual machine:
* <ul>
* <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
* <li>The classes {@link java.lang.invoke.MethodHandle MethodHandle}
* {@link java.lang.invoke.VarHandle VarHandle} contain
* <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
* which can be linked regardless of their type descriptor.
* Normally, method linkage requires exact matching of type descriptors.

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2016, 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
@ -25,9 +25,10 @@
package java.nio;
import java.util.Spliterator;
import jdk.internal.HotSpotIntrinsicCandidate;
import java.util.Spliterator;
/**
* A container for data of a specific primitive type.
*
@ -188,7 +189,15 @@ public abstract class Buffer {
private int limit;
private int capacity;
// Used only by direct buffers
// Used by heap byte buffers or direct buffers with Unsafe access
// For heap byte buffers this field will be the address relative to the
// array base address and offset into that array. The address might
// not align on a word boundary for slices, nor align at a long word
// (8 byte) boundary for byte[] allocations on 32-bit systems.
// For direct buffers it is the start address of the memory region. The
// address might not align on a word boundary for slices, nor when created
// using JNI, see NewDirectByteBuffer(void*, long).
// Should ideally be declared final
// NOTE: hoisted here for speed in JNI GetDirectBufferAddress
long address;

@ -140,6 +140,7 @@ class Direct$Type$Buffer$RW$$BO$
att = null;
#else[rw]
super(cap);
this.isReadOnly = true;
#end[rw]
}
@ -180,6 +181,7 @@ class Direct$Type$Buffer$RW$$BO$
att = null;
#else[rw]
super(cap, addr, fd, unmapper);
this.isReadOnly = true;
#end[rw]
}
@ -200,6 +202,7 @@ class Direct$Type$Buffer$RW$$BO$
att = db;
#else[rw]
super(db, mark, pos, lim, cap, off);
this.isReadOnly = true;
#end[rw]
}
@ -213,6 +216,15 @@ class Direct$Type$Buffer$RW$$BO$
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
}
#if[byte]
public $Type$Buffer slice(int pos, int lim) {
assert (pos >= 0);
assert (pos <= lim);
int rem = lim - pos;
return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
}
#end[byte]
public $Type$Buffer duplicate() {
return new Direct$Type$Buffer$RW$$BO$(this,
this.markValue(),

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2016, 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
@ -74,6 +74,9 @@ class Heap$Type$Buffer$RW$
super(cap, lim);
this.isReadOnly = true;
#end[rw]
#if[byte]
this.address = arrayBaseOffset;
#end[byte]
}
Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
@ -87,6 +90,9 @@ class Heap$Type$Buffer$RW$
super(buf, off, len);
this.isReadOnly = true;
#end[rw]
#if[byte]
this.address = arrayBaseOffset;
#end[byte]
}
protected Heap$Type$Buffer$RW$($type$[] buf,
@ -103,6 +109,9 @@ class Heap$Type$Buffer$RW$
super(buf, mark, pos, lim, cap, off);
this.isReadOnly = true;
#end[rw]
#if[byte]
this.address = arrayBaseOffset + off;
#end[byte]
}
public $Type$Buffer slice() {
@ -114,6 +123,20 @@ class Heap$Type$Buffer$RW$
this.position() + offset);
}
#if[byte]
$Type$Buffer slice(int pos, int lim) {
assert (pos >= 0);
assert (pos <= lim);
int rem = lim - pos;
return new Heap$Type$Buffer$RW$(hb,
-1,
0,
rem,
rem,
pos + offset);
}
#end[byte]
public $Type$Buffer duplicate() {
return new Heap$Type$Buffer$RW$(hb,
this.markValue(),
@ -144,7 +167,7 @@ class Heap$Type$Buffer$RW$
#if[byte]
private long byteOffset(long i) {
return arrayBaseOffset + i + offset;
return address + i;
}
#end[byte]

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2016, 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
@ -39,6 +39,7 @@ class StringCharBuffer // package-private
if ((start < 0) || (start > n) || (end < start) || (end > n))
throw new IndexOutOfBoundsException();
str = s;
this.isReadOnly = true;
}
public CharBuffer slice() {
@ -58,6 +59,7 @@ class StringCharBuffer // package-private
int offset) {
super(mark, pos, limit, cap, null, offset);
str = s;
this.isReadOnly = true;
}
public CharBuffer duplicate() {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2016, 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
@ -269,7 +269,7 @@ public abstract class $Type$Buffer
//
final $type$[] hb; // Non-null only for heap buffers
final int offset;
boolean isReadOnly; // Valid only for heap buffers
boolean isReadOnly;
// Creates a new buffer with the given mark, position, limit, capacity,
// backing array, and array offset
@ -530,6 +530,10 @@ public abstract class $Type$Buffer
* it will be read-only if, and only if, this buffer is read-only. </p>
*
* @return The new $type$ buffer
#if[byte]
*
* @see #alignedSlice(int)
#end[byte]
*/
public abstract $Type$Buffer slice();
@ -1611,6 +1615,143 @@ public abstract class $Type$Buffer
return this;
}
/**
* Returns the memory address, pointing to the byte at the given index,
* modulus the given unit size.
*
* <p> A return value greater than zero indicates the address of the byte at
* the index is misaligned for the unit size, and the value's quantity
* indicates how much the index should be rounded up or down to locate a
* byte at an aligned address. Otherwise, a value of {@code 0} indicates
* that the address of the byte at the index is aligned for the unit size.
*
* @apiNote
* This method may be utilized to determine if unit size bytes from an
* index can be accessed atomically, if supported by the native platform.
*
* @implNote
* This implementation throws {@code UnsupportedOperationException} for
* non-direct buffers when the given unit size is greater then {@code 8}.
*
* @param index
* The index to query for alignment offset, must be non-negative, no
* upper bounds check is performed
*
* @param unitSize
* The unit size in bytes, must be a power of {@code 2}
*
* @return The indexed byte's memory address modulus the unit size
*
* @throws IllegalArgumentException
* If the index is negative or the unit size is not a power of
* {@code 2}
*
* @throws UnsupportedOperationException
* If the native platform does not guarantee stable alignment offset
* values for the given unit size when managing the memory regions
* of buffers of the same kind as this buffer (direct or
* non-direct). For example, if garbage collection would result
* in the moving of a memory region covered by a non-direct buffer
* from one location to another and both locations have different
* alignment characteristics.
*
* @see #alignedSlice(int)
* @since 9
*/
public final int alignmentOffset(int index, int unitSize) {
if (index < 0)
throw new IllegalArgumentException("Index less than zero: " + index);
if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
if (unitSize > 8 && !isDirect())
throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
return (int) ((address + index) % unitSize);
}
/**
* Creates a new byte buffer whose content is a shared and aligned
* subsequence of this buffer's content.
*
* <p> The content of the new buffer will start at this buffer's current
* position rounded up to the index of the nearest aligned byte for the
* given unit size, and end at this buffer's limit rounded down to the index
* of the nearest aligned byte for the given unit size.
* If rounding results in out-of-bound values then the new buffer's capacity
* and limit will be zero. If rounding is within bounds the following
* expressions will be true for a new buffer {@code nb} and unit size
* {@code unitSize}:
* <pre>{@code
* nb.alignmentOffset(0, unitSize) == 0
* nb.alignmentOffset(nb.limit(), unitSize) == 0
* }</pre>
*
* <p> Changes to this buffer's content will be visible in the new
* buffer, and vice versa; the two buffers' position, limit, and mark
* values will be independent.
*
* <p> The new buffer's position will be zero, its capacity and its limit
* will be the number of bytes remaining in this buffer or fewer subject to
* alignment, its mark will be undefined, and its byte order will be
* {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
*
* The new buffer will be direct if, and only if, this buffer is direct, and
* it will be read-only if, and only if, this buffer is read-only. </p>
*
* @apiNote
* This method may be utilized to create a new buffer where unit size bytes
* from index, that is a multiple of the unit size, may be accessed
* atomically, if supported by the native platform.
*
* @implNote
* This implementation throws {@code UnsupportedOperationException} for
* non-direct buffers when the given unit size is greater then {@code 8}.
*
* @param unitSize
* The unit size in bytes, must be a power of {@code 2}
*
* @return The new byte buffer
*
* @throws IllegalArgumentException
* If the unit size not a power of {@code 2}
*
* @throws UnsupportedOperationException
* If the native platform does not guarantee stable aligned slices
* for the given unit size when managing the memory regions
* of buffers of the same kind as this buffer (direct or
* non-direct). For example, if garbage collection would result
* in the moving of a memory region covered by a non-direct buffer
* from one location to another and both locations have different
* alignment characteristics.
*
* @see #alignmentOffset(int, int)
* @see #slice()
* @since 9
*/
public final ByteBuffer alignedSlice(int unitSize) {
int pos = position();
int lim = limit();
int pos_mod = alignmentOffset(pos, unitSize);
int lim_mod = alignmentOffset(lim, unitSize);
// Round up the position to align with unit size
int aligned_pos = (pos_mod > 0)
? pos + (unitSize - pos_mod)
: pos;
// Round down the limit to align with unit size
int aligned_lim = lim - lim_mod;
if (aligned_pos > lim || aligned_lim < pos) {
aligned_pos = aligned_lim = pos;
}
return slice(aligned_pos, aligned_lim);
}
abstract ByteBuffer slice(int pos, int lim);
// Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
//
abstract byte _get(int i); // package-private

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2016, 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
@ -47,7 +47,6 @@ import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import sun.util.locale.provider.LocaleProviderAdapter;
@ -146,6 +145,12 @@ public class DateFormatSymbols implements Serializable, Cloneable {
initializeData(locale);
}
/**
* Constructs an uninitialized DateFormatSymbols.
*/
private DateFormatSymbols(boolean flag) {
}
/**
* Era strings. For example: "AD" and "BC". An array of 2 strings,
* indexed by <code>Calendar.BC</code> and <code>Calendar.AD</code>.
@ -679,54 +684,80 @@ public class DateFormatSymbols implements Serializable, Cloneable {
*/
transient volatile int cachedHashCode;
private void initializeData(Locale desiredLocale) {
locale = desiredLocale;
// Copy values of a cached instance if any.
/**
* Initializes this DateFormatSymbols with the locale data. This method uses
* a cached DateFormatSymbols instance for the given locale if available. If
* there's no cached one, this method creates an uninitialized instance and
* populates its fields from the resource bundle for the locale, and caches
* the instance. Note: zoneStrings isn't initialized in this method.
*/
private void initializeData(Locale locale) {
SoftReference<DateFormatSymbols> ref = cachedInstances.get(locale);
DateFormatSymbols dfs;
if (ref != null && (dfs = ref.get()) != null) {
copyMembers(dfs, this);
return;
}
if (ref == null || (dfs = ref.get()) == null) {
if (ref != null) {
// Remove the empty SoftReference
cachedInstances.remove(locale, ref);
}
dfs = new DateFormatSymbols(false);
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter
= LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource
= ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
// JRE and CLDR use different keys
// JRE: Eras, short.Eras and narrow.Eras
// CLDR: long.Eras, Eras and narrow.Eras
if (resource.containsKey("Eras")) {
eras = resource.getStringArray("Eras");
} else if (resource.containsKey("long.Eras")) {
eras = resource.getStringArray("long.Eras");
} else if (resource.containsKey("short.Eras")) {
eras = resource.getStringArray("short.Eras");
}
months = resource.getStringArray("MonthNames");
shortMonths = resource.getStringArray("MonthAbbreviations");
ampms = resource.getStringArray("AmPmMarkers");
localPatternChars = resource.getString("DateTimePatternChars");
dfs.locale = locale;
// JRE and CLDR use different keys
// JRE: Eras, short.Eras and narrow.Eras
// CLDR: long.Eras, Eras and narrow.Eras
if (resource.containsKey("Eras")) {
dfs.eras = resource.getStringArray("Eras");
} else if (resource.containsKey("long.Eras")) {
dfs.eras = resource.getStringArray("long.Eras");
} else if (resource.containsKey("short.Eras")) {
dfs.eras = resource.getStringArray("short.Eras");
}
dfs.months = resource.getStringArray("MonthNames");
dfs.shortMonths = resource.getStringArray("MonthAbbreviations");
dfs.ampms = resource.getStringArray("AmPmMarkers");
dfs.localPatternChars = resource.getString("DateTimePatternChars");
// Day of week names are stored in a 1-based array.
weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
// Day of week names are stored in a 1-based array.
dfs.weekdays = toOneBasedArray(resource.getStringArray("DayNames"));
dfs.shortWeekdays = toOneBasedArray(resource.getStringArray("DayAbbreviations"));
// Put a clone in the cache
ref = new SoftReference<>((DateFormatSymbols)this.clone());
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
DateFormatSymbols y = x.get();
if (y == null) {
// Replace the empty SoftReference with ref.
cachedInstances.put(locale, ref);
// Put dfs in the cache
ref = new SoftReference<>(dfs);
SoftReference<DateFormatSymbols> x = cachedInstances.putIfAbsent(locale, ref);
if (x != null) {
DateFormatSymbols y = x.get();
if (y == null) {
// Replace the empty SoftReference with ref.
cachedInstances.replace(locale, x, ref);
} else {
ref = x;
dfs = y;
}
}
// If the bundle's locale isn't the target locale, put another cache
// entry for the bundle's locale.
Locale bundleLocale = resource.getLocale();
if (!bundleLocale.equals(locale)) {
SoftReference<DateFormatSymbols> z
= cachedInstances.putIfAbsent(bundleLocale, ref);
if (z != null && z.get() == null) {
cachedInstances.replace(bundleLocale, z, ref);
}
}
}
// Copy the field values from dfs to this instance.
copyMembers(dfs, this);
}
private static String[] toOneBasedArray(String[] src) {
@ -808,12 +839,14 @@ public class DateFormatSymbols implements Serializable, Cloneable {
/**
* Clones all the data members from the source DateFormatSymbols to
* the target DateFormatSymbols. This is only for subclasses.
* the target DateFormatSymbols.
*
* @param src the source DateFormatSymbols.
* @param dst the target DateFormatSymbols.
*/
private void copyMembers(DateFormatSymbols src, DateFormatSymbols dst)
{
dst.locale = src.locale;
dst.eras = Arrays.copyOf(src.eras, src.eras.length);
dst.months = Arrays.copyOf(src.months, src.months.length);
dst.shortMonths = Arrays.copyOf(src.shortMonths, src.shortMonths.length);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, 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
@ -61,12 +61,17 @@
*/
package java.time.chrono;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import java.time.Clock;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.format.TextStyle;
@ -712,6 +717,59 @@ public interface Chronology extends Comparable<Chronology> {
return new ChronoPeriodImpl(this, years, months, days);
}
//---------------------------------------------------------------------
/**
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
* <p>
* The number of seconds is calculated using the proleptic-year,
* month, day-of-month, hour, minute, second, and zoneOffset.
*
* @param prolepticYear the chronology proleptic-year
* @param month the chronology month-of-year
* @param dayOfMonth the chronology day-of-month
* @param hour the hour-of-day, from 0 to 23
* @param minute the minute-of-hour, from 0 to 59
* @param second the second-of-minute, from 0 to 59
* @param zoneOffset the zone offset, not null
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
* @throws DateTimeException if any of the values are out of range
* @since 9
*/
public default long epochSecond(int prolepticYear, int month, int dayOfMonth,
int hour, int minute, int second, ZoneOffset zoneOffset) {
Objects.requireNonNull(zoneOffset, "zoneOffset");
HOUR_OF_DAY.checkValidValue(hour);
MINUTE_OF_HOUR.checkValidValue(minute);
SECOND_OF_MINUTE.checkValidValue(second);
long daysInSec = Math.multiplyExact(date(prolepticYear, month, dayOfMonth).toEpochDay(), 86400);
long timeinSec = (hour * 60 + minute) * 60 + second;
return Math.addExact(daysInSec, timeinSec - zoneOffset.getTotalSeconds());
}
/**
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
* <p>
* The number of seconds is calculated using the era, year-of-era,
* month, day-of-month, hour, minute, second, and zoneOffset.
*
* @param era the era of the correct type for the chronology, not null
* @param yearOfEra the chronology year-of-era
* @param month the chronology month-of-year
* @param dayOfMonth the chronology day-of-month
* @param hour the hour-of-day, from 0 to 23
* @param minute the minute-of-hour, from 0 to 59
* @param second the second-of-minute, from 0 to 59
* @param zoneOffset the zone offset, not null
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
* @throws DateTimeException if any of the values are out of range
* @since 9
*/
public default long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth,
int hour, int minute, int second, ZoneOffset zoneOffset) {
Objects.requireNonNull(era, "era");
return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset);
}
//-----------------------------------------------------------------------
/**
* Compares this chronology to another chronology.

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, 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
@ -61,14 +61,17 @@
*/
package java.time.chrono;
import java.io.InvalidObjectException;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.ERA;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR;
import static java.time.temporal.ChronoField.YEAR_OF_ERA;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.time.Clock;
@ -79,8 +82,9 @@ import java.time.LocalDateTime;
import java.time.Month;
import java.time.Period;
import java.time.Year;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
@ -132,6 +136,8 @@ public final class IsoChronology extends AbstractChronology implements Serializa
*/
private static final long serialVersionUID = -1440403870442975015L;
private static final long DAYS_0000_TO_1970 = (146097 * 5L) - (30L * 365L + 7L); // taken from LocalDate
/**
* Restricted constructor.
*/
@ -263,6 +269,94 @@ public final class IsoChronology extends AbstractChronology implements Serializa
return LocalDate.from(temporal);
}
//-----------------------------------------------------------------------
/**
* Gets the number of seconds from the epoch of 1970-01-01T00:00:00Z.
* <p>
* The number of seconds is calculated using the year,
* month, day-of-month, hour, minute, second, and zoneOffset.
*
* @param prolepticYear the year, from MIN_YEAR to MAX_YEAR
* @param month the month-of-year, from 1 to 12
* @param dayOfMonth the day-of-month, from 1 to 31
* @param hour the hour-of-day, from 0 to 23
* @param minute the minute-of-hour, from 0 to 59
* @param second the second-of-minute, from 0 to 59
* @param zoneOffset the zone offset, not null
* @return the number of seconds relative to 1970-01-01T00:00:00Z, may be negative
* @throws DateTimeException if the value of any argument is out of range,
* or if the day-of-month is invalid for the month-of-year
* @since 9
*/
@Override
public long epochSecond(int prolepticYear, int month, int dayOfMonth,
int hour, int minute, int second, ZoneOffset zoneOffset) {
YEAR.checkValidValue(prolepticYear);
MONTH_OF_YEAR.checkValidValue(month);
DAY_OF_MONTH.checkValidValue(dayOfMonth);
HOUR_OF_DAY.checkValidValue(hour);
MINUTE_OF_HOUR.checkValidValue(minute);
SECOND_OF_MINUTE.checkValidValue(second);
Objects.requireNonNull(zoneOffset, "zoneOffset");
if (dayOfMonth > 28) {
int dom = numberOfDaysOfMonth(prolepticYear, month);
if (dayOfMonth > dom) {
if (dayOfMonth == 29) {
throw new DateTimeException("Invalid date 'February 29' as '" + prolepticYear + "' is not a leap year");
} else {
throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
}
}
}
long totalDays = 0;
int timeinSec = 0;
totalDays += 365L * prolepticYear;
if (prolepticYear >= 0) {
totalDays += (prolepticYear + 3L) / 4 - (prolepticYear + 99L) / 100 + (prolepticYear + 399L) / 400;
} else {
totalDays -= prolepticYear / -4 - prolepticYear / -100 + prolepticYear / -400;
}
totalDays += (367 * month - 362) / 12;
totalDays += dayOfMonth - 1;
if (month > 2) {
totalDays--;
if (IsoChronology.INSTANCE.isLeapYear(prolepticYear) == false) {
totalDays--;
}
}
totalDays -= DAYS_0000_TO_1970;
timeinSec = (hour * 60 + minute ) * 60 + second;
return Math.addExact(Math.multiplyExact(totalDays, 86400L), timeinSec - zoneOffset.getTotalSeconds());
}
/**
* Gets the number of days for the given month in the given year.
*
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
* @param month the month-of-year to represent, from 1 to 12
* @return the number of days for the given month in the given year
*/
private int numberOfDaysOfMonth(int year, int month) {
int dom;
switch (month) {
case 2:
dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
break;
case 4:
case 6:
case 9:
case 11:
dom = 30;
break;
default:
dom = 31;
break;
}
return dom;
}
/**
* Obtains an ISO local date-time from another date-time object.
* <p>

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, 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
@ -270,6 +270,8 @@ public enum ChronoField implements TemporalField {
* In lenient mode the value is not validated. It is combined with
* {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
* the {AMPM_OF_DAY} value by 12.
* <p>
* See {@link #CLOCK_HOUR_OF_AMPM} for the related field that counts hours from 1 to 12.
*/
HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
/**
@ -284,6 +286,8 @@ public enum ChronoField implements TemporalField {
* 0 to 12 in smart mode. In lenient mode the value is not validated.
* The field is converted to an {@code HOUR_OF_AMPM} with the same value,
* unless the value is 12, in which case it is converted to 0.
* <p>
* See {@link #HOUR_OF_AMPM} for the related field that counts hours from 0 to 11.
*/
CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
/**
@ -299,12 +303,14 @@ public enum ChronoField implements TemporalField {
* {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
* In lenient mode, any excess days are added to the parsed date, or
* made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
* <p>
* See {@link #CLOCK_HOUR_OF_DAY} for the related field that counts hours from 1 to 24.
*/
HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
/**
* The clock-hour-of-day.
* <p>
* This counts the hour within the AM/PM, from 1 to 24.
* This counts the hour within the day, from 1 to 24.
* This is the hour that would be observed on a 24-hour analog wall clock.
* This field has the same meaning for all calendar systems.
* <p>
@ -313,6 +319,8 @@ public enum ChronoField implements TemporalField {
* 0 to 24 in smart mode. In lenient mode the value is not validated.
* The field is converted to an {@code HOUR_OF_DAY} with the same value,
* unless the value is 24, in which case it is converted to 0.
* <p>
* See {@link #HOUR_OF_DAY} for the related field that counts hours from 0 to 23.
*/
CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
/**

@ -174,7 +174,7 @@ package java.util;
* that do allow null elements are strongly encouraged <i>not</i> to
* take advantage of the ability to insert nulls. This is so because
* {@code null} is used as a special return value by various methods
* to indicated that the deque is empty.
* to indicate that the deque is empty.
*
* <p>{@code Deque} implementations generally do not define
* element-based versions of the {@code equals} and {@code hashCode}

@ -480,7 +480,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}
static void lazySetNext(Completion c, Completion next) {
U.putOrderedObject(c, NEXT, next);
U.putObjectRelease(c, NEXT, next);
}
/**
@ -583,9 +583,9 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
*/
final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
if (a != null && a.stack != null) {
if (mode < 0 || a.result == null)
if (a.result == null)
a.cleanStack();
else
else if (mode >= 0)
a.postComplete();
}
if (result != null && stack != null) {
@ -1107,9 +1107,9 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
final CompletableFuture<T> postFire(CompletableFuture<?> a,
CompletableFuture<?> b, int mode) {
if (b != null && b.stack != null) { // clean second source
if (mode < 0 || b.result == null)
if (b.result == null)
b.cleanStack();
else
else if (mode >= 0)
b.postComplete();
}
return postFire(a, mode);

@ -628,10 +628,14 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
volatile V val;
volatile Node<K,V> next;
Node(int hash, K key, V val, Node<K,V> next) {
Node(int hash, K key, V val) {
this.hash = hash;
this.key = key;
this.val = val;
}
Node(int hash, K key, V val, Node<K,V> next) {
this(hash, key, val);
this.next = next;
}
@ -1024,8 +1028,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
@ -1048,8 +1051,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key,
value, null);
pred.next = new Node<K,V>(hash, key, value);
break;
}
}
@ -1709,7 +1711,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
Node<K,V> node = null;
try {
if ((val = mappingFunction.apply(key)) != null)
node = new Node<K,V>(h, key, val, null);
node = new Node<K,V>(h, key, val);
} finally {
setTabAt(tab, i, node);
}
@ -1740,7 +1742,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
if (pred.next != null)
throw new IllegalStateException("Recursive update");
added = true;
pred.next = new Node<K,V>(h, key, val, null);
pred.next = new Node<K,V>(h, key, val);
}
break;
}
@ -1909,7 +1911,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
try {
if ((val = remappingFunction.apply(key, null)) != null) {
delta = 1;
node = new Node<K,V>(h, key, val, null);
node = new Node<K,V>(h, key, val);
}
} finally {
setTabAt(tab, i, node);
@ -1951,8 +1953,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
if (pred.next != null)
throw new IllegalStateException("Recursive update");
delta = 1;
pred.next =
new Node<K,V>(h, key, val, null);
pred.next = new Node<K,V>(h, key, val);
}
break;
}
@ -2030,7 +2031,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
if (casTabAt(tab, i, null, new Node<K,V>(h, key, value, null))) {
if (casTabAt(tab, i, null, new Node<K,V>(h, key, value))) {
delta = 1;
val = value;
break;
@ -2065,8 +2066,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
if ((e = e.next) == null) {
delta = 1;
val = value;
pred.next =
new Node<K,V>(h, key, val, null);
pred.next = new Node<K,V>(h, key, val);
break;
}
}
@ -2227,7 +2227,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
static final class ForwardingNode<K,V> extends Node<K,V> {
final Node<K,V>[] nextTable;
ForwardingNode(Node<K,V>[] tab) {
super(MOVED, null, null, null);
super(MOVED, null, null);
this.nextTable = tab;
}
@ -2263,7 +2263,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
*/
static final class ReservationNode<K,V> extends Node<K,V> {
ReservationNode() {
super(RESERVED, null, null, null);
super(RESERVED, null, null);
}
Node<K,V> find(int h, Object k) {
@ -2690,12 +2690,12 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
}
/**
* Returns a list on non-TreeNodes replacing those in given list.
* Returns a list of non-TreeNodes replacing those in given list.
*/
static <K,V> Node<K,V> untreeify(Node<K,V> b) {
Node<K,V> hd = null, tl = null;
for (Node<K,V> q = b; q != null; q = q.next) {
Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val, null);
Node<K,V> p = new Node<K,V>(q.hash, q.key, q.val);
if (tl == null)
hd = p;
else
@ -2801,7 +2801,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* Creates bin with initial set of nodes headed by b.
*/
TreeBin(TreeNode<K,V> b) {
super(TREEBIN, null, null, null);
super(TREEBIN, null, null);
this.first = b;
TreeNode<K,V> r = null;
for (TreeNode<K,V> x = b, next; x != null; x = next) {

@ -309,7 +309,7 @@ public class ConcurrentLinkedDeque<E>
}
void lazySetNext(Node<E> val) {
U.putOrderedObject(this, NEXT, val);
U.putObjectRelease(this, NEXT, val);
}
boolean casNext(Node<E> cmp, Node<E> val) {
@ -317,7 +317,7 @@ public class ConcurrentLinkedDeque<E>
}
void lazySetPrev(Node<E> val) {
U.putOrderedObject(this, PREV, val);
U.putObjectRelease(this, PREV, val);
}
boolean casPrev(Node<E> cmp, Node<E> val) {

@ -198,7 +198,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
}
static <E> void lazySetNext(Node<E> node, Node<E> val) {
U.putOrderedObject(node, NEXT, val);
U.putObjectRelease(node, NEXT, val);
}
static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {

@ -239,7 +239,7 @@ public class Exchanger<V> {
* not to be as readily inlined by dynamic compilers when they are
* hidden behind other methods that would more nicely name and
* encapsulate the intended effects). This includes the use of
* putOrderedX to clear fields of the per-thread Nodes between
* putXRelease to clear fields of the per-thread Nodes between
* uses. Note that field Node.item is not declared as volatile
* even though it is read by releasing threads, because they only
* do so after CAS operations that must precede access, and all
@ -376,7 +376,7 @@ public class Exchanger<V> {
for (int h = p.hash, spins = SPINS;;) {
Object v = p.match;
if (v != null) {
U.putOrderedObject(p, MATCH, null);
U.putObjectRelease(p, MATCH, null);
p.item = null; // clear for next use
p.hash = h;
return v;
@ -507,7 +507,7 @@ public class Exchanger<V> {
break;
}
}
U.putOrderedObject(p, MATCH, null);
U.putObjectRelease(p, MATCH, null);
p.item = null;
p.hash = h;
return v;

@ -289,7 +289,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* on to try or create other queues -- they block only when
* creating and registering new queues. Because it is used only as
* a spinlock, unlocking requires only a "releasing" store (using
* putOrderedInt). The qlock is also used during termination
* putIntRelease). The qlock is also used during termination
* detection, in which case it is forced to a negative
* non-lockable value.
*
@ -1071,7 +1071,7 @@ public class ForkJoinPool extends AbstractExecutorService {
popped = true;
top = s;
}
U.putOrderedInt(this, QLOCK, 0);
U.putIntRelease(this, QLOCK, 0);
}
}
return popped;
@ -1261,7 +1261,7 @@ public class ForkJoinPool extends AbstractExecutorService {
popped = true;
top = s - 1;
}
U.putOrderedInt(this, QLOCK, 0);
U.putIntRelease(this, QLOCK, 0);
if (popped)
return t;
}

@ -92,7 +92,7 @@ public class ForkJoinWorkerThread extends Thread {
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
AccessControlContext acc) {
super(threadGroup, null, "aForkJoinWorkerThread");
U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
eraseThreadLocals(); // clear before registering
this.pool = pool;
this.workQueue = pool.registerWorker(this);

@ -174,7 +174,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
if (t != null)
t.interrupt();
} finally { // final state
U.putOrderedInt(this, STATE, INTERRUPTED);
U.putIntRelease(this, STATE, INTERRUPTED);
}
}
} finally {
@ -230,7 +230,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
protected void set(V v) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = v;
U.putOrderedInt(this, STATE, NORMAL); // final state
U.putIntRelease(this, STATE, NORMAL); // final state
finishCompletion();
}
}
@ -248,7 +248,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
protected void setException(Throwable t) {
if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
outcome = t;
U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
finishCompletion();
}
}

@ -1496,7 +1496,7 @@ public class SubmissionPublisher<T> implements Flow.Publisher<T>,
else if (((c & CONSUME) != 0 ||
U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
U.compareAndSwapObject(a, i, x, null)) {
U.putOrderedInt(this, HEAD, ++h);
U.putIntRelease(this, HEAD, ++h);
U.getAndAddLong(this, DEMAND, -1L);
if ((w = waiter) != null)
signalWaiter(w);

@ -136,7 +136,7 @@ public class AtomicBoolean implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(boolean newValue) {
U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
}
/**

@ -108,7 +108,7 @@ public class AtomicInteger extends Number implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(int newValue) {
U.putOrderedInt(this, VALUE, newValue);
U.putIntRelease(this, VALUE, newValue);
}
/**

@ -136,7 +136,7 @@ public class AtomicIntegerArray implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(int i, int newValue) {
U.putOrderedInt(array, checkedByteOffset(i), newValue);
U.putIntRelease(array, checkedByteOffset(i), newValue);
}
/**

@ -475,7 +475,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
public final void lazySet(T obj, int newValue) {
accessCheck(obj);
U.putOrderedInt(obj, offset, newValue);
U.putIntRelease(obj, offset, newValue);
}
public final int get(T obj) {

@ -124,7 +124,7 @@ public class AtomicLong extends Number implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(long newValue) {
U.putOrderedLong(this, VALUE, newValue);
U.putLongRelease(this, VALUE, newValue);
}
/**

@ -135,7 +135,7 @@ public class AtomicLongArray implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(int i, long newValue) {
U.putOrderedLong(array, checkedByteOffset(i), newValue);
U.putLongRelease(array, checkedByteOffset(i), newValue);
}
/**

@ -457,7 +457,7 @@ public abstract class AtomicLongFieldUpdater<T> {
public final void lazySet(T obj, long newValue) {
accessCheck(obj);
U.putOrderedLong(obj, offset, newValue);
U.putLongRelease(obj, offset, newValue);
}
public final long get(T obj) {

@ -103,7 +103,7 @@ public class AtomicReference<V> implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(V newValue) {
U.putOrderedObject(this, VALUE, newValue);
U.putObjectRelease(this, VALUE, newValue);
}
/**

@ -147,7 +147,7 @@ public class AtomicReferenceArray<E> implements java.io.Serializable {
* @since 1.6
*/
public final void lazySet(int i, E newValue) {
U.putOrderedObject(array, checkedByteOffset(i), newValue);
U.putObjectRelease(array, checkedByteOffset(i), newValue);
}
/**

@ -426,7 +426,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
public final void lazySet(T obj, V newValue) {
accessCheck(obj);
valueCheck(newValue);
U.putOrderedObject(obj, offset, newValue);
U.putObjectRelease(obj, offset, newValue);
}
@SuppressWarnings("unchecked")

@ -42,107 +42,95 @@ import java.util.List;
* to the jimage file provided by the shipped JDK by tools running on JDK 8.
*/
public class CompressIndexes {
private static final int INTEGER_SIZE = 4;
private static final int COMPRESSED_FLAG = 1 << (Byte.SIZE - 1);
private static final int HEADER_WIDTH = 3;
private static final int HEADER_SHIFT = Byte.SIZE - HEADER_WIDTH;
public static List<Integer> decompressFlow(byte[] values) {
List<Integer> lst = new ArrayList<>();
for (int i = 0; i < values.length;) {
byte b = values[i];
int length = isCompressed(b) ? getLength(b) : INTEGER_SIZE;
for (int i = 0; i < values.length; i += getHeaderLength(values[i])) {
int decompressed = decompress(values, i);
lst.add(decompressed);
i += length;
}
return lst;
}
public static int readInt(DataInputStream cr) throws IOException {
byte[] b = new byte[1];
cr.readFully(b);
byte firstByte = b[0];
boolean compressed = CompressIndexes.isCompressed(firstByte);
int toRead = 4;
if(compressed) {
toRead = CompressIndexes.getLength(firstByte);
// Get header byte.
byte header = cr.readByte();
// Determine size.
int size = getHeaderLength(header);
// Prepare result.
int result = getHeaderValue(header);
// For each value byte
for (int i = 1; i < size; i++) {
// Merge byte value.
result <<= Byte.SIZE;
result |= cr.readByte() & 0xFF;
}
byte[] content = new byte[toRead-1];
cr.readFully(content);
ByteBuffer bb = ByteBuffer.allocate(content.length+1);
bb.put(firstByte);
bb.put(content);
int index = CompressIndexes.decompress(bb.array(), 0);
return index;
return result;
}
public static int getLength(byte b) {
return ((byte) (b & 0x60) >> 5);
private static boolean isCompressed(byte b) {
return (b & COMPRESSED_FLAG) != 0;
}
public static boolean isCompressed(byte b) {
return b < 0;
private static int getHeaderLength(byte b) {
return isCompressed(b) ? (b >> HEADER_SHIFT) & 3 : Integer.BYTES;
}
private static int getHeaderValue(byte b) {
return isCompressed(b) ? b & (1 << HEADER_SHIFT) - 1 : b;
}
public static int decompress(byte[] value, int offset) {
byte b1 = value[offset];
ByteBuffer buffer = ByteBuffer.allocate(INTEGER_SIZE);
if (isCompressed(b1)) { // compressed
int length = getLength(b1);
byte clearedValue = (byte) (b1 & 0x1F);
// Get header byte.
byte header = value[offset];
// Determine size.
int size = getHeaderLength(header);
// Prepare result.
int result = getHeaderValue(header);
int start = INTEGER_SIZE - length;
buffer.put(start, clearedValue);
for (int i = offset + 1; i < offset + length; i++) {
buffer.put(++start, value[i]);
}
} else {
buffer.put(value, offset, INTEGER_SIZE);
// For each value byte
for (int i = 1; i < size; i++) {
// Merge byte value.
result <<= Byte.SIZE;
result |= value[offset + i] & 0xFF;
}
return buffer.getInt(0);
return result;
}
public static byte[] compress(int val) {
ByteBuffer result = ByteBuffer.allocate(4).putInt(val);
byte[] array = result.array();
if ((val & 0xFF000000) == 0) { // nothing on 4th
if ((val & 0x00FF0000) == 0) { // nothing on 3rd
if ((val & 0x0000FF00) == 0) { // nothing on 2nd
if ((val & 0x000000E0) == 0) { // only in 1st, encode length in the byte.
//sign bit and size 1 ==> 101X
result = ByteBuffer.allocate(1);
result.put((byte) (0xA0 | array[3]));
} else { // add a byte for size
//sign bit and size 2 ==> 110X
result = ByteBuffer.allocate(2);
result.put((byte) 0xC0);
result.put(array[3]);
}
} else { // content in 2nd
if ((val & 0x0000E000) == 0) {// encode length in the byte.
//sign bit and size 2 ==> 110X
result = ByteBuffer.allocate(2);
result.put((byte) (0xC0 | array[2]));
result.put(array[3]);
} else { // add a byte for size
//sign bit and size 3 ==> 111X
result = ByteBuffer.allocate(3);
result.put((byte) 0xE0);
result.put(array[2]);
result.put(array[3]);
}
}
} else {// content in 3rd
if ((val & 0x00E00000) == 0) {// encode length in the byte.
//sign bit and size 3 ==> 111X
result = ByteBuffer.allocate(3);
result.put((byte) (0xE0 | array[1]));
result.put(array[2]);
result.put(array[3]);
} else { // add a byte, useless
//
}
}
public static byte[] compress(int value) {
// Only positive values are supported.
if (value < 0) {
throw new IllegalArgumentException("value < 0");
}
return result.array();
// Determine number of significant digits.
int width = 32 - Integer.numberOfLeadingZeros(value);
// Determine number of byte to represent. Allow for header if
// compressed.
int size = Math.min(((width + HEADER_WIDTH - 1) >> 3) + 1, Integer.BYTES);
// Allocate result buffer.
byte[] result = new byte[size];
// Insert significant bytes in result.
for (int i = 0; i < size; i++) {
result[i] = (byte)(value >> ((size - i - 1) * Byte.SIZE));
}
// If compressed, mark and insert size.
if (size < Integer.BYTES) {
result[0] |= (byte)(COMPRESSED_FLAG | (size << HEADER_SHIFT));
}
return result;
}
}

@ -86,8 +86,8 @@ public final class InnocuousThread extends Thread {
private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
super(group, target, name, 0L, false);
UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);
UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
}
@Override

@ -1457,25 +1457,7 @@ public final class Unsafe {
@HotSpotIntrinsicCandidate
public native void putDoubleVolatile(Object o, long offset, double x);
/**
* Version of {@link #putObjectVolatile(Object, long, Object)}
* that does not guarantee immediate visibility of the store to
* other threads. This method is generally only useful if the
* underlying field is a Java volatile (or if an array cell, one
* that is otherwise only accessed using volatile accesses).
*
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
*/
@HotSpotIntrinsicCandidate
public native void putOrderedObject(Object o, long offset, Object x);
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
@HotSpotIntrinsicCandidate
public native void putOrderedInt(Object o, long offset, int x);
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
@HotSpotIntrinsicCandidate
public native void putOrderedLong(Object o, long offset, long x);
/** Acquire version of {@link #getObjectVolatile(Object, long)} */
@HotSpotIntrinsicCandidate
@ -1531,6 +1513,16 @@ public final class Unsafe {
return getDoubleVolatile(o, offset);
}
/*
* Versions of {@link #putObjectVolatile(Object, long, Object)}
* that do not guarantee immediate visibility of the store to
* other threads. This method is generally only useful if the
* underlying field is a Java volatile (or if an array cell, one
* that is otherwise only accessed using volatile accesses).
*
* Corresponds to C11 atomic_store_explicit(..., memory_order_release).
*/
/** Release version of {@link #putObjectVolatile(Object, long, Object)} */
@HotSpotIntrinsicCandidate
public final void putObjectRelease(Object o, long offset, Object x) {

@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.misc;
package jdk.internal.vm;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

@ -182,6 +182,9 @@ module java.base {
java.desktop;
exports jdk.internal.util.jar to
jdk.jartool;
exports jdk.internal.vm to
java.management,
jdk.jvmstat;
exports sun.net to
java.httpclient;
exports sun.net.dns to

@ -1068,19 +1068,19 @@ public final class Unsafe {
*/
@ForceInline
public void putOrderedObject(Object o, long offset, Object x) {
theInternalUnsafe.putOrderedObject(o, offset, x);
theInternalUnsafe.putObjectRelease(o, offset, x);
}
/** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
@ForceInline
public void putOrderedInt(Object o, long offset, int x) {
theInternalUnsafe.putOrderedInt(o, offset, x);
theInternalUnsafe.putIntRelease(o, offset, x);
}
/** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
@ForceInline
public void putOrderedLong(Object o, long offset, long x) {
theInternalUnsafe.putOrderedLong(o, offset, x);
theInternalUnsafe.putLongRelease(o, offset, x);
}
/**

@ -83,7 +83,7 @@ public class TransferProtocolClient extends NetworkClient {
code = Integer.parseInt(response, 0, 3, 10);
} catch (NumberFormatException e) {
code = -1;
} catch (StringIndexOutOfBoundsException e) {
} catch (IndexOutOfBoundsException e) {
/* this line doesn't contain a response code, so
we just completely ignore it */
continue;

@ -440,7 +440,7 @@ public class FtpClient extends sun.net.ftp.FtpClient {
code = Integer.parseInt(response, 0, 3, 10);
} catch (NumberFormatException e) {
code = -1;
} catch (StringIndexOutOfBoundsException e) {
} catch (IndexOutOfBoundsException e) {
/* this line doesn't contain a response code, so
we just completely ignore it */
continue;

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2016, 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
@ -299,6 +299,13 @@ public class FtpURLConnection extends URLConnection {
// Just keep throwing for now.
throw e;
} catch (FtpProtocolException fe) {
if (ftp != null) {
try {
ftp.close();
} catch (IOException ioe) {
fe.addSuppressed(ioe);
}
}
throw new IOException(fe);
}
try {
@ -481,11 +488,34 @@ public class FtpURLConnection extends URLConnection {
msgh.add("content-type", "text/plain");
msgh.add("access-type", "directory");
} catch (IOException ex) {
throw new FileNotFoundException(fullpath);
FileNotFoundException fnfe = new FileNotFoundException(fullpath);
if (ftp != null) {
try {
ftp.close();
} catch (IOException ioe) {
fnfe.addSuppressed(ioe);
}
}
throw fnfe;
} catch (FtpProtocolException ex2) {
throw new FileNotFoundException(fullpath);
FileNotFoundException fnfe = new FileNotFoundException(fullpath);
if (ftp != null) {
try {
ftp.close();
} catch (IOException ioe) {
fnfe.addSuppressed(ioe);
}
}
throw fnfe;
}
} catch (FtpProtocolException ftpe) {
if (ftp != null) {
try {
ftp.close();
} catch (IOException ioe) {
ftpe.addSuppressed(ioe);
}
}
throw new IOException(ftpe);
}
setProperties(msgh);

@ -1198,8 +1198,9 @@ class DH_ServerKeyExchange extends ServerKeyExchange
if (!localSupportedSignAlgs.contains(
preferableSignatureAlgorithm)) {
throw new SSLHandshakeException(
"Unsupported SignatureAndHashAlgorithm in " +
"ServerKeyExchange message");
"Unsupported SignatureAndHashAlgorithm in " +
"ServerKeyExchange message: " +
preferableSignatureAlgorithm);
}
} else {
this.preferableSignatureAlgorithm = null;
@ -1232,7 +1233,8 @@ class DH_ServerKeyExchange extends ServerKeyExchange
sig = RSASignature.getInstance();
break;
default:
throw new SSLKeyException("neither an RSA or a DSA key");
throw new SSLKeyException(
"neither an RSA or a DSA key: " + algorithm);
}
}
@ -1482,7 +1484,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
preferableSignatureAlgorithm)) {
throw new SSLHandshakeException(
"Unsupported SignatureAndHashAlgorithm in " +
"ServerKeyExchange message");
"ServerKeyExchange message: " +
preferableSignatureAlgorithm);
}
}
@ -1522,7 +1525,8 @@ class ECDH_ServerKeyExchange extends ServerKeyExchange {
case "RSA":
return RSASignature.getInstance();
default:
throw new NoSuchAlgorithmException("neither an RSA or a EC key");
throw new NoSuchAlgorithmException(
"neither an RSA or a EC key : " + keyAlgorithm);
}
}
@ -1729,7 +1733,8 @@ class CertificateRequest extends HandshakeMessage
algorithmsLen = input.getInt16();
if (algorithmsLen < 2) {
throw new SSLProtocolException(
"Invalid supported_signature_algorithms field");
"Invalid supported_signature_algorithms field: " +
algorithmsLen);
}
algorithms = new ArrayList<SignatureAndHashAlgorithm>();
@ -1748,7 +1753,8 @@ class CertificateRequest extends HandshakeMessage
if (remains != 0) {
throw new SSLProtocolException(
"Invalid supported_signature_algorithms field");
"Invalid supported_signature_algorithms field. remains: " +
remains);
}
} else {
algorithms = new ArrayList<SignatureAndHashAlgorithm>();
@ -1765,7 +1771,8 @@ class CertificateRequest extends HandshakeMessage
}
if (len != 0) {
throw new SSLProtocolException("Bad CertificateRequest DN length");
throw new SSLProtocolException(
"Bad CertificateRequest DN length: " + len);
}
authorities = v.toArray(new DistinguishedName[v.size()]);
@ -1995,8 +2002,8 @@ static final class CertificateVerify extends HandshakeMessage {
if (!localSupportedSignAlgs.contains(
preferableSignatureAlgorithm)) {
throw new SSLHandshakeException(
"Unsupported SignatureAndHashAlgorithm in " +
"CertificateVerify message");
"Unsupported SignatureAndHashAlgorithm in " +
"CertificateVerify message: " + preferableSignatureAlgorithm);
}
}
@ -2364,7 +2371,8 @@ static final class Finished extends HandshakeMessage {
SecretKey prfKey = kg.generateKey();
if ("RAW".equals(prfKey.getFormat()) == false) {
throw new ProviderException(
"Invalid PRF output, format must be RAW");
"Invalid PRF output, format must be RAW. " +
"Format received: " + prfKey.getFormat());
}
byte[] finished = prfKey.getEncoded();
return finished;

@ -68,7 +68,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
ProtocolVersion maxVersion,
SecureRandom generator, PublicKey publicKey) throws IOException {
if (publicKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Public key not of type RSA");
throw new SSLKeyException("Public key not of type RSA: " +
publicKey.getAlgorithm());
}
this.protocolVersion = protocolVersion;
@ -100,7 +101,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
int messageSize, PrivateKey privateKey) throws IOException {
if (privateKey.getAlgorithm().equals("RSA") == false) {
throw new SSLKeyException("Private key not of type RSA");
throw new SSLKeyException("Private key not of type RSA: " +
privateKey.getAlgorithm());
}
if (currentVersion.useTLS10PlusSpec()) {
@ -161,8 +163,8 @@ final class RSAClientKeyExchange extends HandshakeMessage {
}
} catch (InvalidKeyException ibk) {
// the message is too big to process with RSA
throw new SSLProtocolException(
"Unable to process PreMasterSecret, may be too big");
throw new SSLException(
"Unable to process PreMasterSecret", ibk);
} catch (Exception e) {
// unlikely to happen, otherwise, must be a provider exception
if (debug != null && Debug.isOn("handshake")) {

@ -27,36 +27,17 @@
#include "jni_util.h"
#include "jlong.h"
#include "jvm.h"
#include "jdk_util.h"
#include "sun_misc_VMSupport.h"
typedef jobject (JNICALL *INIT_AGENT_PROPERTIES_FN)(JNIEnv *, jobject);
static INIT_AGENT_PROPERTIES_FN InitAgentProperties_fp = NULL;
#include "jdk_internal_vm_VMSupport.h"
JNIEXPORT jobject JNICALL
Java_sun_misc_VMSupport_initAgentProperties(JNIEnv *env, jclass cls, jobject props)
Java_jdk_internal_vm_VMSupport_initAgentProperties(JNIEnv *env, jclass cls, jobject props)
{
if (InitAgentProperties_fp == NULL) {
if (!JDK_InitJvmHandle()) {
JNU_ThrowInternalError(env,
"Handle for JVM not found for symbol lookup");
return NULL;
}
InitAgentProperties_fp = (INIT_AGENT_PROPERTIES_FN)
JDK_FindJvmEntry("JVM_InitAgentProperties");
if (InitAgentProperties_fp == NULL) {
JNU_ThrowInternalError(env,
"Mismatched VM version: JVM_InitAgentProperties not found");
return NULL;
}
}
return (*InitAgentProperties_fp)(env, props);
return JVM_InitAgentProperties(env, props);
}
JNIEXPORT jstring JNICALL
Java_sun_misc_VMSupport_getVMTemporaryDirectory(JNIEnv *env, jclass cls)
Java_jdk_internal_vm_VMSupport_getVMTemporaryDirectory(JNIEnv *env, jclass cls)
{
return JVM_GetTemporaryDirectory(env);
}

@ -2003,16 +2003,21 @@ ShowSplashScreen()
void *image_data = NULL;
float scale_factor = 1;
char *scaled_splash_name = NULL;
jboolean isImageScaled = JNI_FALSE;
size_t maxScaledImgNameLength = 0;
if (file_name == NULL){
return;
}
maxScaledImgNameLength = DoSplashGetScaledImgNameMaxPstfixLen(file_name);
scaled_splash_name = DoSplashGetScaledImageName(
jar_name, file_name, &scale_factor);
scaled_splash_name = JLI_MemAlloc(
maxScaledImgNameLength * sizeof(char));
isImageScaled = DoSplashGetScaledImageName(jar_name, file_name,
&scale_factor,
scaled_splash_name, maxScaledImgNameLength);
if (jar_name) {
if (scaled_splash_name) {
if (isImageScaled) {
image_data = JLI_JarUnpackFile(
jar_name, scaled_splash_name, &data_size);
}
@ -2030,17 +2035,14 @@ ShowSplashScreen()
}
} else {
DoSplashInit();
if (scaled_splash_name) {
if (isImageScaled) {
DoSplashSetScaleFactor(scale_factor);
DoSplashLoadFile(scaled_splash_name);
} else {
DoSplashLoadFile(file_name);
}
}
if (scaled_splash_name) {
JLI_MemFree(scaled_splash_name);
}
JLI_MemFree(scaled_splash_name);
DoSplashSetFileJarName(file_name, jar_name);

@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
int DoSplashLoadMemory(void* pdata, int size); /* requires preloading the file */
int DoSplashLoadFile(const char* filename);
@ -30,5 +30,6 @@ void DoSplashInit(void);
void DoSplashClose(void);
void DoSplashSetFileJarName(const char* fileName, const char* jarName);
void DoSplashSetScaleFactor(float scaleFactor);
char* DoSplashGetScaledImageName(const char* jarName, const char* fileName,
float* scaleFactor);
jboolean DoSplashGetScaledImageName(const char* jarName, const char* fileName,
float* scaleFactor, char *scaleImageName, const size_t scaleImageNameLength);
int DoSplashGetScaledImgNameMaxPstfixLen(const char *fileName);

@ -25,7 +25,7 @@
#include <stdio.h>
#include "splashscreen.h"
#include "jni.h"
extern void* SplashProcAddress(const char* name); /* in java_md.c */
/*
@ -38,8 +38,10 @@ typedef void (*SplashClose_t)(void);
typedef void (*SplashSetFileJarName_t)(const char* fileName,
const char* jarName);
typedef void (*SplashSetScaleFactor_t)(float scaleFactor);
typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
const char* jarName, float* scaleFactor);
typedef jboolean (*SplashGetScaledImageName_t)(const char* fileName,
const char* jarName, float* scaleFactor,
char *scaleImageName, const size_t scaleImageNameLength);
typedef int (*SplashGetScaledImgNameMaxPstfixLen_t)(const char* filename);
/*
* This macro invokes a function from the shared lib.
@ -60,6 +62,7 @@ typedef char* (*SplashGetScaledImageName_t)(const char* fileName,
#define INVOKE(name,def) _INVOKE(name,def,return)
#define INVOKEV(name) _INVOKE(name, ,;)
int DoSplashLoadMemory(void* pdata, int size) {
INVOKE(SplashLoadMemory, 0)(pdata, size);
}
@ -84,7 +87,13 @@ void DoSplashSetScaleFactor(float scaleFactor) {
INVOKEV(SplashSetScaleFactor)(scaleFactor);
}
char* DoSplashGetScaledImageName(const char* fileName, const char* jarName,
float* scaleFactor) {
INVOKE(SplashGetScaledImageName, NULL)(fileName, jarName, scaleFactor);
jboolean DoSplashGetScaledImageName(const char* fileName, const char* jarName,
float* scaleFactor, char *scaledImageName, const size_t scaledImageNameLength) {
INVOKE(SplashGetScaledImageName, 0)(fileName, jarName, scaleFactor,
scaledImageName, scaledImageNameLength);
}
int DoSplashGetScaledImgNameMaxPstfixLen(const char *fileName) {
INVOKE(SplashGetScaledImgNameMaxPstfixLen, 0)(fileName);
}

@ -26,7 +26,6 @@
module java.compact3 {
requires public java.compact2;
requires public java.compiler;
requires public java.httpclient;
requires public java.instrument;
requires public java.management;
requires public java.naming;

@ -1,220 +0,0 @@
/*
* Copyright (c) 2011, 2014, 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 com.apple.eawt;
import java.io.File;
import java.net.URI;
import java.util.*;
import java.awt.Window;
/**
* AppEvents are sent to listeners and handlers installed on the {@link Application}.
*
* @since Java for Mac OS X 10.6 Update 3
* @since Java for Mac OS X 10.5 Update 8
*/
@SuppressWarnings("serial") // JDK implementation class
public abstract class AppEvent extends EventObject {
AppEvent() {
super(Application.getApplication());
}
/**
* Contains a list of files.
*/
@SuppressWarnings("serial") // JDK implementation class
public abstract static class FilesEvent extends AppEvent {
final List<File> files;
FilesEvent(final List<File> files) {
this.files = files;
}
/**
* @return the list of files
*/
public List<File> getFiles() {
return files;
}
}
/**
* Event sent when the app is asked to open a list of files.
*
* @see OpenFilesHandler#openFiles(OpenFilesEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class OpenFilesEvent extends FilesEvent {
final String searchTerm;
OpenFilesEvent(final List<File> files, final String searchTerm) {
super(files);
this.searchTerm = searchTerm;
}
/**
* If the files were opened using the Spotlight search menu or a Finder search window, this method obtains the search term used to find the files.
* This is useful for highlighting the search term in the documents when they are opened.
* @return the search term used to find the files
*/
public String getSearchTerm() {
return searchTerm;
}
}
/**
* Event sent when the app is asked to print a list of files.
*
* @see PrintFilesHandler#printFiles(PrintFilesEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class PrintFilesEvent extends FilesEvent {
PrintFilesEvent(final List<File> files) {
super(files);
}
}
/**
* Event sent when the app is asked to open a URI.
*
* @see OpenURIHandler#openURI(OpenURIEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class OpenURIEvent extends AppEvent {
final URI uri;
OpenURIEvent(final URI uri) {
this.uri = uri;
}
/**
* @return the URI the app was asked to open
*/
public URI getURI() {
return uri;
}
}
/**
* Event sent when the application is asked to open it's about window.
*
* @see AboutHandler#handleAbout()
*/
@SuppressWarnings("serial") // JDK implementation class
public static class AboutEvent extends AppEvent { AboutEvent() { } }
/**
* Event sent when the application is asked to open it's preferences window.
*
* @see PreferencesHandler#handlePreferences()
*/
@SuppressWarnings("serial") // JDK implementation class
public static class PreferencesEvent extends AppEvent { PreferencesEvent() { } }
/**
* Event sent when the application is asked to quit.
*
* @see QuitHandler#handleQuitRequestWith(QuitEvent, QuitResponse)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class QuitEvent extends AppEvent { QuitEvent() { } }
/**
* Event sent when the application is asked to re-open itself.
*
* @see AppReOpenedListener#appReOpened(AppReOpenedEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class AppReOpenedEvent extends AppEvent { AppReOpenedEvent() { } }
/**
* Event sent when the application has become the foreground app, and when it has resigned being the foreground app.
*
* @see AppForegroundListener#appRaisedToForeground(AppForegroundEvent)
* @see AppForegroundListener#appMovedToBackground(AppForegroundEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class AppForegroundEvent extends AppEvent { AppForegroundEvent() { } }
/**
* Event sent when the application has been hidden or shown.
*
* @see AppHiddenListener#appHidden(AppHiddenEvent)
* @see AppHiddenListener#appUnhidden(AppHiddenEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class AppHiddenEvent extends AppEvent { AppHiddenEvent() { } }
/**
* Event sent when the user session has been changed via Fast User Switching.
*
* @see UserSessionListener#userSessionActivated(UserSessionEvent)
* @see UserSessionListener#userSessionDeactivated(UserSessionEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class UserSessionEvent extends AppEvent { UserSessionEvent() { } }
/**
* Event sent when the displays attached to the system enter and exit power save sleep.
*
* @see ScreenSleepListener#screenAboutToSleep(ScreenSleepEvent)
* @see ScreenSleepListener#screenAwoke(ScreenSleepEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class ScreenSleepEvent extends AppEvent { ScreenSleepEvent() { } }
/**
* Event sent when the system enters and exits power save sleep.
*
* @see SystemSleepListener#systemAboutToSleep(SystemSleepEvent)
* @see SystemSleepListener#systemAwoke(SystemSleepEvent)
*/
@SuppressWarnings("serial") // JDK implementation class
public static class SystemSleepEvent extends AppEvent { SystemSleepEvent() { } }
/**
* Event sent when a window is entering/exiting or has entered/exited full screen state.
*
* @see FullScreenUtilities
*
* @since Java for Mac OS X 10.7 Update 1
*/
@SuppressWarnings("serial") // JDK implementation class
public static class FullScreenEvent extends AppEvent {
final Window window;
FullScreenEvent(final Window window) {
this.window = window;
}
/**
* @return window transitioning between full screen states
*/
public Window getWindow() {
return window;
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -26,10 +26,10 @@
package com.apple.eawt;
import java.awt.Image;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.desktop.*;
import java.beans.Beans;
import javax.swing.JMenuBar;
@ -104,38 +104,38 @@ public class Application {
}
/**
* Adds sub-types of {@link AppEventListener} to listen for notifications from the native Mac OS X system.
* Adds sub-types of {@link SystemEventListener} to listen for notifications from the native Mac OS X system.
*
* @see AppForegroundListener
* @see AppHiddenListener
* @see AppReOpenedListener
* @see ScreenSleepListener
* @see SystemSleepListener
* @see UserSessionListener
* @see AppScreenSleepListener
* @see AppSystemSleepListener
* @see AppUserSessionListener
*
* @param listener
* @since Java for Mac OS X 10.6 Update 3
* @since Java for Mac OS X 10.5 Update 8
*/
public void addAppEventListener(final AppEventListener listener) {
public void addAppEventListener(final SystemEventListener listener) {
eventHandler.addListener(listener);
}
/**
* Removes sub-types of {@link AppEventListener} from listening for notifications from the native Mac OS X system.
* Removes sub-types of {@link SystemEventListener} from listening for notifications from the native Mac OS X system.
*
* @see AppForegroundListener
* @see AppHiddenListener
* @see AppReOpenedListener
* @see ScreenSleepListener
* @see SystemSleepListener
* @see UserSessionListener
* @see AppScreenSleepListener
* @see AppSystemSleepListener
* @see AppUserSessionListener
*
* @param listener
* @since Java for Mac OS X 10.6 Update 3
* @since Java for Mac OS X 10.5 Update 8
*/
public void removeAppEventListener(final AppEventListener listener) {
public void removeAppEventListener(final SystemEventListener listener) {
eventHandler.removeListener(listener);
}
@ -367,6 +367,17 @@ public class Application {
iconHandler.setDockIconBadge(badge);
}
/**
* Displays a progress bar to this application's Dock icon.
* Acceptable values are from 0 to 100, any other disables progress indication.
*
* @param value progress value
* @since 1.9
*/
public void setDockIconProgress(final int value) {
iconHandler.setDockIconProgress(value);
}
/**
* Sets the default menu bar to use when there are no active frames.
* Only used when the system property "apple.laf.useScreenMenuBar" is "true", and
@ -397,168 +408,4 @@ public class Application {
((CPlatformWindow)platformWindow).toggleFullScreen();
}
// -- DEPRECATED API --
/**
* Adds the specified ApplicationListener as a receiver of callbacks from this class.
* This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
*
* @param listener an implementation of ApplicationListener that handles ApplicationEvents
*
* @deprecated register individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
* @since 1.4
*/
@SuppressWarnings("deprecation")
@Deprecated
public void addApplicationListener(final ApplicationListener listener) {
eventHandler.legacyHandler.addLegacyAppListener(listener);
}
/**
* Removes the specified ApplicationListener from being a receiver of callbacks from this class.
* This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
*
* @param listener an implementation of ApplicationListener that had previously been registered to handle ApplicationEvents
*
* @deprecated unregister individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
* @since 1.4
*/
@SuppressWarnings("deprecation")
@Deprecated
public void removeApplicationListener(final ApplicationListener listener) {
eventHandler.legacyHandler.removeLegacyAppListener(listener);
}
/**
* Enables the Preferences item in the application menu. The ApplicationListener receives a callback for
* selection of the Preferences item in the application menu only if this is set to {@code true}.
*
* If a Preferences item isn't present, this method adds and enables it.
*
* @param enable specifies whether the Preferences item in the application menu should be enabled ({@code true}) or not ({@code false})
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public void setEnabledPreferencesMenu(final boolean enable) {
menuBarHandler.setPreferencesMenuItemVisible(true);
menuBarHandler.setPreferencesMenuItemEnabled(enable);
}
/**
* Enables the About item in the application menu. The ApplicationListener receives a callback for
* selection of the About item in the application menu only if this is set to {@code true}. Because AWT supplies
* a standard About window when an application may not, by default this is set to {@code true}.
*
* If the About item isn't present, this method adds and enables it.
*
* @param enable specifies whether the About item in the application menu should be enabled ({@code true}) or not ({@code false})
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public void setEnabledAboutMenu(final boolean enable) {
menuBarHandler.setAboutMenuItemEnabled(enable);
}
/**
* Determines if the Preferences item of the application menu is enabled.
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public boolean getEnabledPreferencesMenu() {
return menuBarHandler.isPreferencesMenuItemEnabled();
}
/**
* Determines if the About item of the application menu is enabled.
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public boolean getEnabledAboutMenu() {
return menuBarHandler.isAboutMenuItemEnabled();
}
/**
* Determines if the About item of the application menu is present.
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public boolean isAboutMenuItemPresent() {
return menuBarHandler.isAboutMenuItemVisible();
}
/**
* Adds the About item to the application menu if the item is not already present.
*
* @deprecated use {@link #setAboutHandler(AboutHandler)} with a non-null {@link AboutHandler} parameter
* @since 1.4
*/
@Deprecated
public void addAboutMenuItem() {
menuBarHandler.setAboutMenuItemVisible(true);
}
/**
* Removes the About item from the application menu if the item is present.
*
* @deprecated use {@link #setAboutHandler(AboutHandler)} with a null parameter
* @since 1.4
*/
@Deprecated
public void removeAboutMenuItem() {
menuBarHandler.setAboutMenuItemVisible(false);
}
/**
* Determines if the About Preferences of the application menu is present. By default there is no Preferences menu item.
*
* @deprecated no replacement
* @since 1.4
*/
@Deprecated
public boolean isPreferencesMenuItemPresent() {
return menuBarHandler.isPreferencesMenuItemVisible();
}
/**
* Adds the Preferences item to the application menu if the item is not already present.
*
* @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a non-null {@link PreferencesHandler} parameter
* @since 1.4
*/
@Deprecated
public void addPreferencesMenuItem() {
menuBarHandler.setPreferencesMenuItemVisible(true);
}
/**
* Removes the Preferences item from the application menu if that item is present.
*
* @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a null parameter
* @since 1.4
*/
@Deprecated
public void removePreferencesMenuItem() {
menuBarHandler.setPreferencesMenuItemVisible(false);
}
/**
* @deprecated Use {@code java.awt.MouseInfo.getPointerInfo().getLocation()}.
*
* @since 1.4
*/
@Deprecated
public static Point getMouseLocationOnScreen() {
return java.awt.MouseInfo.getPointerInfo().getLocation();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -46,7 +46,7 @@ package com.apple.eawt;
* @see ScreenSleepListener
* @see SystemSleepListener
*
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}.
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}.
* @since 1.4
*/
@SuppressWarnings("deprecation")

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -30,7 +30,7 @@ import java.util.EventObject;
/**
* The class of events sent to the deprecated ApplicationListener callbacks.
*
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}
* @since 1.4
*/
@Deprecated

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -47,7 +47,7 @@ import java.util.EventListener;
* @see SystemSleepListener
*
* @since 1.4
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link QuitResponse}
* @deprecated replaced by {@link AboutHandler}, {@link PreferencesHandler}, {@link AppReOpenedListener}, {@link OpenFilesHandler}, {@link PrintFilesHandler}, {@link QuitHandler}, {@link MacQuitResponse}
*/
@SuppressWarnings("deprecation")
@Deprecated
@ -134,7 +134,7 @@ public interface ApplicationListener extends EventListener {
* {@code event}. To reject the quit, set {@code isHandled(false)}.
*
* @param event a Quit Application event
* @deprecated use {@link QuitHandler} and {@link QuitResponse}
* @deprecated use {@link QuitHandler} and {@link MacQuitResponse}
*/
@Deprecated
public void handleQuit(ApplicationEvent event);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -25,7 +25,7 @@
package com.apple.eawt;
import com.apple.eawt.AppEvent.FullScreenEvent;
import com.apple.eawt.event.FullScreenEvent;
/**
* Abstract adapter class for receiving fullscreen events. This class is provided

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -25,13 +25,13 @@
package com.apple.eawt;
import com.apple.eawt.event.FullScreenEvent;
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.RootPaneContainer;
import com.apple.eawt.AppEvent.FullScreenEvent;
import sun.awt.SunToolkit;
import java.lang.annotation.Native;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -25,9 +25,9 @@
package com.apple.eawt;
import com.apple.eawt.event.FullScreenEvent;
import java.util.EventListener;
import com.apple.eawt.AppEvent.FullScreenEvent;
/**
*

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -25,9 +25,11 @@
package com.apple.eawt;
import java.awt.desktop.QuitResponse;
/**
* Used to respond to a request to quit the application.
* The QuitResponse may be used after the {@link QuitHandler#handleQuitRequestWith(AppEvent.QuitEvent, QuitResponse)} method has returned, and may be used from any thread.
* The QuitResponse may be used after the {@link QuitHandler#handleQuitRequestWith(AppEvent.QuitEvent, MacQuitResponse)} method has returned, and may be used from any thread.
*
* @see Application#setQuitHandler(QuitHandler)
* @see QuitHandler
@ -36,16 +38,17 @@ package com.apple.eawt;
* @since Java for Mac OS X 10.6 Update 3
* @since Java for Mac OS X 10.5 Update 8
*/
public class QuitResponse {
public class MacQuitResponse implements QuitResponse {
final _AppEventHandler appEventHandler;
QuitResponse(final _AppEventHandler appEventHandler) {
MacQuitResponse(final _AppEventHandler appEventHandler) {
this.appEventHandler = appEventHandler;
}
/**
* Notifies the external quit requester that the quit will proceed, and performs the default {@link QuitStrategy}.
*/
@Override
public void performQuit() {
if (appEventHandler.currentQuitResponse != this) return;
appEventHandler.performQuit();
@ -55,6 +58,7 @@ public class QuitResponse {
* Notifies the external quit requester that the user has explicitly canceled the pending quit, and leaves the application running.
* <b>Note: this will cancel a pending log-out, restart, or shutdown.</b>
*/
@Override
public void cancelQuit() {
if (appEventHandler.currentQuitResponse != this) return;
appEventHandler.cancelQuit();

@ -1,46 +0,0 @@
/*
* Copyright (c) 2011, 2012, 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 com.apple.eawt;
import com.apple.eawt.AppEvent.OpenURIEvent;
/**
* An implementor is notified when the application is asked to open a URI.
* The application only sends {@link com.apple.eawt.EAWTEvent.OpenURIEvent}s when it has been launched as a bundled Mac application, and it's Info.plist claims URL schemes in it's {@code CFBundleURLTypes} entry.
* See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a {@code CFBundleURLTypes} key to your app's Info.plist.
*
* @see Application#setOpenURIHandler(OpenURIHandler)
*
* @since Java for Mac OS X 10.6 Update 3
* @since Java for Mac OS X 10.5 Update 8
*/
public interface OpenURIHandler {
/**
* Called when the application is asked to open a URI
* @param e the request to open a URI
*/
public void openURI(final OpenURIEvent e);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -35,6 +35,7 @@ import sun.lwawt.macosx.CImage.Creator;
class _AppDockIconHandler {
private static native void nativeSetDockMenu(final long cmenu);
private static native void nativeSetDockIconImage(final long image);
private static native void nativeSetDockIconProgress(final int value);
private static native long nativeGetDockIconImage();
private static native void nativeSetDockIconBadge(final String badge);
@ -93,6 +94,10 @@ class _AppDockIconHandler {
nativeSetDockIconBadge(badge);
}
void setDockIconProgress(int value) {
nativeSetDockIconProgress(value);
}
static Creator getCImageCreator() {
try {
final Method getCreatorMethod = CImage.class.getDeclaredMethod("getCreator", new Class<?>[] {});

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -25,17 +25,47 @@
package com.apple.eawt;
import java.awt.*;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.desktop.AboutEvent;
import java.awt.desktop.AboutHandler;
import java.awt.desktop.AppForegroundEvent;
import java.awt.desktop.AppForegroundListener;
import java.awt.desktop.AppHiddenEvent;
import java.awt.desktop.AppHiddenListener;
import java.awt.desktop.AppReopenedEvent;
import java.awt.desktop.AppReopenedListener;
import java.awt.desktop.OpenFilesEvent;
import java.awt.desktop.OpenFilesHandler;
import java.awt.desktop.OpenURIEvent;
import java.awt.desktop.OpenURIHandler;
import java.awt.desktop.PreferencesEvent;
import java.awt.desktop.PreferencesHandler;
import java.awt.desktop.PrintFilesEvent;
import java.awt.desktop.PrintFilesHandler;
import java.awt.desktop.QuitEvent;
import java.awt.desktop.QuitHandler;
import java.awt.desktop.QuitStrategy;
import java.awt.desktop.ScreenSleepEvent;
import java.awt.desktop.ScreenSleepListener;
import java.awt.desktop.SystemEventListener;
import java.awt.desktop.SystemSleepEvent;
import java.awt.desktop.SystemSleepListener;
import java.awt.desktop.UserSessionEvent;
import java.awt.desktop.UserSessionEvent.Reason;
import java.awt.desktop.UserSessionListener;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.*;
import java.util.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import com.apple.eawt.AppEvent.*;
class _AppEventHandler {
private static final int NOTIFY_ABOUT = 1;
private static final int NOTIFY_PREFS = 2;
@ -84,9 +114,7 @@ class _AppEventHandler {
final _ScreenSleepDispatcher screenSleepDispatcher = new _ScreenSleepDispatcher();
final _SystemSleepDispatcher systemSleepDispatcher = new _SystemSleepDispatcher();
final _AppEventLegacyHandler legacyHandler = new _AppEventLegacyHandler(this);
QuitStrategy defaultQuitAction = QuitStrategy.SYSTEM_EXIT_0;
QuitStrategy defaultQuitAction = QuitStrategy.NORMAL_EXIT;
_AppEventHandler() {
final String strategyProp = System.getProperty("apple.eawt.quitStrategy");
@ -94,15 +122,16 @@ class _AppEventHandler {
if ("CLOSE_ALL_WINDOWS".equals(strategyProp)) {
setDefaultQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS);
} else if ("SYSTEM_EXIT_O".equals(strategyProp)) {
setDefaultQuitStrategy(QuitStrategy.SYSTEM_EXIT_0);
} else if ("SYSTEM_EXIT_O".equals(strategyProp)
|| "NORMAL_EXIT".equals(strategyProp)) {
setDefaultQuitStrategy(QuitStrategy.NORMAL_EXIT);
} else {
System.err.println("unrecognized apple.eawt.quitStrategy: " + strategyProp);
}
}
void addListener(final AppEventListener listener) {
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.addListener((AppReOpenedListener)listener);
void addListener(final SystemEventListener listener) {
if (listener instanceof AppReopenedListener) reOpenAppDispatcher.addListener((AppReopenedListener)listener);
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.addListener((AppForegroundListener)listener);
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.addListener((AppHiddenListener)listener);
if (listener instanceof UserSessionListener) userSessionDispatcher.addListener((UserSessionListener)listener);
@ -110,8 +139,8 @@ class _AppEventHandler {
if (listener instanceof SystemSleepListener) systemSleepDispatcher.addListener((SystemSleepListener)listener);
}
void removeListener(final AppEventListener listener) {
if (listener instanceof AppReOpenedListener) reOpenAppDispatcher.removeListener((AppReOpenedListener)listener);
void removeListener(final SystemEventListener listener) {
if (listener instanceof AppReopenedListener) reOpenAppDispatcher.removeListener((AppReopenedListener)listener);
if (listener instanceof AppForegroundListener) foregroundAppDispatcher.removeListener((AppForegroundListener)listener);
if (listener instanceof AppHiddenListener) hiddenAppDispatcher.removeListener((AppHiddenListener)listener);
if (listener instanceof UserSessionListener) userSessionDispatcher.removeListener((UserSessionListener)listener);
@ -127,10 +156,10 @@ class _AppEventHandler {
this.defaultQuitAction = defaultQuitAction;
}
QuitResponse currentQuitResponse;
synchronized QuitResponse obtainQuitResponse() {
MacQuitResponse currentQuitResponse;
synchronized MacQuitResponse obtainQuitResponse() {
if (currentQuitResponse != null) return currentQuitResponse;
return currentQuitResponse = new QuitResponse(this);
return currentQuitResponse = new MacQuitResponse(this);
}
synchronized void cancelQuit() {
@ -142,7 +171,7 @@ class _AppEventHandler {
currentQuitResponse = null;
try {
if (defaultQuitAction == QuitStrategy.SYSTEM_EXIT_0) System.exit(0);
if (defaultQuitAction == QuitStrategy.NORMAL_EXIT) System.exit(0);
if (defaultQuitAction != QuitStrategy.CLOSE_ALL_WINDOWS) {
throw new RuntimeException("Unknown quit action");
@ -270,10 +299,10 @@ class _AppEventHandler {
}
}
class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReOpenedListener> {
void performOnListener(AppReOpenedListener listener, final _NativeEvent event) {
final AppReOpenedEvent e = new AppReOpenedEvent();
listener.appReOpened(e);
class _AppReOpenedDispatcher extends _AppEventMultiplexor<AppReopenedListener> {
void performOnListener(AppReopenedListener listener, final _NativeEvent event) {
final AppReopenedEvent e = new AppReopenedEvent();
listener.appReopened(e);
}
}
@ -302,7 +331,9 @@ class _AppEventHandler {
}
class _UserSessionDispatcher extends _BooleanAppEventMultiplexor<UserSessionListener, UserSessionEvent> {
UserSessionEvent createEvent(final boolean isTrue) { return new UserSessionEvent(); }
UserSessionEvent createEvent(final boolean isTrue) {
return new UserSessionEvent(Reason.UNSPECIFIED);
}
void performFalseEventOn(final UserSessionListener listener, final UserSessionEvent e) {
listener.userSessionDeactivated(e);
@ -391,7 +422,7 @@ class _AppEventHandler {
}
void performUsing(final QuitHandler handler, final _NativeEvent event) {
final QuitResponse response = obtainQuitResponse(); // obtains the "current" quit response
final MacQuitResponse response = obtainQuitResponse(); // obtains the "current" quit response
handler.handleQuitRequestWith(new QuitEvent(), response);
}
}
@ -524,9 +555,6 @@ class _AppEventHandler {
setHandlerContext(AppContext.getAppContext());
// if a new handler is installed, block addition of legacy ApplicationListeners
if (handler == legacyHandler) return;
legacyHandler.blockLegacyAPI();
}
void performDefaultAction(final _NativeEvent event) { } // by default, do nothing
@ -574,10 +602,6 @@ class _AppEventHandler {
}
}
}
// if a new handler is installed, block addition of legacy ApplicationListeners
if (handler == legacyHandler) return;
legacyHandler.blockLegacyAPI();
}
}
}

@ -1,188 +0,0 @@
/*
* Copyright (c) 2011, 2013, 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 com.apple.eawt;
import java.awt.Toolkit;
import java.io.File;
import java.util.*;
import com.apple.eawt.AppEvent.*;
@SuppressWarnings("deprecation")
class _AppEventLegacyHandler implements AboutHandler, PreferencesHandler, _OpenAppHandler, AppReOpenedListener, OpenFilesHandler, PrintFilesHandler, QuitHandler {
final _AppEventHandler parent;
final Vector<ApplicationListener> legacyAppListeners = new Vector<ApplicationListener>();
boolean blockLegacyAPI;
boolean initializedParentDispatchers;
_AppEventLegacyHandler(final _AppEventHandler parent) {
this.parent = parent;
}
void blockLegacyAPI() {
blockLegacyAPI = true;
}
void checkIfLegacyAPIBlocked() {
if (!blockLegacyAPI) return;
throw new IllegalStateException("Cannot add com.apple.eawt.ApplicationListener after installing an app event handler");
}
void addLegacyAppListener(final ApplicationListener listener) {
checkIfLegacyAPIBlocked();
if (!initializedParentDispatchers) {
final _AppMenuBarHandler menuBarHandler = Application.getApplication().menuBarHandler;
final boolean prefsMenuAlreadyExplicitlySet = menuBarHandler.prefsMenuItemExplicitlySet;
parent.aboutDispatcher.setHandler(this);
parent.preferencesDispatcher.setHandler(this);
if (!prefsMenuAlreadyExplicitlySet) {
menuBarHandler.setPreferencesMenuItemVisible(false); // default behavior is not to have a preferences item
}
parent.openAppDispatcher.setHandler(this);
parent.reOpenAppDispatcher.addListener(this);
parent.openFilesDispatcher.setHandler(this);
parent.printFilesDispatcher.setHandler(this);
parent.quitDispatcher.setHandler(this);
initializedParentDispatchers = true;
}
synchronized (legacyAppListeners) {
legacyAppListeners.addElement(listener);
}
}
public void removeLegacyAppListener(final ApplicationListener listener) {
checkIfLegacyAPIBlocked();
synchronized (legacyAppListeners) {
legacyAppListeners.removeElement(listener);
}
}
@Override
public void handleAbout(final AboutEvent e) {
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handleAbout(ae);
}
});
if (ae.isHandled()) return;
parent.openCocoaAboutWindow();
}
@Override
public void handlePreferences(final PreferencesEvent e) {
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handlePreferences(ae);
}
});
}
@Override
public void handleOpenApp() {
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handleOpenApplication(ae);
}
});
}
@Override
public void appReOpened(final AppReOpenedEvent e) {
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handleReOpenApplication(ae);
}
});
}
@Override
public void openFiles(final OpenFilesEvent e) {
final List<File> files = e.getFiles();
for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handleOpenFile(ae);
}
});
}
}
@Override
public void printFiles(PrintFilesEvent e) {
final List<File> files = e.getFiles();
for (final File file : files) { // legacy ApplicationListeners only understood one file at a time
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit(), file.getAbsolutePath());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handlePrintFile(ae);
}
});
}
}
@Override
public void handleQuitRequestWith(final QuitEvent e, final QuitResponse response) {
final ApplicationEvent ae = new ApplicationEvent(Toolkit.getDefaultToolkit());
sendEventToEachListenerUntilHandled(ae, new EventDispatcher() {
public void dispatchEvent(final ApplicationListener listener) {
listener.handleQuit(ae);
}
});
if (ae.isHandled()) {
parent.performQuit();
} else {
parent.cancelQuit();
}
}
interface EventDispatcher {
void dispatchEvent(final ApplicationListener listener);
}
// helper that cycles through the loop and aborts if the event is handled, or there are no listeners
void sendEventToEachListenerUntilHandled(final ApplicationEvent event, final EventDispatcher dispatcher) {
synchronized (legacyAppListeners) {
if (legacyAppListeners.size() == 0) return;
final Enumeration<ApplicationListener> e = legacyAppListeners.elements();
while (e.hasMoreElements() && !event.isHandled()) {
dispatcher.dispatchEvent(e.nextElement());
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2016, 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
@ -26,7 +26,6 @@
package com.apple.eawt;
import java.awt.Frame;
import java.awt.peer.MenuComponentPeer;
import javax.swing.*;
import javax.swing.plaf.MenuBarUI;

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016, 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 com.apple.eawt.event;
import com.apple.eawt.Application;
import java.awt.Window;
import java.util.EventObject;
@SuppressWarnings("serial") // JDK implementation class
public class FullScreenEvent extends EventObject {
final Window window;
/**
* @param window window
*/
public FullScreenEvent(final Window window) {
super(Application.getApplication());
this.window = window;
}
/**
* @return window transitioning between full screen states
*/
public Window getWindow() {
return window;
}
}

@ -32,7 +32,7 @@ import java.awt.GraphicsDevice;
import java.awt.Insets;
import java.awt.Window;
import java.util.Objects;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.opengl.CGLGraphicsConfig;
public final class CGraphicsDevice extends GraphicsDevice
@ -140,7 +140,7 @@ public final class CGraphicsDevice extends GraphicsDevice
public void displayChanged() {
xResolution = nativeGetXResolution(displayID);
yResolution = nativeGetYResolution(displayID);
scale = (int) nativeGetScaleFactor(displayID);
initScaleFactor();
//TODO configs/fullscreenWindow/modes?
}
@ -249,6 +249,17 @@ public final class CGraphicsDevice extends GraphicsDevice
return nativeGetDisplayModes(displayID);
}
private void initScaleFactor() {
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
scale = (int) (debugScale >= 1
? Math.round(debugScale)
: nativeGetScaleFactor(displayID));
} else {
scale = 1;
}
}
private static native double nativeGetScaleFactor(int displayID);
private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);

@ -142,94 +142,6 @@ public final class CFontManager extends SunFontManager {
}
}
@Override
public Font2D createFont2D(File fontFile, int fontFormat, boolean isCopy, CreatedFontTracker tracker) throws FontFormatException {
String fontFilePath = fontFile.getPath();
Font2D font2D = null;
final File fFile = fontFile;
final CreatedFontTracker _tracker = tracker;
try {
switch (fontFormat) {
case Font.TRUETYPE_FONT:
font2D = new TrueTypeFont(fontFilePath, null, 0, true);
break;
case Font.TYPE1_FONT:
font2D = new Type1Font(fontFilePath, null, isCopy);
break;
default:
throw new FontFormatException("Unrecognised Font Format");
}
} catch (FontFormatException e) {
if (isCopy) {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
public Object run() {
if (_tracker != null) {
_tracker.subBytes((int)fFile.length());
}
fFile.delete();
return null;
}
});
}
throw(e);
}
if (isCopy) {
FileFont.setFileToRemove(font2D, fontFile, tracker);
synchronized (FontManager.class) {
if (tmpFontFiles == null) {
tmpFontFiles = new Vector<File>();
}
tmpFontFiles.add(fontFile);
if (fileCloser == null) {
final Runnable fileCloserRunnable = new Runnable() {
public void run() {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Object>() {
public Object run() {
for (int i=0;i<CHANNELPOOLSIZE;i++) {
if (fontFileCache[i] != null) {
try {
fontFileCache[i].close();
} catch (Exception e) {}
}
}
if (tmpFontFiles != null) {
File[] files = new File[tmpFontFiles.size()];
files = tmpFontFiles.toArray(files);
for (int f=0; f<files.length;f++) {
try {
files[f].delete();
} catch (Exception e) {}
}
}
return null;
}
});
}
};
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
/* The thread must be a member of a thread group
* which will not get GCed before VM exit.
* Make its parent the top-level thread group.
*/
ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
fileCloser = new ManagedLocalsThread(rootTG, fileCloserRunnable);
fileCloser.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(fileCloser);
return null;
}
);
}
}
}
return font2D;
}
protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
loadNativeDirFonts(dirName);
super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);

@ -478,13 +478,9 @@ public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements Raster
// <rdar://problem/4488745> For the Sun2D renderer we should rely on the implementation of the super class.
// BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class.
int offsetX = 0;
int offsetY = 0;
if (sg2d.transformState == SunGraphics2D.TRANSFORM_ANY_TRANSLATE ||
sg2d.transformState == SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
offsetX = (int) sg2d.transform.getTranslateX();
offsetY = (int) sg2d.transform.getTranslateY();
} else if (sg2d.transformState != SunGraphics2D.TRANSFORM_ISIDENT) { return false; }
if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
return false;
}
// reset the clip (this is how it works on windows)
// we actually can handle a case with any clips but windows ignores the light clip
@ -498,18 +494,23 @@ public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements Raster
return true;
}
// the rectangle returned from clipCopyArea() is in the coordinate space of the surface (image)
// we need to substract the offsetX and offsetY to move it to the coordinate space of the graphics2d.
// sg2d.drawImage expects the destination rect to be in the coord space of the graphics2d. <rdar://3746194>
// (vm)
x = clippedCopyAreaRect.x - offsetX;
y = clippedCopyAreaRect.y - offsetY;
// the rectangle returned from clipCopyArea() is in the coordinate space
// of the surface (image)
x = clippedCopyAreaRect.x;
y = clippedCopyAreaRect.y;
w = clippedCopyAreaRect.width;
h = clippedCopyAreaRect.height;
// copy (dst coordinates are in the coord space of the graphics2d, and src coordinates are
// in the coordinate space of the image)
sg2d.drawImage(this.bim, x + dx, y + dy, x + dx + w, y + dy + h, x + offsetX, y + offsetY, x + w + offsetX, y + h + offsetY, null);
// copy (dst coordinates are in the coord space of the graphics2d, and
// src coordinates are in the coordinate space of the image)
// sg2d.drawImage expects the destination rect to be in the coord space
// of the graphics2d. <rdar://3746194> (vm)
// we need to substract the transX and transY to move it
// to the coordinate space of the graphics2d.
int dstX = x + dx - sg2d.transX;
int dstY = y + dy - sg2d.transY;
sg2d.drawImage(this.bim, dstX, dstY, dstX + w, dstY + h,
x, y, x + w, y + h, null);
// restore the clip
sg2d.setClip(clip);

@ -1094,19 +1094,13 @@ public abstract class OSXSurfaceData extends BufImgSurfaceData {
}
/**
* Clips the copy area to the heavywieght bounds and returns the cliped rectangle. The tricky part here is the
* passed arguments x, y are in the coordinate space of the sg2d/lightweight comp. In order to do the clipping we
* translate them to the coordinate space of the surface, and the returned clipped rectangle is in the coordinate
* space of the surface.
* Clips the copy area to the heavyweight bounds and returns the clipped rectangle.
* The returned clipped rectangle is in the coordinate space of the surface.
*/
protected Rectangle clipCopyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
// we need to clip against the heavyweight bounds
copyAreaBounds.setBounds(sg2d.devClip.getLoX(), sg2d.devClip.getLoY(), sg2d.devClip.getWidth(), sg2d.devClip.getHeight());
// put src rect into surface coordinate space
x += sg2d.transX;
y += sg2d.transY;
// clip src rect
srcCopyAreaRect.setBounds(x, y, w, h);
intersection(srcCopyAreaRect, copyAreaBounds, srcCopyAreaRect);

@ -175,31 +175,6 @@ public abstract class CGLSurfaceData extends OGLSurfaceData {
return scale;
}
@Override
public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
int dx, int dy) {
final int state = sg2d.transformState;
if (state > SunGraphics2D.TRANSFORM_TRANSLATESCALE
|| sg2d.compositeState >= SunGraphics2D.COMP_XOR) {
return false;
}
if (state <= SunGraphics2D.TRANSFORM_ANY_TRANSLATE) {
x += sg2d.transX;
y += sg2d.transY;
} else if (state == SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
final double[] coords = {x, y, x + w, y + h, x + dx, y + dy};
sg2d.transform.transform(coords, 0, coords, 0, 3);
x = (int) Math.ceil(coords[0] - 0.5);
y = (int) Math.ceil(coords[1] - 0.5);
w = ((int) Math.ceil(coords[2] - 0.5)) - x;
h = ((int) Math.ceil(coords[3] - 0.5)) - y;
dx = ((int) Math.ceil(coords[4] - 0.5)) - x;
dy = ((int) Math.ceil(coords[5] - 0.5)) - y;
}
oglRenderPipe.copyArea(sg2d, x, y, w, h, dx, dy);
return true;
}
protected native void clearWindow();
public static class CGLWindowSurfaceData extends CGLSurfaceData {

Some files were not shown because too many files have changed in this diff Show More