Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2015-06-09 12:28:37 +0300
committerjfrijters <jfrijters>2015-06-09 12:28:37 +0300
commitbe6daf30426500ed3c3188b9c2a7882b55176705 (patch)
tree710493db1ddeca45498846e6885d164a832d44c1
parentdab43d5cf4bf3b8b9a5b5f8cb175dee38a5fe69f (diff)
Integrated OpenJDK 8u45.
-rw-r--r--awt/native.cs6
-rw-r--r--awt/toolkit-0.95.cs8
-rw-r--r--openjdk/FORKED9
-rw-r--r--openjdk/allsources.lst127
-rw-r--r--openjdk/ikvm/internal/Winsock.java3
-rw-r--r--openjdk/java/io/FileInputStream.java130
-rw-r--r--openjdk/java/io/FileOutputStream.java118
-rw-r--r--openjdk/java/io/RandomAccessFile.java340
-rw-r--r--openjdk/java/lang/Class.java172
-rw-r--r--openjdk/java/lang/ClassLoader.java279
-rw-r--r--openjdk/java/lang/StringHelper.java951
-rw-r--r--openjdk/java/lang/System.java80
-rw-r--r--openjdk/java/lang/reflect/Constructor.java416
-rw-r--r--openjdk/java/lang/reflect/Executable.java720
-rw-r--r--openjdk/java/lang/reflect/Field.java152
-rw-r--r--openjdk/java/lang/reflect/Method.java415
-rw-r--r--openjdk/java/lang/reflect/Proxy.java642
-rw-r--r--openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java21
-rw-r--r--openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java3
-rw-r--r--openjdk/java/net/TwoStacksPlainSocketImpl_c.java7
-rw-r--r--openjdk/java/net/net_util_md.java27
-rw-r--r--openjdk/java/util/concurrent/ForkJoinPool.java3363
-rw-r--r--openjdk/map.xml18
-rw-r--r--openjdk/openjdk.build8
-rw-r--r--openjdk/response.txt24
-rw-r--r--openjdk/sun/awt/SunToolkit.java518
-rw-r--r--openjdk/sun/awt/shell/Win32ShellFolder2.java21
-rw-r--r--openjdk/sun/awt/shell/Win32ShellFolderManager2.java66
-rw-r--r--openjdk/sun/java2d/loops/TransformHelper.java27
-rw-r--r--openjdk/sun/misc/VM.java38
-rw-r--r--openjdk/sun/misc/Version.java37
-rw-r--r--openjdk/sun/nio/ch/DatagramChannelImpl.java94
-rw-r--r--openjdk/sun/nio/ch/DotNetSelectorImpl.java6
-rw-r--r--openjdk/sun/nio/ch/FileChannelImpl.java115
-rw-r--r--openjdk/sun/nio/ch/Net.java99
-rw-r--r--openjdk/sun/nio/ch/PollArrayWrapper.java37
-rw-r--r--openjdk/sun/nio/ch/SocketOptionRegistry.java6
-rw-r--r--openjdk/sun/nio/fs/NetFileSystemProvider.java2
-rw-r--r--openjdk/sun/reflect/Reflection.java95
-rw-r--r--openjdk/sun/reflect/ReflectionFactory.java64
-rw-r--r--runtime/openjdk/java.lang.cs7
-rw-r--r--runtime/openjdk/java.lang.invoke.cs8
-rw-r--r--runtime/openjdk/java.net.cs32
-rw-r--r--runtime/openjdk/java.util.cs339
-rw-r--r--runtime/openjdk/misc.cs39
-rw-r--r--runtime/openjdk/sun.misc.cs23
-rw-r--r--runtime/openjdk/sun.nio.ch.cs51
47 files changed, 3994 insertions, 5769 deletions
diff --git a/awt/native.cs b/awt/native.cs
index b5dee449..62b92dd2 100644
--- a/awt/native.cs
+++ b/awt/native.cs
@@ -566,7 +566,7 @@ namespace IKVM.NativeCode.sun.awt.shell
{
return;
}
- Marshal.Release(pIDL);
+ Marshal.FreeCoTaskMem(pIDL);
}
/// <summary>
@@ -608,8 +608,8 @@ namespace IKVM.NativeCode.sun.awt.shell
return (int)atts[0];
}
- [System.Security.SecurityCritical]
- public static String getFileSystemPath(int csidl)
+ [System.Security.SecuritySafeCritical]
+ public static String getFileSystemPath0(int csidl)
{
IntPtr pIDL = new IntPtr();
int hRes = ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero, (ShellApi.CSIDL)csidl, ref pIDL);
diff --git a/awt/toolkit-0.95.cs b/awt/toolkit-0.95.cs
index a8a055aa..3326c8c8 100644
--- a/awt/toolkit-0.95.cs
+++ b/awt/toolkit-0.95.cs
@@ -287,8 +287,6 @@ namespace ikvm.awt
public sealed class NetToolkit : sun.awt.SunToolkit, ikvm.awt.IkvmToolkit, sun.awt.KeyboardFocusManagerPeerProvider
{
- public static readonly String DATA_TRANSFERER_CLASS_NAME = typeof(NetDataTransferer).AssemblyQualifiedName;
-
private int resolution;
private NetClipboard clipboard;
private bool eventQueueSynchronizationContext;
@@ -330,7 +328,6 @@ namespace ikvm.awt
public NetToolkit()
{
- setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
}
/// <summary>
@@ -1039,6 +1036,11 @@ namespace ikvm.awt
{
throw new NotImplementedException();
}
+
+ public override sun.awt.datatransfer.DataTransferer getDataTransferer()
+ {
+ return NetDataTransferer.getInstanceImpl();
+ }
}
sealed class NetMenuBarPeer : java.awt.peer.MenuBarPeer
diff --git a/openjdk/FORKED b/openjdk/FORKED
index 52a8921f..20207d02 100644
--- a/openjdk/FORKED
+++ b/openjdk/FORKED
@@ -4,9 +4,9 @@
# This file list all forked OpenJDK files in their original OpenJDK location and their forked ikvm/openjdk location.
# Each line not starting with # contains a mapping: <original>=<forked>
#
-build/linux-amd64/gensrc/sun/misc/Version.java=sun/misc/Version.java
-build/linux-amd64/gensrc/sun/nio/ch/SocketOptionRegistry.java=sun/nio/ch/SocketOptionRegistry.java
-build/linux-amd64/gensrc/sun/nio/cs/StandardCharsets.java=sun/nio/cs/StandardCharsets.java
+build/linux-x86_64-normal-server-release/jdk/gensrc/sun/misc/Version.java=sun/misc/Version.java
+build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/ch/SocketOptionRegistry.java=sun/nio/ch/SocketOptionRegistry.java
+build/linux-x86_64-normal-server-release/jdk/gensrc/sun/nio/cs/StandardCharsets.java=sun/nio/cs/StandardCharsets.java
jdk/src/macosx/classes/java/lang/ClassLoaderHelper.java=java/lang/ClassLoaderHelper.java
jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java=com/sun/imageio/plugins/jpeg/JPEGImageReader.java
jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java=com/sun/imageio/plugins/jpeg/JPEGImageWriter.java
@@ -33,6 +33,7 @@ jdk/src/share/classes/java/lang/Enum.java=java/lang/Enum.java
jdk/src/share/classes/java/lang/management/PlatformComponent.java=java/lang/management/PlatformComponent.java
jdk/src/share/classes/java/lang/ref/SoftReference.java=java/lang/ref/SoftReference.java
jdk/src/share/classes/java/lang/reflect/Constructor.java=java/lang/reflect/Constructor.java
+jdk/src/share/classes/java/lang/reflect/Executable.java=java/lang/reflect/Executable.java
jdk/src/share/classes/java/lang/reflect/Field.java=java/lang/reflect/Field.java
jdk/src/share/classes/java/lang/reflect/Method.java=java/lang/reflect/Method.java
jdk/src/share/classes/java/lang/reflect/Proxy.java=java/lang/reflect/Proxy.java
@@ -53,7 +54,6 @@ jdk/src/share/classes/java/util/concurrent/atomic/AtomicLong.java=../classpath/j
jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java=../classpath/java/util/concurrent/atomic/AtomicLongArray.java
jdk/src/share/classes/java/util/concurrent/atomic/AtomicReference.java=../classpath/java/util/concurrent/atomic/AtomicReference.java
jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java=../classpath/java/util/concurrent/atomic/AtomicReferenceArray.java
-jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java=java/util/concurrent/ForkJoinPool.java
jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java=java/util/concurrent/locks/AbstractQueuedSynchronizer.java
jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java=java/util/concurrent/locks/LockSupport.java
jdk/src/share/classes/sun/awt/EmbeddedFrame.java=sun/awt/EmbeddedFrame.java
@@ -99,7 +99,6 @@ jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java=sun/net/www
jdk/src/windows/classes/sun/nio/ch/DefaultSelectorProvider.java=sun/nio/ch/DefaultSelectorProvider.java
jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java=sun/nio/ch/FileDispatcherImpl.java
jdk/src/windows/classes/sun/nio/ch/Iocp.java=sun/nio/ch/Iocp.java
-jdk/src/windows/classes/sun/nio/ch/PollArrayWrapper.java=sun/nio/ch/PollArrayWrapper.java
jdk/src/windows/classes/sun/nio/ch/SocketDispatcher.java=sun/nio/ch/SocketDispatcher.java
jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java=sun/nio/ch/WindowsAsynchronousFileChannelImpl.java
jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java=sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java
diff --git a/openjdk/allsources.lst b/openjdk/allsources.lst
index 9893116e..d75f5526 100644
--- a/openjdk/allsources.lst
+++ b/openjdk/allsources.lst
@@ -124,7 +124,6 @@ java/net/TwoStacksPlainSocketImpl_c.java
java/nio/Bits.java
java/security/AccessController.java
java/security/ProtectionDomain.java
-java/util/concurrent/ForkJoinPool.java
java/util/concurrent/locks/AbstractQueuedSynchronizer.java
java/util/concurrent/locks/LockSupport.java
java/util/zip/Adler32.java
@@ -171,6 +170,7 @@ sun/font/SunFontManager.java
sun/font/TrueTypeFont.java
sun/java2d/cmm/lcms/LCMS.java
sun/java2d/HeadlessGraphicsEnvironment.java
+sun/java2d/loops/TransformHelper.java
sun/java2d/pipe/ShapeSpanIterator.java
sun/java2d/SunCompositeContext.java
sun/java2d/SunGraphics2D.java
@@ -214,7 +214,6 @@ sun/nio/ch/Iocp.java
sun/nio/ch/IOUtil.java
sun/nio/ch/NativeDispatcher.java
sun/nio/ch/Net.java
-sun/nio/ch/PollArrayWrapper.java
sun/nio/ch/SelectionKeyImpl.java
sun/nio/ch/SocketDispatcher.java
sun/nio/ch/SocketOptionRegistry.java
@@ -5989,6 +5988,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/AbstractExtensionHandler.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/AbstractReferenceFinderImpl.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/Constants.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMBuilder.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForest.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/ws/wsdl/parser/DOMForestParser.java
@@ -6226,6 +6226,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/gbind/SourceNode.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/AbstractReferenceFinderImpl.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/ContentHandlerNamespacePrefixAdapter.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMBuilder.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForest.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/internalizer/DOMForestParser.java
@@ -6373,6 +6374,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/IDResolver.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/InternalAccessorFactory.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Locatable.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/Messages.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/CharacterEscapeHandler.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/DataWriter.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/bind/marshaller/DumbEscapeHandler.java
@@ -6920,6 +6922,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/UUDecoderStream.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/packaging/mime/util/UUEncoderStream.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/AttachmentPartImpl.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/dynamic/SOAPFactoryDynamicImpl.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/dynamic/SOAPMessageFactoryDynamicImpl.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/Envelope.java
@@ -7214,6 +7217,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AbstractCreatorProcessor.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AbstractProcessor.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/AttributesHolder.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/FragmentedArray.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/MutableXMLStreamBuffer.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/sax/DefaultWithLexicalHandler.java
@@ -7504,6 +7508,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/server/WSWebServiceContext.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/ServiceSharedFeatureMarker.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/SOAPVersion.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamWriterFactory.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/api/WebServiceFeatureFactory.java
@@ -7595,6 +7600,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/Stub.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/Closeable.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/commons/xmlutil/Converter.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/ManagementAssertionCreator.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/config/management/policy/ManagementPolicyValidator.java
@@ -7611,6 +7617,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/RawAccessorWrapper.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/db/glassfish/WrapperBridge.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/BindingTypeFeature.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/EPRRecipe.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/HttpConfigFeature.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/developer/JAXBContextFactory.java
@@ -7855,6 +7862,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/privateutil/ServiceFinder.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/SimpleAssertion.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/AssertionData.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/ExternalAttachmentsUnmarshaller.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/attach/package-info.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/CompactModelGenerator.java
@@ -7981,6 +7989,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/WrapperBridge.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/WrapperComposite.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/db/XMLBridge.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/spi/ProviderImpl.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/Attributes.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/streaming/DOMStreamReader.java
@@ -8050,6 +8059,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/VersionUtil.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/CDATA.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContentHandlerToXMLStreamWriter.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/DummyLocation.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/NamedNodeMapIterator.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/ws/util/xml/NamespaceContextExAdaper.java
@@ -8240,6 +8250,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/parser/XSOMParser.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/SCD.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ComponentNameFunction.java
+@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/ContextClassloaderLocal.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DeferedCollection.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/DomAnnotationParserFactory.java
@OPENJDK@/jaxws/src/share/jaxws_classes/com/sun/xml/internal/xsom/util/NameGetter.java
@@ -8700,6 +8711,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/com/sun/imageio/stream/StreamFinalizer.java
@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/ContentSigner.java
@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/ContentSignerParameters.java
+@OPENJDK@/jdk/src/share/classes/com/sun/jarsigner/package-info.java
@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAccessException.java
@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAccessor.java
@OPENJDK@/jdk/src/share/classes/com/sun/java/browser/dom/DOMAction.java
@@ -9019,7 +9031,6 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/NotificationAccessController.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/security/SubjectDelegator.java
-@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/CacheMap.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLoaderWithRepository.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/ClassLogger.java
@OPENJDK@/jdk/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java
@@ -9507,6 +9518,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AgentInitializationException.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AgentLoadException.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachNotSupportedException.java
+@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachOperationFailedException.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/AttachPermission.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/spi/AttachProvider.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java
@@ -9541,6 +9553,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/IntegerValueImpl.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InternalEventHandler.java
+@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/JDWPException.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/JNITypeParser.java
@OPENJDK@/jdk/src/share/classes/com/sun/tools/jdi/LineInfo.java
@@ -10158,6 +10171,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/CallSite.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java
+@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DelegatingMethodHandle.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/DontInline.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/ForceInline.java
@@ -10168,6 +10182,8 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/Invokers.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaConversionException.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaForm.java
+@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaFormBuffer.java
+@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaFormEditor.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MemberName.java
@OPENJDK@/jdk/src/share/classes/java/lang/invoke/MethodHandle.java
@@ -10356,6 +10372,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/java/net/SocketOption.java
@OPENJDK@/jdk/src/share/classes/java/net/SocketOptions.java
@OPENJDK@/jdk/src/share/classes/java/net/SocketPermission.java
+@OPENJDK@/jdk/src/share/classes/java/net/SocketSecrets.java
@OPENJDK@/jdk/src/share/classes/java/net/SocketTimeoutException.java
@OPENJDK@/jdk/src/share/classes/java/net/SocksConsts.java
@OPENJDK@/jdk/src/share/classes/java/net/SocksSocketImpl.java
@@ -10970,6 +10987,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ExecutorCompletionService.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Executors.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ExecutorService.java
+@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
@OPENJDK@/jdk/src/share/classes/java/util/concurrent/Future.java
@@ -12602,10 +12620,8 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/Entity.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/Parser.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java
-@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/ResourceLoader.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/TagElement.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/parser/TagStack.java
-@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/ResourceLoader.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/TableView.java
@OPENJDK@/jdk/src/share/classes/javax/swing/text/html/TextAreaDocument.java
@@ -12874,6 +12890,11 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/SAXParser.java
@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/XMLStreamException.java
@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/XMLStreamWriter.java
+@OPENJDK@/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java
+@OPENJDK@/jdk/src/share/classes/jdk/net/NetworkPermission.java
+@OPENJDK@/jdk/src/share/classes/jdk/net/package-info.java
+@OPENJDK@/jdk/src/share/classes/jdk/net/SocketFlow.java
+@OPENJDK@/jdk/src/share/classes/jdk/net/Sockets.java
@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/ChannelBinding.java
@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSContext.java
@OPENJDK@/jdk/src/share/classes/org/ietf/jgss/GSSCredential.java
@@ -12986,6 +13007,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodPopupMenu.java
@OPENJDK@/jdk/src/share/classes/sun/awt/im/InputMethodWindow.java
@OPENJDK@/jdk/src/share/classes/sun/awt/im/SimpleInputMethodWindow.java
+@OPENJDK@/jdk/src/share/classes/sun/awt/image/AbstractMultiResolutionImage.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/BufferedImageDevice.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/BufferedImageGraphicsConfig.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ByteArrayImageSource.java
@@ -12993,6 +13015,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ByteComponentRaster.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/BytePackedRaster.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/FileImageSource.java
+@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageCache.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageConsumerQueue.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageDecoder.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageFetchable.java
@@ -13001,6 +13024,9 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/ImageWatched.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/InputStreamImageSource.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/IntegerComponentRaster.java
+@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionCachedImage.java
+@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionImage.java
+@OPENJDK@/jdk/src/share/classes/sun/awt/image/MultiResolutionToolkitImage.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/NativeLibLoader.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/OffScreenImageSource.java
@OPENJDK@/jdk/src/share/classes/sun/awt/image/PixelConverter.java
@@ -13168,6 +13194,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/management/counter/StringCounter.java
@OPENJDK@/jdk/src/share/classes/sun/management/counter/Units.java
@OPENJDK@/jdk/src/share/classes/sun/management/counter/Variability.java
+@OPENJDK@/jdk/src/share/classes/sun/management/ExtendedPlatformComponent.java
@OPENJDK@/jdk/src/share/classes/sun/management/FileSystem.java
@OPENJDK@/jdk/src/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java
@OPENJDK@/jdk/src/share/classes/sun/management/GcInfoBuilder.java
@@ -13239,6 +13266,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/misc/FpUtils.java
@OPENJDK@/jdk/src/share/classes/sun/misc/GC.java
@OPENJDK@/jdk/src/share/classes/sun/misc/HexDumpEncoder.java
+@OPENJDK@/jdk/src/share/classes/sun/misc/InnocuousThread.java
@OPENJDK@/jdk/src/share/classes/sun/misc/InvalidJarIndexException.java
@OPENJDK@/jdk/src/share/classes/sun/misc/IOUtils.java
@OPENJDK@/jdk/src/share/classes/sun/misc/JarFilter.java
@@ -13288,6 +13316,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/misc/Signal.java
@OPENJDK@/jdk/src/share/classes/sun/misc/SignalHandler.java
@OPENJDK@/jdk/src/share/classes/sun/misc/SoftCache.java
+@OPENJDK@/jdk/src/share/classes/sun/misc/ThreadGroupUtils.java
@OPENJDK@/jdk/src/share/classes/sun/misc/Timeable.java
@OPENJDK@/jdk/src/share/classes/sun/misc/Timer.java
@OPENJDK@/jdk/src/share/classes/sun/misc/UCDecoder.java
@@ -13300,6 +13329,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/jdk/src/share/classes/sun/net/ApplicationProxy.java
@OPENJDK@/jdk/src/share/classes/sun/net/ConnectionResetException.java
@OPENJDK@/jdk/src/share/classes/sun/net/dns/ResolverConfiguration.java
+@OPENJDK@/jdk/src/share/classes/sun/net/ExtendedOptionsImpl.java
@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpClient.java
@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpClientProvider.java
@OPENJDK@/jdk/src/share/classes/sun/net/ftp/FtpDirEntry.java
@@ -15315,6 +15345,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/Todo.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java
+@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/comp/TypeEnvs.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/BaseFileObject.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java
@@ -15407,6 +15438,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Filter.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ForwardingDiagnosticFormatter.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java
+@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/IntHashTable.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/JavacMessages.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/LayoutCharacters.java
@@ -15424,6 +15456,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/ServiceLoader.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/SharedNameTable.java
+@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/StringUtils.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javac/util/Warner.java
@OPENJDK@/langtools/src/share/classes/com/sun/tools/javadoc/AbstractTypeImpl.java
@@ -15653,6 +15686,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/DynamicLinker.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
+@OPENJDK@/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/RelinkableCallSite.java
@@ -15686,6 +15720,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
+@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
@@ -15697,6 +15732,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
+@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/Guards.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
@@ -15709,6 +15745,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/AbstractJSObject.java
+@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ClassFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/Formatter.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
@@ -15718,7 +15755,11 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/URLReader.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/AssertsEnabled.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/IntDeque.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/AstSerializer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -15730,24 +15771,33 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Condition.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Emitter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Label.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MapTuple.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ProgramPoints.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/TypeMap.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/ArrayType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/BitwiseType.java
@@ -15761,7 +15811,6 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/NumericType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Assignment.java
@@ -15776,6 +15825,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CallNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/CompileUnitHolder.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Expression.java
@@ -15784,27 +15834,37 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ForNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/GetSplitState.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IfNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessor.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/JumpStatement.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Labels.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LexicalContextStatement.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LocalVariableConversion.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Node.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Optimistic.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/PropertyKey.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SetSplitState.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SplitReturn.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Statement.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/Terminal.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/TryNode.java
@@ -15818,6 +15878,8 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
@@ -15835,6 +15897,7 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
@@ -15872,10 +15935,10 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Constructor.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Function.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Getter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Setter.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/SpecializedConstructor.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/objects/annotations/Where.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -15890,44 +15953,47 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenStream.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ArgumentSetter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/AstDeserializer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/BitVector.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunctions.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Context.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Debug.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ErrorManager.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSErrorType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Logging.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/NumberToString.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/OptimisticBuiltins.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ParserException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Property.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyListener.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/QuotedStringTokenizer.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/RewriteException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Scope.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -15938,30 +16004,41 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Source.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Specialization.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/StoredScript.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Timing.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/URIUtils.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/Version.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/AnyElements.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntElements.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntOrLongElements.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JavaArrayIterator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JavaListIterator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumericElements.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaArrayIterator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJavaListIterator.java
@@ -15972,12 +16049,16 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectIterator.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
-@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundCallable.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -15998,7 +16079,11 @@ sun/security/jgss/wrapper/SunNativeProvider.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
+@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/Option.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java
diff --git a/openjdk/ikvm/internal/Winsock.java b/openjdk/ikvm/internal/Winsock.java
index ce05de03..69a1eb28 100644
--- a/openjdk/ikvm/internal/Winsock.java
+++ b/openjdk/ikvm/internal/Winsock.java
@@ -138,6 +138,7 @@ public final class Winsock
public static final int IPV6_ADD_MEMBERSHIP = SocketOptionName.AddMembership;
public static final int IPV6_DROP_MEMBERSHIP = SocketOptionName.DropMembership;
public static final int IPV6_V6ONLY = 27;
+ public static final int IPV6_TCLASS = 39;
public static final int SIO_UDP_CONNRESET = 0x9800000C;
@@ -147,6 +148,8 @@ public final class Winsock
public static final int FIONREAD = (int)IOControlCode.DataToRead;
public static final int FIONBIO = (int)IOControlCode.NonBlockingIO;
+ public static final int MAX_PACKET_LEN = 0xFFFF;
+
public static int WSAGetLastError()
{
return lastError;
diff --git a/openjdk/java/io/FileInputStream.java b/openjdk/java/io/FileInputStream.java
index 3547947f..36696445 100644
--- a/openjdk/java/io/FileInputStream.java
+++ b/openjdk/java/io/FileInputStream.java
@@ -27,7 +27,6 @@ package java.io;
import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;
-import sun.misc.IoTrace;
/**
@@ -52,7 +51,10 @@ class FileInputStream extends InputStream
/* File Descriptor - handle to the open file */
private final FileDescriptor fd;
- /* The path of the referenced file (null if the stream is created with a file descriptor) */
+ /**
+ * The path of the referenced file
+ * (null if the stream is created with a file descriptor)
+ */
private final String path;
private FileChannel channel = null;
@@ -60,16 +62,6 @@ class FileInputStream extends InputStream
private final Object closeLock = new Object();
private volatile boolean closed = false;
- private static final ThreadLocal<Boolean> runningFinalize =
- new ThreadLocal<>();
-
- private static boolean isRunningFinalize() {
- Boolean val;
- if ((val = runningFinalize.get()) != null)
- return val.booleanValue();
- return false;
- }
-
/**
* Creates a <code>FileInputStream</code> by
* opening a connection to an actual file,
@@ -137,14 +129,12 @@ class FileInputStream extends InputStream
if (name == null) {
throw new NullPointerException();
}
- /*
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
- */
fd = new FileDescriptor();
- fd.incrementAndGetUseCount();
- this.path = name;
+ fd.attach(this);
+ path = name;
open(name);
}
@@ -185,10 +175,9 @@ class FileInputStream extends InputStream
/*
* FileDescriptor is being shared by streams.
- * Ensure that it's GC'ed only when all the streams/channels are done
- * using it.
+ * Register this stream with FileDescriptor tracker.
*/
- fd.incrementAndGetUseCount();
+ fd.attach(this);
}
/**
@@ -208,15 +197,9 @@ class FileInputStream extends InputStream
* file is reached.
* @exception IOException if an I/O error occurs.
*/
- public int read() throws IOException {
- Object traceContext = IoTrace.fileReadBegin(path);
- int b = 0;
- try {
- b = fd.read();
- } finally {
- IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
- }
- return b;
+ public int read() throws IOException
+ {
+ return fd.read();
}
/**
@@ -243,14 +226,7 @@ class FileInputStream extends InputStream
* @exception IOException if an I/O error occurs.
*/
public int read(byte b[]) throws IOException {
- Object traceContext = IoTrace.fileReadBegin(path);
- int bytesRead = 0;
- try {
- bytesRead = readBytes(b, 0, b.length);
- } finally {
- IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
- }
- return bytesRead;
+ return readBytes(b, 0, b.length);
}
/**
@@ -272,14 +248,7 @@ class FileInputStream extends InputStream
* @exception IOException if an I/O error occurs.
*/
public int read(byte b[], int off, int len) throws IOException {
- Object traceContext = IoTrace.fileReadBegin(path);
- int bytesRead = 0;
- try {
- bytesRead = readBytes(b, off, len);
- } finally {
- IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
- }
- return bytesRead;
+ return readBytes(b, off, len);
}
/**
@@ -288,13 +257,15 @@ class FileInputStream extends InputStream
*
* <p>The <code>skip</code> method may, for a variety of
* reasons, end up skipping over some smaller number of bytes,
- * possibly <code>0</code>. If <code>n</code> is negative, an
- * <code>IOException</code> is thrown, even though the <code>skip</code>
- * method of the {@link InputStream} superclass does nothing in this case.
- * The actual number of bytes skipped is returned.
+ * possibly <code>0</code>. If <code>n</code> is negative, the method
+ * will try to skip backwards. In case the backing file does not support
+ * backward skip at its current position, an <code>IOException</code> is
+ * thrown. The actual number of bytes skipped is returned. If it skips
+ * forwards, it returns a positive value. If it skips backwards, it
+ * returns a negative value.
*
- * <p>This method may skip more bytes than are remaining in the backing
- * file. This produces no exception and the number of bytes skipped
+ * <p>This method may skip more bytes than what are remaining in the
+ * backing file. This produces no exception and the number of bytes skipped
* may include some number of bytes that were beyond the EOF of the
* backing file. Attempting to read from the stream after skipping past
* the end will result in -1 indicating the end of the file.
@@ -312,9 +283,10 @@ class FileInputStream extends InputStream
/**
* Returns an estimate of the number of remaining bytes that can be read (or
* skipped over) from this input stream without blocking by the next
- * invocation of a method for this input stream. The next invocation might be
- * the same thread or another thread. A single read or skip of this
- * many bytes will not block, but may read or skip fewer bytes.
+ * invocation of a method for this input stream. Returns 0 when the file
+ * position is beyond EOF. The next invocation might be the same thread
+ * or another thread. A single read or skip of this many bytes will not
+ * block, but may read or skip fewer bytes.
*
* <p> In some cases, a non-blocking read (or skip) may appear to be
* blocked when it is merely slow, for example when reading large
@@ -350,27 +322,14 @@ class FileInputStream extends InputStream
closed = true;
}
if (channel != null) {
- /*
- * Decrement the FD use count associated with the channel
- * The use count is incremented whenever a new channel
- * is obtained from this stream.
- */
- fd.decrementAndGetUseCount();
channel.close();
}
- /*
- * Decrement the FD use count associated with this stream
- */
- int useCount = fd.decrementAndGetUseCount();
-
- /*
- * If FileDescriptor is still in use by another stream, the finalizer
- * will not close it.
- */
- if ((useCount <= 0) || !isRunningFinalize()) {
- close0();
- }
+ fd.closeAll(new Closeable() {
+ public void close() throws IOException {
+ close0();
+ }
+ });
}
/**
@@ -384,7 +343,9 @@ class FileInputStream extends InputStream
* @see java.io.FileDescriptor
*/
public final FileDescriptor getFD() throws IOException {
- if (fd != null) return fd;
+ if (fd != null) {
+ return fd;
+ }
throw new IOException();
}
@@ -393,7 +354,7 @@ class FileInputStream extends InputStream
* object associated with this file input stream.
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
- * </code>position<code>} of the returned channel will be equal to the
+ * position} of the returned channel will be equal to the
* number of bytes read from the file so far. Reading bytes from this
* stream will increment the channel's position. Changing the channel's
* position, either explicitly or by reading, will change this stream's
@@ -408,13 +369,6 @@ class FileInputStream extends InputStream
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, false, this);
-
- /*
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- fd.incrementAndGetUseCount();
}
return channel;
}
@@ -434,18 +388,12 @@ class FileInputStream extends InputStream
*/
protected void finalize() throws IOException {
if ((fd != null) && (fd != FileDescriptor.in)) {
-
- /*
- * Finalizer should not release the FileDescriptor if another
- * stream is still using it. If the user directly invokes
- * close() then the FileDescriptor is also released.
+ /* if fd is shared, the references in FileDescriptor
+ * will ensure that finalizer is only called when
+ * safe to do so. All references using the fd have
+ * become unreachable. We can call close()
*/
- runningFinalize.set(Boolean.TRUE);
- try {
- close();
- } finally {
- runningFinalize.set(Boolean.FALSE);
- }
+ close();
}
}
}
diff --git a/openjdk/java/io/FileOutputStream.java b/openjdk/java/io/FileOutputStream.java
index dae9d4bc..687bf0ca 100644
--- a/openjdk/java/io/FileOutputStream.java
+++ b/openjdk/java/io/FileOutputStream.java
@@ -27,7 +27,6 @@ package java.io;
import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;
-import sun.misc.IoTrace;
/**
@@ -59,31 +58,23 @@ class FileOutputStream extends OutputStream
private final FileDescriptor fd;
/**
- * The path of the referenced file (null if the stream is created with a file descriptor)
- */
- private final String path;
-
- /**
* True if the file is opened for append.
*/
private final boolean append;
/**
- * The associated channel, initalized lazily.
+ * The associated channel, initialized lazily.
*/
private FileChannel channel;
+ /**
+ * The path of the referenced file
+ * (null if the stream is created with a file descriptor)
+ */
+ private final String path;
+
private final Object closeLock = new Object();
private volatile boolean closed = false;
- private static final ThreadLocal<Boolean> runningFinalize =
- new ThreadLocal<>();
-
- private static boolean isRunningFinalize() {
- Boolean val;
- if ((val = runningFinalize.get()) != null)
- return val.booleanValue();
- return false;
- }
/**
* Creates a file output stream to write to the file with the
@@ -211,15 +202,14 @@ class FileOutputStream extends OutputStream
if (name == null) {
throw new NullPointerException();
}
- /*
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
- */
this.fd = new FileDescriptor();
+ fd.attach(this);
this.append = append;
this.path = name;
- fd.incrementAndGetUseCount();
+
open(name, append);
}
@@ -255,15 +245,10 @@ class FileOutputStream extends OutputStream
security.checkWrite(fdObj);
}
this.fd = fdObj;
- this.path = null;
this.append = false;
+ this.path = null;
- /*
- * FileDescriptor is being shared by streams.
- * Ensure that it's GC'ed only when all the streams/channels are done
- * using it.
- */
- fd.incrementAndGetUseCount();
+ fd.attach(this);
}
/**
@@ -299,14 +284,7 @@ class FileOutputStream extends OutputStream
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
- Object traceContext = IoTrace.fileWriteBegin(path);
- int bytesWritten = 0;
- try {
- write(b, append);
- bytesWritten = 1;
- } finally {
- IoTrace.fileWriteEnd(traceContext, bytesWritten);
- }
+ write(b, append);
}
/**
@@ -331,14 +309,7 @@ class FileOutputStream extends OutputStream
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[]) throws IOException {
- Object traceContext = IoTrace.fileWriteBegin(path);
- int bytesWritten = 0;
- try {
- writeBytes(b, 0, b.length, append);
- bytesWritten = b.length;
- } finally {
- IoTrace.fileWriteEnd(traceContext, bytesWritten);
- }
+ writeBytes(b, 0, b.length, append);
}
/**
@@ -351,14 +322,7 @@ class FileOutputStream extends OutputStream
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
- Object traceContext = IoTrace.fileWriteBegin(path);
- int bytesWritten = 0;
- try {
- writeBytes(b, off, len, append);
- bytesWritten = len;
- } finally {
- IoTrace.fileWriteEnd(traceContext, bytesWritten);
- }
+ writeBytes(b, off, len, append);
}
/**
@@ -383,27 +347,14 @@ class FileOutputStream extends OutputStream
}
if (channel != null) {
- /*
- * Decrement FD use count associated with the channel
- * The use count is incremented whenever a new channel
- * is obtained from this stream.
- */
- fd.decrementAndGetUseCount();
channel.close();
}
- /*
- * Decrement FD use count associated with this stream
- */
- int useCount = fd.decrementAndGetUseCount();
-
- /*
- * If FileDescriptor is still in use by another stream, the finalizer
- * will not close it.
- */
- if ((useCount <= 0) || !isRunningFinalize()) {
- close0();
- }
+ fd.closeAll(new Closeable() {
+ public void close() throws IOException {
+ close0();
+ }
+ });
}
/**
@@ -417,16 +368,18 @@ class FileOutputStream extends OutputStream
* @see java.io.FileDescriptor
*/
public final FileDescriptor getFD() throws IOException {
- if (fd != null) return fd;
+ if (fd != null) {
+ return fd;
+ }
throw new IOException();
}
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
- * object associated with this file output stream. </p>
+ * object associated with this file output stream.
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
- * </code>position<code>} of the returned channel will be equal to the
+ * position} of the returned channel will be equal to the
* number of bytes written to the file so far unless this stream is in
* append mode, in which case it will be equal to the size of the file.
* Writing bytes to this stream will increment the channel's position
@@ -442,13 +395,6 @@ class FileOutputStream extends OutputStream
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, false, true, append, this);
-
- /*
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- fd.incrementAndGetUseCount();
}
return channel;
}
@@ -467,18 +413,12 @@ class FileOutputStream extends OutputStream
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
-
- /*
- * Finalizer should not release the FileDescriptor if another
- * stream is still using it. If the user directly invokes
- * close() then the FileDescriptor is also released.
+ /* if fd is shared, the references in FileDescriptor
+ * will ensure that finalizer is only called when
+ * safe to do so. All references using the fd have
+ * become unreachable. We can call close()
*/
- runningFinalize.set(Boolean.TRUE);
- try {
- close();
- } finally {
- runningFinalize.set(Boolean.FALSE);
- }
+ close();
}
}
}
diff --git a/openjdk/java/io/RandomAccessFile.java b/openjdk/java/io/RandomAccessFile.java
index 61fc27a7..9abb1dbe 100644
--- a/openjdk/java/io/RandomAccessFile.java
+++ b/openjdk/java/io/RandomAccessFile.java
@@ -27,7 +27,6 @@ package java.io;
import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;
-import sun.misc.IoTrace;
/**
@@ -42,16 +41,16 @@ import sun.misc.IoTrace;
* the file pointer past the bytes written. Output operations that write
* past the current end of the implied array cause the array to be
* extended. The file pointer can be read by the
- * <code>getFilePointer</code> method and set by the <code>seek</code>
+ * {@code getFilePointer} method and set by the {@code seek}
* method.
* <p>
* It is generally true of all the reading routines in this class that
* if end-of-file is reached before the desired number of bytes has been
- * read, an <code>EOFException</code> (which is a kind of
- * <code>IOException</code>) is thrown. If any byte cannot be read for
- * any reason other than end-of-file, an <code>IOException</code> other
- * than <code>EOFException</code> is thrown. In particular, an
- * <code>IOException</code> may be thrown if the stream has been closed.
+ * read, an {@code EOFException} (which is a kind of
+ * {@code IOException}) is thrown. If any byte cannot be read for
+ * any reason other than end-of-file, an {@code IOException} other
+ * than {@code EOFException} is thrown. In particular, an
+ * {@code IOException} may be thrown if the stream has been closed.
*
* @author unascribed
* @since JDK1.0
@@ -63,7 +62,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
private FileChannel channel = null;
private boolean rw;
- /* The path of the referenced file */
+ /**
+ * The path of the referenced file
+ * (null if the stream is created with a file descriptor)
+ */
private final String path;
private Object closeLock = new Object();
@@ -86,12 +88,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor.
*
* <p>
- * If there is a security manager, its <code>checkRead</code> method
- * is called with the <code>name</code> argument
+ * If there is a security manager, its {@code checkRead} method
+ * is called with the {@code name} argument
* as its argument to see if read access to the file is allowed.
* If the mode allows writing, the security manager's
- * <code>checkWrite</code> method
- * is also called with the <code>name</code> argument
+ * {@code checkWrite} method
+ * is also called with the {@code name} argument
* as its argument to see if write access to the file is allowed.
*
* @param name the system-dependent filename
@@ -107,9 +109,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* that name cannot be created, or if some other error occurs
* while opening or creating the file
* @exception SecurityException if a security manager exists and its
- * <code>checkRead</code> method denies read access to the file
+ * {@code checkRead} method denies read access to the file
* or the mode is "rw" and the security manager's
- * <code>checkWrite</code> method denies write access to the file
+ * {@code checkWrite} method denies write access to the file
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkRead(java.lang.String)
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
@@ -127,12 +129,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* write to, the file specified by the {@link File} argument. A new {@link
* FileDescriptor} object is created to represent this file connection.
*
- * <a name="mode"><p> The <tt>mode</tt> argument specifies the access mode
+ * <p>The <a name="mode"><tt>mode</tt></a> argument specifies the access mode
* in which the file is to be opened. The permitted values and their
* meanings are:
*
- * <blockquote><table summary="Access mode permitted values and meanings">
- * <tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
+ * <table summary="Access mode permitted values and meanings">
+ * <tr><th align="left">Value</th><th align="left">Meaning</th></tr>
* <tr><td valign="top"><tt>"r"</tt></td>
* <td> Open for reading only. Invoking any of the <tt>write</tt>
* methods of the resulting object will cause an {@link
@@ -148,7 +150,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
* require that every update to the file's content be written
* synchronously to the underlying storage device. </td></tr>
- * </table></blockquote>
+ * </table>
*
* The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
* java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
@@ -162,16 +164,16 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* event of a system crash. If the file does not reside on a local device
* then no such guarantee is made.
*
- * <p> The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
+ * <p>The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
* operations performed. Using <tt>"rwd"</tt> only requires updates to the
* file's content to be written to storage; using <tt>"rws"</tt> requires
* updates to both the file's content and its metadata to be written, which
* generally requires at least one more low-level I/O operation.
*
- * <p> If there is a security manager, its <code>checkRead</code> method is
- * called with the pathname of the <code>file</code> argument as its
+ * <p>If there is a security manager, its {@code checkRead} method is
+ * called with the pathname of the {@code file} argument as its
* argument to see if read access to the file is allowed. If the mode
- * allows writing, the security manager's <code>checkWrite</code> method is
+ * allows writing, the security manager's {@code checkWrite} method is
* also called with the path argument to see if write access to the file is
* allowed.
*
@@ -189,9 +191,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* that name cannot be created, or if some other error occurs
* while opening or creating the file
* @exception SecurityException if a security manager exists and its
- * <code>checkRead</code> method denies read access to the file
+ * {@code checkRead} method denies read access to the file
* or the mode is "rw" and the security manager's
- * <code>checkWrite</code> method denies write access to the file
+ * {@code checkWrite} method denies write access to the file
* @see java.lang.SecurityManager#checkRead(java.lang.String)
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
* @see java.nio.channels.FileChannel#force(boolean)
@@ -232,27 +234,27 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
if (name == null) {
throw new NullPointerException();
}
- /*
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
- */
fd = new FileDescriptor();
- fd.incrementAndGetUseCount();
- this.path = name;
+ fd.attach(this);
+ path = name;
open(name, imode);
}
/**
* Returns the opaque file descriptor object associated with this
- * stream. </p>
+ * stream.
*
* @return the file descriptor object associated with this stream.
* @exception IOException if an I/O error occurs.
* @see java.io.FileDescriptor
*/
public final FileDescriptor getFD() throws IOException {
- if (fd != null) return fd;
+ if (fd != null) {
+ return fd;
+ }
throw new IOException();
}
@@ -261,7 +263,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* object associated with this file.
*
* <p> The {@link java.nio.channels.FileChannel#position()
- * </code>position<code>} of the returned channel will always be equal to
+ * position} of the returned channel will always be equal to
* this object's file-pointer offset as returned by the {@link
* #getFilePointer getFilePointer} method. Changing this object's
* file-pointer offset, whether explicitly or by reading or writing bytes,
@@ -278,17 +280,6 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, path, true, rw, this);
-
- /*
- * FileDescriptor could be shared by FileInputStream or
- * FileOutputStream.
- * Ensure that FD is GC'ed only when all the streams/channels
- * are done using it.
- * Increment fd's use count. Invoking the channel's close()
- * method will result in decrementing the use count set for
- * the channel.
- */
- fd.incrementAndGetUseCount();
}
return channel;
}
@@ -296,9 +287,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Opens a file and returns the file descriptor. The file is
- * opened in read-write mode if the O_RDWR bit in <code>mode</code>
+ * opened in read-write mode if the O_RDWR bit in {@code mode}
* is true, else the file is opened as read-only.
- * If the <code>name</code> refers to a directory, an IOException
+ * If the {@code name} refers to a directory, an IOException
* is thrown.
*
* @param name the name of the file
@@ -322,28 +313,21 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Reads a byte of data from this file. The byte is returned as an
- * integer in the range 0 to 255 (<code>0x00-0x0ff</code>). This
+ * integer in the range 0 to 255 ({@code 0x00-0x0ff}). This
* method blocks if no input is yet available.
* <p>
- * Although <code>RandomAccessFile</code> is not a subclass of
- * <code>InputStream</code>, this method behaves in exactly the same
+ * Although {@code RandomAccessFile} is not a subclass of
+ * {@code InputStream}, this method behaves in exactly the same
* way as the {@link InputStream#read()} method of
- * <code>InputStream</code>.
+ * {@code InputStream}.
*
- * @return the next byte of data, or <code>-1</code> if the end of the
+ * @return the next byte of data, or {@code -1} if the end of the
* file has been reached.
* @exception IOException if an I/O error occurs. Not thrown if
* end-of-file has been reached.
*/
public int read() throws IOException {
- Object traceContext = IoTrace.fileReadBegin(path);
- int b = 0;
- try {
- b = fd.read();
- } finally {
- IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
- }
- return b;
+ return fd.read();
}
/**
@@ -355,70 +339,63 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
*/
private int readBytes(byte b[], int off, int len) throws IOException
{
- Object traceContext = IoTrace.fileReadBegin(path);
- int bytesRead = 0;
- try {
- bytesRead = fd.readBytes(b, off, len);
- } finally {
- IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
- }
- return bytesRead;
+ return fd.readBytes(b, off, len);
}
/**
- * Reads up to <code>len</code> bytes of data from this file into an
+ * Reads up to {@code len} bytes of data from this file into an
* array of bytes. This method blocks until at least one byte of input
* is available.
* <p>
- * Although <code>RandomAccessFile</code> is not a subclass of
- * <code>InputStream</code>, this method behaves in exactly the
+ * Although {@code RandomAccessFile} is not a subclass of
+ * {@code InputStream}, this method behaves in exactly the
* same way as the {@link InputStream#read(byte[], int, int)} method of
- * <code>InputStream</code>.
+ * {@code InputStream}.
*
* @param b the buffer into which the data is read.
- * @param off the start offset in array <code>b</code>
+ * @param off the start offset in array {@code b}
* at which the data is written.
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
- * <code>-1</code> if there is no more data because the end of
+ * {@code -1} if there is no more data because the end of
* the file has been reached.
* @exception IOException If the first byte cannot be read for any reason
* other than end of file, or if the random access file has been closed, or if
* some other I/O error occurs.
- * @exception NullPointerException If <code>b</code> is <code>null</code>.
- * @exception IndexOutOfBoundsException If <code>off</code> is negative,
- * <code>len</code> is negative, or <code>len</code> is greater than
- * <code>b.length - off</code>
+ * @exception NullPointerException If {@code b} is {@code null}.
+ * @exception IndexOutOfBoundsException If {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code b.length - off}
*/
public int read(byte b[], int off, int len) throws IOException {
return readBytes(b, off, len);
}
/**
- * Reads up to <code>b.length</code> bytes of data from this file
+ * Reads up to {@code b.length} bytes of data from this file
* into an array of bytes. This method blocks until at least one byte
* of input is available.
* <p>
- * Although <code>RandomAccessFile</code> is not a subclass of
- * <code>InputStream</code>, this method behaves in exactly the
+ * Although {@code RandomAccessFile} is not a subclass of
+ * {@code InputStream}, this method behaves in exactly the
* same way as the {@link InputStream#read(byte[])} method of
- * <code>InputStream</code>.
+ * {@code InputStream}.
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
- * <code>-1</code> if there is no more data because the end of
+ * {@code -1} if there is no more data because the end of
* this file has been reached.
* @exception IOException If the first byte cannot be read for any reason
* other than end of file, or if the random access file has been closed, or if
* some other I/O error occurs.
- * @exception NullPointerException If <code>b</code> is <code>null</code>.
+ * @exception NullPointerException If {@code b} is {@code null}.
*/
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
/**
- * Reads <code>b.length</code> bytes from this file into the byte
+ * Reads {@code b.length} bytes from this file into the byte
* array, starting at the current file pointer. This method reads
* repeatedly from the file until the requested number of bytes are
* read. This method blocks until the requested number of bytes are
@@ -434,7 +411,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Reads exactly <code>len</code> bytes from this file into the byte
+ * Reads exactly {@code len} bytes from this file into the byte
* array, starting at the current file pointer. This method reads
* repeatedly from the file until the requested number of bytes are
* read. This method blocks until the requested number of bytes are
@@ -458,15 +435,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Attempts to skip over <code>n</code> bytes of input discarding the
+ * Attempts to skip over {@code n} bytes of input discarding the
* skipped bytes.
* <p>
*
* This method may skip over some smaller number of bytes, possibly zero.
* This may result from any of a number of conditions; reaching end of
- * file before <code>n</code> bytes have been skipped is only one
- * possibility. This method never throws an <code>EOFException</code>.
- * The actual number of bytes skipped is returned. If <code>n</code>
+ * file before {@code n} bytes have been skipped is only one
+ * possibility. This method never throws an {@code EOFException}.
+ * The actual number of bytes skipped is returned. If {@code n}
* is negative, no bytes are skipped.
*
* @param n the number of bytes to be skipped.
@@ -499,18 +476,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Writes the specified byte to this file. The write starts at
* the current file pointer.
*
- * @param b the <code>byte</code> to be written.
+ * @param b the {@code byte} to be written.
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
- Object traceContext = IoTrace.fileWriteBegin(path);
- int bytesWritten = 0;
- try {
- fd.write(b);
- bytesWritten = 1;
- } finally {
- IoTrace.fileWriteEnd(traceContext, bytesWritten);
- }
+ fd.write(b);
}
/**
@@ -522,18 +492,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @exception IOException If an I/O error has occurred.
*/
private void writeBytes(byte b[], int off, int len) throws IOException {
- Object traceContext = IoTrace.fileWriteBegin(path);
- int bytesWritten = 0;
- try {
- fd.writeBytes(b, off, len);
- bytesWritten = len;
- } finally {
- IoTrace.fileWriteEnd(traceContext, bytesWritten);
- }
+ fd.writeBytes(b, off, len);
}
/**
- * Writes <code>b.length</code> bytes from the specified byte array
+ * Writes {@code b.length} bytes from the specified byte array
* to this file, starting at the current file pointer.
*
* @param b the data.
@@ -544,8 +507,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes <code>len</code> bytes from the specified byte array
- * starting at offset <code>off</code> to this file.
+ * Writes {@code len} bytes from the specified byte array
+ * starting at offset {@code off} to this file.
*
* @param b the data.
* @param off the start offset in the data.
@@ -581,12 +544,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @param pos the offset position, measured in bytes from the
* beginning of the file, at which to set the file
* pointer.
- * @exception IOException if <code>pos</code> is less than
- * <code>0</code> or if an I/O error occurs.
+ * @exception IOException if {@code pos} is less than
+ * {@code 0} or if an I/O error occurs.
*/
- public void seek(long pos) throws IOException
- {
- fd.seek(pos);
+ public void seek(long pos) throws IOException {
+ if (pos < 0) {
+ throw new IOException("Negative seek offset");
+ } else {
+ fd.seek(pos);
+ }
}
/**
@@ -604,14 +570,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Sets the length of this file.
*
* <p> If the present length of the file as returned by the
- * <code>length</code> method is greater than the <code>newLength</code>
+ * {@code length} method is greater than the {@code newLength}
* argument then the file will be truncated. In this case, if the file
- * offset as returned by the <code>getFilePointer</code> method is greater
- * than <code>newLength</code> then after this method returns the offset
- * will be equal to <code>newLength</code>.
+ * offset as returned by the {@code getFilePointer} method is greater
+ * than {@code newLength} then after this method returns the offset
+ * will be equal to {@code newLength}.
*
* <p> If the present length of the file as returned by the
- * <code>length</code> method is smaller than the <code>newLength</code>
+ * {@code length} method is smaller than the {@code newLength}
* argument then the file will be extended. In this case, the contents of
* the extended portion of the file are not defined.
*
@@ -646,21 +612,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
closed = true;
}
if (channel != null) {
- /*
- * Decrement FD use count associated with the channel. The FD use
- * count is incremented whenever a new channel is obtained from
- * this stream.
- */
- fd.decrementAndGetUseCount();
channel.close();
}
- /*
- * Decrement FD use count associated with this stream.
- * The count got incremented by FileDescriptor during its construction.
- */
- fd.decrementAndGetUseCount();
- close0();
+ fd.closeAll(new Closeable() {
+ public void close() throws IOException {
+ close0();
+ }
+ });
}
//
@@ -669,14 +628,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
//
/**
- * Reads a <code>boolean</code> from this file. This method reads a
+ * Reads a {@code boolean} from this file. This method reads a
* single byte from the file, starting at the current file pointer.
- * A value of <code>0</code> represents
- * <code>false</code>. Any other value represents <code>true</code>.
+ * A value of {@code 0} represents
+ * {@code false}. Any other value represents {@code true}.
* This method blocks until the byte is read, the end of the stream
* is detected, or an exception is thrown.
*
- * @return the <code>boolean</code> value read.
+ * @return the {@code boolean} value read.
* @exception EOFException if this file has reached the end.
* @exception IOException if an I/O error occurs.
*/
@@ -690,7 +649,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Reads a signed eight-bit value from this file. This method reads a
* byte from the file, starting from the current file pointer.
- * If the byte read is <code>b</code>, where
+ * If the byte read is {@code b}, where
* <code>0&nbsp;&lt;=&nbsp;b&nbsp;&lt;=&nbsp;255</code>,
* then the result is:
* <blockquote><pre>
@@ -701,7 +660,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* is detected, or an exception is thrown.
*
* @return the next byte of this file as a signed eight-bit
- * <code>byte</code>.
+ * {@code byte}.
* @exception EOFException if this file has reached the end.
* @exception IOException if an I/O error occurs.
*/
@@ -736,8 +695,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Reads a signed 16-bit number from this file. The method reads two
* bytes from this file, starting at the current file pointer.
* If the two bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where each of the two values is
- * between <code>0</code> and <code>255</code>, inclusive, then the
+ * {@code b1} and {@code b2}, where each of the two values is
+ * between {@code 0} and {@code 255}, inclusive, then the
* result is equal to:
* <blockquote><pre>
* (short)((b1 &lt;&lt; 8) | b2)
@@ -764,7 +723,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Reads an unsigned 16-bit number from this file. This method reads
* two bytes from the file, starting at the current file pointer.
* If the bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where
+ * {@code b1} and {@code b2}, where
* <code>0&nbsp;&lt;=&nbsp;b1, b2&nbsp;&lt;=&nbsp;255</code>,
* then the result is equal to:
* <blockquote><pre>
@@ -792,7 +751,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Reads a character from this file. This method reads two
* bytes from the file, starting at the current file pointer.
* If the bytes read, in order, are
- * <code>b1</code> and <code>b2</code>, where
+ * {@code b1} and {@code b2}, where
* <code>0&nbsp;&lt;=&nbsp;b1,&nbsp;b2&nbsp;&lt;=&nbsp;255</code>,
* then the result is equal to:
* <blockquote><pre>
@@ -803,7 +762,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* stream is detected, or an exception is thrown.
*
* @return the next two bytes of this file, interpreted as a
- * <code>char</code>.
+ * {@code char}.
* @exception EOFException if this file reaches the end before reading
* two bytes.
* @exception IOException if an I/O error occurs.
@@ -819,8 +778,8 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Reads a signed 32-bit integer from this file. This method reads 4
* bytes from the file, starting at the current file pointer.
- * If the bytes read, in order, are <code>b1</code>,
- * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
+ * If the bytes read, in order, are {@code b1},
+ * {@code b2}, {@code b3}, and {@code b4}, where
* <code>0&nbsp;&lt;=&nbsp;b1, b2, b3, b4&nbsp;&lt;=&nbsp;255</code>,
* then the result is equal to:
* <blockquote><pre>
@@ -831,7 +790,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* stream is detected, or an exception is thrown.
*
* @return the next four bytes of this file, interpreted as an
- * <code>int</code>.
+ * {@code int}.
* @exception EOFException if this file reaches the end before reading
* four bytes.
* @exception IOException if an I/O error occurs.
@@ -850,15 +809,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* Reads a signed 64-bit integer from this file. This method reads eight
* bytes from the file, starting at the current file pointer.
* If the bytes read, in order, are
- * <code>b1</code>, <code>b2</code>, <code>b3</code>,
- * <code>b4</code>, <code>b5</code>, <code>b6</code>,
- * <code>b7</code>, and <code>b8,</code> where:
+ * {@code b1}, {@code b2}, {@code b3},
+ * {@code b4}, {@code b5}, {@code b6},
+ * {@code b7}, and {@code b8,} where:
* <blockquote><pre>
* 0 &lt;= b1, b2, b3, b4, b5, b6, b7, b8 &lt;=255,
* </pre></blockquote>
* <p>
* then the result is equal to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* ((long)b1 &lt;&lt; 56) + ((long)b2 &lt;&lt; 48)
* + ((long)b3 &lt;&lt; 40) + ((long)b4 &lt;&lt; 32)
* + ((long)b5 &lt;&lt; 24) + ((long)b6 &lt;&lt; 16)
@@ -869,7 +828,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* stream is detected, or an exception is thrown.
*
* @return the next eight bytes of this file, interpreted as a
- * <code>long</code>.
+ * {@code long}.
* @exception EOFException if this file reaches the end before reading
* eight bytes.
* @exception IOException if an I/O error occurs.
@@ -879,18 +838,18 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Reads a <code>float</code> from this file. This method reads an
- * <code>int</code> value, starting at the current file pointer,
- * as if by the <code>readInt</code> method
- * and then converts that <code>int</code> to a <code>float</code>
- * using the <code>intBitsToFloat</code> method in class
- * <code>Float</code>.
+ * Reads a {@code float} from this file. This method reads an
+ * {@code int} value, starting at the current file pointer,
+ * as if by the {@code readInt} method
+ * and then converts that {@code int} to a {@code float}
+ * using the {@code intBitsToFloat} method in class
+ * {@code Float}.
* <p>
* This method blocks until the four bytes are read, the end of the
* stream is detected, or an exception is thrown.
*
* @return the next four bytes of this file, interpreted as a
- * <code>float</code>.
+ * {@code float}.
* @exception EOFException if this file reaches the end before reading
* four bytes.
* @exception IOException if an I/O error occurs.
@@ -902,18 +861,18 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Reads a <code>double</code> from this file. This method reads a
- * <code>long</code> value, starting at the current file pointer,
- * as if by the <code>readLong</code> method
- * and then converts that <code>long</code> to a <code>double</code>
- * using the <code>longBitsToDouble</code> method in
- * class <code>Double</code>.
+ * Reads a {@code double} from this file. This method reads a
+ * {@code long} value, starting at the current file pointer,
+ * as if by the {@code readLong} method
+ * and then converts that {@code long} to a {@code double}
+ * using the {@code longBitsToDouble} method in
+ * class {@code Double}.
* <p>
* This method blocks until the eight bytes are read, the end of the
* stream is detected, or an exception is thrown.
*
* @return the next eight bytes of this file, interpreted as a
- * <code>double</code>.
+ * {@code double}.
* @exception EOFException if this file reaches the end before reading
* eight bytes.
* @exception IOException if an I/O error occurs.
@@ -934,7 +893,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* therefore, support the full Unicode character set.
*
* <p> A line of text is terminated by a carriage-return character
- * (<code>'&#92;r'</code>), a newline character (<code>'&#92;n'</code>), a
+ * ({@code '\u005Cr'}), a newline character ({@code '\u005Cn'}), a
* carriage-return character immediately followed by a newline character,
* or the end of the file. Line-terminating characters are discarded and
* are not included as part of the string returned.
@@ -986,7 +945,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* <p>
* The first two bytes are read, starting from the current file
* pointer, as if by
- * <code>readUnsignedShort</code>. This value gives the number of
+ * {@code readUnsignedShort}. This value gives the number of
* following bytes that are in the encoded string, not
* the length of the resulting string. The following bytes are then
* interpreted as bytes encoding characters in the modified UTF-8 format
@@ -1008,13 +967,13 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes a <code>boolean</code> to the file as a one-byte value. The
- * value <code>true</code> is written out as the value
- * <code>(byte)1</code>; the value <code>false</code> is written out
- * as the value <code>(byte)0</code>. The write starts at
+ * Writes a {@code boolean} to the file as a one-byte value. The
+ * value {@code true} is written out as the value
+ * {@code (byte)1}; the value {@code false} is written out
+ * as the value {@code (byte)0}. The write starts at
* the current position of the file pointer.
*
- * @param v a <code>boolean</code> value to be written.
+ * @param v a {@code boolean} value to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeBoolean(boolean v) throws IOException {
@@ -1023,10 +982,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes a <code>byte</code> to the file as a one-byte value. The
+ * Writes a {@code byte} to the file as a one-byte value. The
* write starts at the current position of the file pointer.
*
- * @param v a <code>byte</code> value to be written.
+ * @param v a {@code byte} value to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeByte(int v) throws IOException {
@@ -1035,10 +994,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes a <code>short</code> to the file as two bytes, high byte first.
+ * Writes a {@code short} to the file as two bytes, high byte first.
* The write starts at the current position of the file pointer.
*
- * @param v a <code>short</code> to be written.
+ * @param v a {@code short} to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeShort(int v) throws IOException {
@@ -1048,11 +1007,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes a <code>char</code> to the file as a two-byte value, high
+ * Writes a {@code char} to the file as a two-byte value, high
* byte first. The write starts at the current position of the
* file pointer.
*
- * @param v a <code>char</code> value to be written.
+ * @param v a {@code char} value to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeChar(int v) throws IOException {
@@ -1062,10 +1021,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes an <code>int</code> to the file as four bytes, high byte first.
+ * Writes an {@code int} to the file as four bytes, high byte first.
* The write starts at the current position of the file pointer.
*
- * @param v an <code>int</code> to be written.
+ * @param v an {@code int} to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeInt(int v) throws IOException {
@@ -1077,10 +1036,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Writes a <code>long</code> to the file as eight bytes, high byte first.
+ * Writes a {@code long} to the file as eight bytes, high byte first.
* The write starts at the current position of the file pointer.
*
- * @param v a <code>long</code> to be written.
+ * @param v a {@code long} to be written.
* @exception IOException if an I/O error occurs.
*/
public final void writeLong(long v) throws IOException {
@@ -1096,13 +1055,13 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Converts the float argument to an <code>int</code> using the
- * <code>floatToIntBits</code> method in class <code>Float</code>,
- * and then writes that <code>int</code> value to the file as a
+ * Converts the float argument to an {@code int} using the
+ * {@code floatToIntBits} method in class {@code Float},
+ * and then writes that {@code int} value to the file as a
* four-byte quantity, high byte first. The write starts at the
* current position of the file pointer.
*
- * @param v a <code>float</code> value to be written.
+ * @param v a {@code float} value to be written.
* @exception IOException if an I/O error occurs.
* @see java.lang.Float#floatToIntBits(float)
*/
@@ -1111,13 +1070,13 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
}
/**
- * Converts the double argument to a <code>long</code> using the
- * <code>doubleToLongBits</code> method in class <code>Double</code>,
- * and then writes that <code>long</code> value to the file as an
+ * Converts the double argument to a {@code long} using the
+ * {@code doubleToLongBits} method in class {@code Double},
+ * and then writes that {@code long} value to the file as an
* eight-byte quantity, high byte first. The write starts at the current
* position of the file pointer.
*
- * @param v a <code>double</code> value to be written.
+ * @param v a {@code double} value to be written.
* @exception IOException if an I/O error occurs.
* @see java.lang.Double#doubleToLongBits(double)
*/
@@ -1134,6 +1093,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @param s a string of bytes to be written.
* @exception IOException if an I/O error occurs.
*/
+ @SuppressWarnings("deprecation")
public final void writeBytes(String s) throws IOException {
int len = s.length();
byte[] b = new byte[len];
@@ -1144,10 +1104,10 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Writes a string to the file as a sequence of characters. Each
* character is written to the data output stream as if by the
- * <code>writeChar</code> method. The write starts at the current
+ * {@code writeChar} method. The write starts at the current
* position of the file pointer.
*
- * @param s a <code>String</code> value to be written.
+ * @param s a {@code String} value to be written.
* @exception IOException if an I/O error occurs.
* @see java.io.RandomAccessFile#writeChar(int)
*/
@@ -1171,7 +1131,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* <p>
* First, two bytes are written to the file, starting at the
* current file pointer, as if by the
- * <code>writeShort</code> method giving the number of bytes to
+ * {@code writeShort} method giving the number of bytes to
* follow. This value is the number of bytes actually written out,
* not the length of the string. Following the length, each character
* of the string is output, in sequence, using the modified UTF-8 encoding
diff --git a/openjdk/java/lang/Class.java b/openjdk/java/lang/Class.java
index 07fd7bd5..1d4d391f 100644
--- a/openjdk/java/lang/Class.java
+++ b/openjdk/java/lang/Class.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -198,13 +198,14 @@ public final class Class<T> implements java.io.Serializable,
final cli.System.Type type;
/*
- * Constructor. Only the Java Virtual Machine creates Class
- * objects.
- */
- private Class()
- {
- // this constructor is not used, but exists for compatibility
- // (otherwise it would look as if this class doesn't have a constructor, which might break some code)
+ * Private constructor. Only the Java Virtual Machine creates Class objects.
+ * This constructor is not used and prevents the default constructor being
+ * generated.
+ */
+ private Class(ClassLoader loader) {
+ // Initialize final field for classLoader. The initialization value of non-null
+ // prevents future JIT optimizations from assuming this final field is null.
+ //classLoader = loader;
throw new InternalError();
}
@@ -356,8 +357,8 @@ public final class Class<T> implements java.io.Serializable,
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
- return forName0(className, true,
- ClassLoader.getClassLoader(Reflection.getCallerClass()));
+ Class<?> caller = Reflection.getCallerClass();
+ return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
@@ -427,22 +428,27 @@ public final class Class<T> implements java.io.Serializable,
ClassLoader loader)
throws ClassNotFoundException
{
- if (sun.misc.VM.isSystemDomainLoader(loader)) {
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
+ Class<?> caller = null;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ // Reflective call to get caller class is only needed if a security manager
+ // is present. Avoid the overhead of making this call otherwise.
+ caller = Reflection.getCallerClass();
+ if (sun.misc.VM.isSystemDomainLoader(loader)) {
+ ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
- return forName0(name, initialize, loader);
+ return forName0(name, initialize, loader, caller);
}
- /** Called after security checks have been made. */
+ /** Called after security check for system loader access checks have been made. */
private static native Class<?> forName0(String name, boolean initialize,
- ClassLoader loader)
+ ClassLoader loader,
+ Class<?> caller)
throws ClassNotFoundException;
/**
@@ -2769,12 +2775,26 @@ public final class Class<T> implements java.io.Serializable,
}
static class MethodArray {
+ // Don't add or remove methods except by add() or remove() calls.
private Method[] methods;
private int length;
+ private int defaults;
MethodArray() {
- methods = new Method[20];
+ this(20);
+ }
+
+ MethodArray(int initialSize) {
+ if (initialSize < 2)
+ throw new IllegalArgumentException("Size should be 2 or more");
+
+ methods = new Method[initialSize];
length = 0;
+ defaults = 0;
+ }
+
+ boolean hasDefaults() {
+ return defaults != 0;
}
void add(Method m) {
@@ -2782,6 +2802,9 @@ public final class Class<T> implements java.io.Serializable,
methods = Arrays.copyOf(methods, 2 * methods.length);
}
methods[length++] = m;
+
+ if (m != null && m.isDefault())
+ defaults++;
}
void addAll(Method[] ma) {
@@ -2815,7 +2838,10 @@ public final class Class<T> implements java.io.Serializable,
}
}
- void addAllNonStatic(Method[] methods) {
+ /* Add Methods declared in an interface to this MethodArray.
+ * Static methods declared in interfaces are not inherited.
+ */
+ void addInterfaceMethods(Method[] methods) {
for (Method candidate : methods) {
if (!Modifier.isStatic(candidate.getModifiers())) {
add(candidate);
@@ -2831,19 +2857,35 @@ public final class Class<T> implements java.io.Serializable,
return methods[i];
}
- void removeByNameAndSignature(Method toRemove) {
+ Method getFirst() {
+ for (Method m : methods)
+ if (m != null)
+ return m;
+ return null;
+ }
+
+ void removeByNameAndDescriptor(Method toRemove) {
for (int i = 0; i < length; i++) {
Method m = methods[i];
- if (m != null &&
- m.getReturnType() == toRemove.getReturnType() &&
- m.getName() == toRemove.getName() &&
- arrayContentsEq(m.getParameterTypes(),
- toRemove.getParameterTypes())) {
- methods[i] = null;
+ if (m != null && matchesNameAndDescriptor(m, toRemove)) {
+ remove(i);
}
}
}
+ private void remove(int i) {
+ if (methods[i] != null && methods[i].isDefault())
+ defaults--;
+ methods[i] = null;
+ }
+
+ private boolean matchesNameAndDescriptor(Method m1, Method m2) {
+ return m1.getReturnType() == m2.getReturnType() &&
+ m1.getName() == m2.getName() && // name is guaranteed to be interned
+ arrayContentsEq(m1.getParameterTypes(),
+ m2.getParameterTypes());
+ }
+
void compactAndTrim() {
int newPos = 0;
// Get rid of null slots
@@ -2861,9 +2903,48 @@ public final class Class<T> implements java.io.Serializable,
}
}
+ /* Removes all Methods from this MethodArray that have a more specific
+ * default Method in this MethodArray.
+ *
+ * Users of MethodArray are responsible for pruning Methods that have
+ * a more specific <em>concrete</em> Method.
+ */
+ void removeLessSpecifics() {
+ if (!hasDefaults())
+ return;
+
+ for (int i = 0; i < length; i++) {
+ Method m = get(i);
+ if (m == null || !m.isDefault())
+ continue;
+
+ for (int j = 0; j < length; j++) {
+ if (i == j)
+ continue;
+
+ Method candidate = get(j);
+ if (candidate == null)
+ continue;
+
+ if (!matchesNameAndDescriptor(m, candidate))
+ continue;
+
+ if (hasMoreSpecificClass(m, candidate))
+ remove(j);
+ }
+ }
+ }
+
Method[] getArray() {
return methods;
}
+
+ // Returns true if m1 is more specific than m2
+ static boolean hasMoreSpecificClass(Method m1, Method m2) {
+ Class<?> m1Class = m1.getDeclaringClass();
+ Class<?> m2Class = m2.getDeclaringClass();
+ return m1Class != m2Class && m2Class.isAssignableFrom(m1Class);
+ }
}
@@ -2891,9 +2972,8 @@ public final class Class<T> implements java.io.Serializable,
// out concrete implementations inherited from superclasses at
// the end.
MethodArray inheritedMethods = new MethodArray();
- Class<?>[] interfaces = getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- inheritedMethods.addAllNonStatic(interfaces[i].privateGetPublicMethods());
+ for (Class<?> i : getInterfaces()) {
+ inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods());
}
if (!isInterface()) {
Class<?> c = getSuperclass();
@@ -2904,8 +2984,10 @@ public final class Class<T> implements java.io.Serializable,
// interface methods
for (int i = 0; i < supers.length(); i++) {
Method m = supers.get(i);
- if (m != null && !Modifier.isAbstract(m.getModifiers())) {
- inheritedMethods.removeByNameAndSignature(m);
+ if (m != null &&
+ !Modifier.isAbstract(m.getModifiers()) &&
+ !m.isDefault()) {
+ inheritedMethods.removeByNameAndDescriptor(m);
}
}
// Insert superclass's inherited methods before
@@ -2918,9 +3000,10 @@ public final class Class<T> implements java.io.Serializable,
// Filter out all local methods from inherited ones
for (int i = 0; i < methods.length(); i++) {
Method m = methods.get(i);
- inheritedMethods.removeByNameAndSignature(m);
+ inheritedMethods.removeByNameAndDescriptor(m);
}
methods.addAllIfNotPresent(inheritedMethods);
+ methods.removeLessSpecifics();
methods.compactAndTrim();
res = methods.getArray();
if (rd != null) {
@@ -2995,8 +3078,21 @@ public final class Class<T> implements java.io.Serializable,
return (res == null ? res : getReflectionFactory().copyMethod(res));
}
-
private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
+ MethodArray interfaceCandidates = new MethodArray(2);
+ Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
+ if (res != null)
+ return res;
+
+ // Not found on class or superclass directly
+ interfaceCandidates.removeLessSpecifics();
+ return interfaceCandidates.getFirst(); // may be null
+ }
+
+ private Method privateGetMethodRecursive(String name,
+ Class<?>[] parameterTypes,
+ boolean includeStaticMethods,
+ MethodArray allInterfaceCandidates) {
// Note: the intent is that the search algorithm this routine
// uses be equivalent to the ordering imposed by
// privateGetPublicMethods(). It fetches only the declared
@@ -3004,6 +3100,14 @@ public final class Class<T> implements java.io.Serializable,
// number of Method objects which have to be created for the
// common case where the method being requested is declared in
// the class which is being queried.
+ //
+ // Due to default methods, unless a method is found on a superclass,
+ // methods declared in any superinterface needs to be considered.
+ // Collect all candidates declared in superinterfaces in {@code
+ // allInterfaceCandidates} and select the most specific if no match on
+ // a superclass is found.
+
+ // Must _not_ return root methods
Method res;
// Search declared public methods
if ((res = searchMethods(privateGetDeclaredMethods(true),
@@ -3025,7 +3129,7 @@ public final class Class<T> implements java.io.Serializable,
Class<?>[] interfaces = getInterfaces();
for (Class<?> c : interfaces)
if ((res = c.getMethod0(name, parameterTypes, false)) != null)
- return res;
+ allInterfaceCandidates.add(res);
// Not found
return null;
}
diff --git a/openjdk/java/lang/ClassLoader.java b/openjdk/java/lang/ClassLoader.java
index 57c1ee3e..280a6889 100644
--- a/openjdk/java/lang/ClassLoader.java
+++ b/openjdk/java/lang/ClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -51,13 +51,13 @@ import java.util.Vector;
import java.util.Hashtable;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
-import sun.misc.ClassFileTransformer;
import sun.misc.CompoundEnumeration;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
+import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
/**
@@ -158,7 +158,7 @@ import sun.security.util.SecurityConstants;
* }
* </pre></blockquote>
*
- * <h4> <a name="name">Binary names</a> </h4>
+ * <h3> <a name="name">Binary names</a> </h3>
*
* <p> Any class name provided as a {@link String} parameter to methods in
* <tt>ClassLoader</tt> must be a binary name as defined by
@@ -245,7 +245,7 @@ public abstract class ClassLoader {
// Shared among all packages with unsigned classes
private static final Certificate[] nocerts = new Certificate[0];
- // The classes loaded by this class loader. The only purpose of this table
+ // The classes loaded by this class loader. The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private final Vector<Class<?>> classes = new Vector<>();
@@ -259,7 +259,7 @@ public abstract class ClassLoader {
private final Set<ProtectionDomain> domains;
// Invoked by the VM to record every loaded class with this loader.
- void addClass(Class c) {
+ void addClass(Class<?> c) {
classes.addElement(c);
}
@@ -361,7 +361,7 @@ public abstract class ClassLoader {
* #loadClass(String, boolean)} method. It is invoked by the Java virtual
* machine to resolve class references. Invoking this method is equivalent
* to invoking {@link #loadClass(String, boolean) <tt>loadClass(name,
- * false)</tt>}. </p>
+ * false)</tt>}.
*
* @param name
* The <a href="#name">binary name</a> of the class
@@ -380,7 +380,7 @@ public abstract class ClassLoader {
* default implementation of this method searches for classes in the
* following order:
*
- * <p><ol>
+ * <ol>
*
* <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
* has already been loaded. </p></li>
@@ -421,7 +421,7 @@ public abstract class ClassLoader {
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
- Class c = findLoadedClass(name);
+ Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
@@ -453,7 +453,7 @@ public abstract class ClassLoader {
* behaves as follows. If this ClassLoader object is registered as
* parallel capable, the method returns a dedicated object associated
* with the specified class name. Otherwise, the method returns this
- * ClassLoader object. </p>
+ * ClassLoader object.
*
* @param className
* The name of the to-be-loaded class
@@ -480,7 +480,7 @@ public abstract class ClassLoader {
}
// This method is invoked by the virtual machine to load a class.
- final Class loadClassInternal(String name)
+ final Class<?> loadClassInternal(String name)
throws ClassNotFoundException
{
// For backward compatibility, explicitly lock on 'this' when
@@ -495,9 +495,16 @@ public abstract class ClassLoader {
}
// Invoked by the VM after loading class with this loader.
- final void checkPackageAccess(Class cls, ProtectionDomain pd) {
+ final void checkPackageAccess(Class<?> cls, ProtectionDomain pd) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
+ if (ReflectUtil.isNonPublicProxyClass(cls)) {
+ for (Class<?> intf: cls.getInterfaces()) {
+ checkPackageAccess(intf, pd);
+ }
+ return;
+ }
+
final String name = cls.getName();
final int i = name.lastIndexOf('.');
if (i != -1) {
@@ -518,7 +525,7 @@ public abstract class ClassLoader {
* follow the delegation model for loading classes, and will be invoked by
* the {@link #loadClass <tt>loadClass</tt>} method after checking the
* parent class loader for the requested class. The default implementation
- * throws a <tt>ClassNotFoundException</tt>. </p>
+ * throws a <tt>ClassNotFoundException</tt>.
*
* @param name
* The <a href="#name">binary name</a> of the class
@@ -681,42 +688,7 @@ public abstract class ClassLoader {
return source;
}
- private Class defineTransformedClass(String name, byte[] b, int off, int len,
- ProtectionDomain pd,
- ClassFormatError cfe, String source)
- throws ClassFormatError
- {
- // Class format error - try to transform the bytecode and
- // define the class again
- //
- ClassFileTransformer[] transformers =
- ClassFileTransformer.getTransformers();
- Class c = null;
-
- if (transformers != null) {
- for (ClassFileTransformer transformer : transformers) {
- try {
- // Transform byte code using transformer
- byte[] tb = transformer.transform(b, off, len);
- c = defineClass1(name, tb, 0, tb.length,
- pd, source);
- break;
- } catch (ClassFormatError cfe2) {
- // If ClassFormatError occurs, try next transformer
- }
- }
- }
-
- // Rethrow original ClassFormatError if unable to transform
- // bytecode to well-formed
- //
- if (c == null)
- throw cfe;
-
- return c;
- }
-
- private void postDefineClass(Class c, ProtectionDomain pd)
+ private void postDefineClass(Class<?> c, ProtectionDomain pd)
{
if (pd.getCodeSource() != null) {
Certificate certs[] = pd.getCodeSource().getCertificates();
@@ -749,7 +721,7 @@ public abstract class ClassLoader {
* bootstrap class loader. If <tt>name</tt> is not <tt>null</tt>, it
* must be equal to the <a href="#name">binary name</a> of the class
* specified by the byte array "<tt>b</tt>", otherwise a {@link
- * <tt>NoClassDefFoundError</tt>} will be thrown. </p>
+ * NoClassDefFoundError <tt>NoClassDefFoundError</tt>} will be thrown. </p>
*
* @param name
* The expected <a href="#name">binary name</a> of the class, or
@@ -796,17 +768,8 @@ public abstract class ClassLoader {
{
check();
protectionDomain = preDefineClass(name, protectionDomain);
-
- Class c = null;
String source = defineClassSourceLocation(protectionDomain);
-
- try {
- c = defineClass1(name, b, off, len, protectionDomain, source);
- } catch (ClassFormatError cfe) {
- c = defineTransformedClass(name, b, off, len, protectionDomain, cfe,
- source);
- }
-
+ Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
@@ -829,16 +792,16 @@ public abstract class ClassLoader {
* <i>bBuffer</i><tt>,</tt> <i>pd</i><tt>)</tt> yields exactly the same
* result as the statements
*
- * <blockquote><tt>
+ *<p> <tt>
* ...<br>
- * byte[] temp = new byte[</tt><i>bBuffer</i><tt>.{@link
+ * byte[] temp = new byte[bBuffer.{@link
* java.nio.ByteBuffer#remaining remaining}()];<br>
- * </tt><i>bBuffer</i><tt>.{@link java.nio.ByteBuffer#get(byte[])
+ * bBuffer.{@link java.nio.ByteBuffer#get(byte[])
* get}(temp);<br>
* return {@link #defineClass(String, byte[], int, int, ProtectionDomain)
- * </tt><i>cl</i><tt>.defineClass}(</tt><i>name</i><tt>, temp, 0,
- * temp.length, </tt><i>pd</i><tt>);<br>
- * </tt></blockquote>
+ * cl.defineClass}(name, temp, 0,
+ * temp.length, pd);<br>
+ * </tt></p>
*
* @param name
* The expected <a href="#name">binary name</a>. of the class, or
@@ -896,33 +859,21 @@ public abstract class ClassLoader {
}
protectionDomain = preDefineClass(name, protectionDomain);
-
- Class c = null;
String source = defineClassSourceLocation(protectionDomain);
-
- try {
- c = defineClass2(name, b, b.position(), len, protectionDomain,
- source);
- } catch (ClassFormatError cfe) {
- byte[] tb = new byte[len];
- b.get(tb); // get bytes out of byte buffer.
- c = defineTransformedClass(name, tb, 0, len, protectionDomain, cfe,
- source);
- }
-
+ Class<?> c = defineClass2(name, b, b.position(), len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
- private native Class defineClass0(String name, byte[] b, int off, int len,
- ProtectionDomain pd);
+ private native Class<?> defineClass0(String name, byte[] b, int off, int len,
+ ProtectionDomain pd);
- private native Class defineClass1(String name, byte[] b, int off, int len,
- ProtectionDomain pd, String source);
+ private native Class<?> defineClass1(String name, byte[] b, int off, int len,
+ ProtectionDomain pd, String source);
- private native Class defineClass2(String name, java.nio.ByteBuffer b,
- int off, int len, ProtectionDomain pd,
- String source);
+ private native Class<?> defineClass2(String name, java.nio.ByteBuffer b,
+ int off, int len, ProtectionDomain pd,
+ String source);
// true if the name is null or has the potential to be a valid binary name
static boolean checkName(String name) {
@@ -1011,7 +962,6 @@ public abstract class ClassLoader {
* already been linked, then this method simply returns. Otherwise, the
* class is linked as described in the "Execution" chapter of
* <cite>The Java&trade; Language Specification</cite>.
- * </p>
*
* @param c
* The class to link
@@ -1026,7 +976,7 @@ public abstract class ClassLoader {
resolveClass0(c);
}
- private native void resolveClass0(Class c);
+ private native void resolveClass0(Class<?> c);
/**
* Finds a class with the specified <a href="#name">binary name</a>,
@@ -1058,7 +1008,7 @@ public abstract class ClassLoader {
if (system == null) {
if (!checkName(name))
throw new ClassNotFoundException(name);
- Class cls = findBootstrapClass(name);
+ Class<?> cls = findBootstrapClass(name);
if (cls == null) {
throw new ClassNotFoundException(name);
}
@@ -1071,7 +1021,7 @@ public abstract class ClassLoader {
* Returns a class loaded by the bootstrap class loader;
* or return null if not found.
*/
- private Class findBootstrapClassOrNull(String name)
+ private Class<?> findBootstrapClassOrNull(String name)
{
check();
if (!checkName(name)) return null;
@@ -1080,7 +1030,7 @@ public abstract class ClassLoader {
}
// return null if not found
- private native Class findBootstrapClass(String name);
+ private native Class<?> findBootstrapClass(String name);
// Check to make sure the class loader has been initialized.
private void check() {
@@ -1093,7 +1043,7 @@ public abstract class ClassLoader {
* Returns the class with the given <a href="#name">binary name</a> if this
* loader has been recorded by the Java virtual machine as an initiating
* loader of a class with that <a href="#name">binary name</a>. Otherwise
- * <tt>null</tt> is returned. </p>
+ * <tt>null</tt> is returned.
*
* @param name
* The <a href="#name">binary name</a> of the class
@@ -1110,11 +1060,11 @@ public abstract class ClassLoader {
return findLoadedClass0(name);
}
- private native final Class findLoadedClass0(String name);
+ private native final Class<?> findLoadedClass0(String name);
/**
* Sets the signers of a class. This should be invoked after defining a
- * class. </p>
+ * class.
*
* @param c
* The <tt>Class</tt> object
@@ -1145,6 +1095,10 @@ public abstract class ClassLoader {
* built-in to the virtual machine is searched. That failing, this method
* will invoke {@link #findResource(String)} to find the resource. </p>
*
+ * @apiNote When overriding this method it is recommended that an
+ * implementation ensures that any delegation is consistent with the {@link
+ * #getResources(java.lang.String) getResources(String)} method.
+ *
* @param name
* The resource name
*
@@ -1178,6 +1132,13 @@ public abstract class ClassLoader {
* <p> The search order is described in the documentation for {@link
* #getResource(String)}. </p>
*
+ * @apiNote When overriding this method it is recommended that an
+ * implementation ensures that any delegation is consistent with the {@link
+ * #getResource(java.lang.String) getResource(String)} method. This should
+ * ensure that the first element returned by the Enumeration's
+ * {@code nextElement} method is the same resource that the
+ * {@code getResource(String)} method would return.
+ *
* @param name
* The resource name
*
@@ -1194,7 +1155,8 @@ public abstract class ClassLoader {
* @since 1.2
*/
public Enumeration<URL> getResources(String name) throws IOException {
- Enumeration[] tmp = new Enumeration[2];
+ @SuppressWarnings("unchecked")
+ Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
if (parent != null) {
tmp[0] = parent.getResources(name);
} else {
@@ -1207,7 +1169,7 @@ public abstract class ClassLoader {
/**
* Finds the resource with the given name. Class loader implementations
- * should override this method to specify where to find resources. </p>
+ * should override this method to specify where to find resources.
*
* @param name
* The resource name
@@ -1225,7 +1187,7 @@ public abstract class ClassLoader {
* Returns an enumeration of {@link java.net.URL <tt>URL</tt>} objects
* representing all the resources with the given name. Class loader
* implementations should override this method to specify where to load
- * resources from. </p>
+ * resources from.
*
* @param name
* The resource name
@@ -1243,14 +1205,16 @@ public abstract class ClassLoader {
}
/**
- * Registers the caller as parallel capable.</p>
+ * Registers the caller as parallel capable.
* The registration succeeds if and only if all of the following
- * conditions are met: <br>
- * 1. no instance of the caller has been created</p>
- * 2. all of the super classes (except class Object) of the caller are
- * registered as parallel capable</p>
- * Note that once a class loader is registered as parallel capable, there
- * is no way to change it back. </p>
+ * conditions are met:
+ * <ol>
+ * <li> no instance of the caller has been created</li>
+ * <li> all of the super classes (except class Object) of the caller are
+ * registered as parallel capable</li>
+ * </ol>
+ * <p>Note that once a class loader is registered as parallel capable, there
+ * is no way to change it back.</p>
*
* @return true if the caller is successfully registered as
* parallel capable and false if otherwise.
@@ -1267,7 +1231,7 @@ public abstract class ClassLoader {
/**
* Find a resource of the specified name from the search path used to load
* classes. This method locates the resource through the system class
- * loader (see {@link #getSystemClassLoader()}). </p>
+ * loader (see {@link #getSystemClassLoader()}).
*
* @param name
* The resource name
@@ -1358,7 +1322,7 @@ public abstract class ClassLoader {
/**
* Open for reading, a resource of the specified name from the search path
* used to load classes. This method locates the resource through the
- * system class loader (see {@link #getSystemClassLoader()}). </p>
+ * system class loader (see {@link #getSystemClassLoader()}).
*
* @param name
* The resource name
@@ -1411,6 +1375,9 @@ public abstract class ClassLoader {
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
+ // Check access to the parent class loader
+ // If the caller's class loader is same as this class loader,
+ // permission check is performed.
checkClassLoaderPermission(parent, Reflection.getCallerClass());
}
return parent;
@@ -1554,6 +1521,11 @@ public abstract class ClassLoader {
return caller.getClassLoader0();
}
+ /*
+ * Checks RuntimePermission("getClassLoader") permission
+ * if caller's class loader is not null and caller's class loader
+ * is not the same as or an ancestor of the given cl argument.
+ */
static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -1581,7 +1553,7 @@ public abstract class ClassLoader {
* class loaders to define the packages for their classes. Packages must
* be created before the class is defined, and package names must be
* unique within a class loader and cannot be redefined or changed once
- * created. </p>
+ * created.
*
* @param name
* The package name
@@ -1638,7 +1610,7 @@ public abstract class ClassLoader {
/**
* Returns a <tt>Package</tt> that has been defined by this class loader
- * or any of its ancestors. </p>
+ * or any of its ancestors.
*
* @param name
* The package name
@@ -1675,7 +1647,7 @@ public abstract class ClassLoader {
/**
* Returns all of the <tt>Packages</tt> defined by this class loader and
- * its ancestors. </p>
+ * its ancestors.
*
* @return The array of <tt>Package</tt> objects defined by this
* <tt>ClassLoader</tt>
@@ -1712,7 +1684,7 @@ public abstract class ClassLoader {
* method to locate the native libraries that belong to classes loaded with
* this class loader. If this method returns <tt>null</tt>, the VM
* searches the library along the path specified as the
- * "<tt>java.library.path</tt>" property. </p>
+ * "<tt>java.library.path</tt>" property.
*
* @param libname
* The library name
@@ -1750,22 +1722,29 @@ public abstract class ClassLoader {
private int jniVersion;
// the class from which the library is loaded, also indicates
// the loader this native library belongs.
- Class fromClass;
+ private final Class<?> fromClass;
// the canonicalized name of the native library.
+ // or static library name
String name;
+ // Indicates if the native library is linked into the VM
+ boolean isBuiltin;
+ // Indicates if the native library is loaded
+ boolean loaded;
+ native void load(String name, boolean isBuiltin);
- native void load(String name);
native long find(String name);
- native void unload();
+ native void unload(String name, boolean isBuiltin);
+ static native String findBuiltinLib(String name);
- public NativeLibrary(Class fromClass, String name) {
+ public NativeLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
this.name = name;
this.fromClass = fromClass;
+ this.isBuiltin = isBuiltin;
}
protected void finalize() {
synchronized (loadedLibraryNames) {
- if (fromClass.getClassLoader() != null && handle != 0) {
+ if (fromClass.getClassLoader() != null && loaded) {
/* remove the native library name */
int size = loadedLibraryNames.size();
for (int i = 0; i < size; i++) {
@@ -1777,7 +1756,7 @@ public abstract class ClassLoader {
/* unload the library. */
ClassLoader.nativeLibraryContext.push(this);
try {
- unload();
+ unload(name, isBuiltin);
} finally {
ClassLoader.nativeLibraryContext.pop();
}
@@ -1786,7 +1765,7 @@ public abstract class ClassLoader {
}
// Invoked in the VM to determine the context class in
// JNI_Load/JNI_Unload
- static Class getFromClass() {
+ static Class<?> getFromClass() {
return ClassLoader.nativeLibraryContext.peek().fromClass;
}
}
@@ -1849,7 +1828,7 @@ public abstract class ClassLoader {
}
// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
- static void loadLibrary(Class fromClass, String name,
+ static void loadLibrary(Class<?> fromClass, String name,
boolean isAbsolute) {
ClassLoader loader =
(fromClass == null) ? null : fromClass.getClassLoader();
@@ -1882,6 +1861,10 @@ public abstract class ClassLoader {
if (loadLibrary0(fromClass, libfile)) {
return;
}
+ libfile = ClassLoaderHelper.mapAlternativeName(libfile);
+ if (libfile != null && loadLibrary0(fromClass, libfile)) {
+ return;
+ }
}
if (loader != null) {
for (int i = 0 ; i < usr_paths.length ; i++) {
@@ -1890,38 +1873,35 @@ public abstract class ClassLoader {
if (loadLibrary0(fromClass, libfile)) {
return;
}
+ libfile = ClassLoaderHelper.mapAlternativeName(libfile);
+ if (libfile != null && loadLibrary0(fromClass, libfile)) {
+ return;
+ }
}
}
// Oops, it failed
throw new UnsatisfiedLinkError("no " + name + " in java.library.path");
}
- private static boolean loadLibrary0(Class fromClass, final File file) {
- if (loadLibrary1(fromClass, file)) {
- return true;
- }
- final File libfile = ClassLoaderHelper.mapAlternativeName(file);
- if (libfile != null && loadLibrary1(fromClass, libfile)) {
- return true;
- }
- return false;
- }
-
- private static boolean loadLibrary1(Class fromClass, final File file) {
- boolean exists = AccessController.doPrivileged(
- new PrivilegedAction<Object>() {
- public Object run() {
- return file.exists() ? Boolean.TRUE : null;
- }})
- != null;
- if (!exists) {
- return false;
- }
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- return false;
+ private static boolean loadLibrary0(Class<?> fromClass, final File file) {
+ // Check to see if we're attempting to access a static library
+ String name = NativeLibrary.findBuiltinLib(file.getName());
+ boolean isBuiltin = (name != null);
+ if (!isBuiltin) {
+ boolean exists = AccessController.doPrivileged(
+ new PrivilegedAction<Object>() {
+ public Object run() {
+ return file.exists() ? Boolean.TRUE : null;
+ }})
+ != null;
+ if (!exists) {
+ return false;
+ }
+ try {
+ name = file.getCanonicalPath();
+ } catch (IOException e) {
+ return false;
+ }
}
ClassLoader loader =
(fromClass == null) ? null : fromClass.getClassLoader();
@@ -1969,14 +1949,14 @@ public abstract class ClassLoader {
}
}
}
- NativeLibrary lib = new NativeLibrary(fromClass, name);
+ NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
nativeLibraryContext.push(lib);
try {
- lib.load(name);
+ lib.load(name, isBuiltin);
} finally {
nativeLibraryContext.pop();
}
- if (lib.handle != 0) {
+ if (lib.loaded) {
loadedLibraryNames.addElement(name);
libs.addElement(lib);
return true;
@@ -2032,7 +2012,7 @@ public abstract class ClassLoader {
* in the future will have assertions enabled or disabled by default.
* This setting may be overridden on a per-package or per-class basis by
* invoking {@link #setPackageAssertionStatus(String, boolean)} or {@link
- * #setClassAssertionStatus(String, boolean)}. </p>
+ * #setClassAssertionStatus(String, boolean)}.
*
* @param enabled
* <tt>true</tt> if classes loaded by this class loader will
@@ -2134,7 +2114,6 @@ public abstract class ClassLoader {
* status settings associated with the class loader. This method is
* provided so that class loaders can be made to ignore any command line or
* persistent assertion status settings and "start with a clean slate."
- * </p>
*
* @since 1.4
*/
@@ -2251,8 +2230,8 @@ class SystemClassLoaderAction
return parent;
}
- Constructor ctor = Class.forName(cls, true, parent)
- .getDeclaredConstructor(new Class[] { ClassLoader.class });
+ Constructor<?> ctor = Class.forName(cls, true, parent)
+ .getDeclaredConstructor(new Class<?>[] { ClassLoader.class });
ClassLoader sys = (ClassLoader) ctor.newInstance(
new Object[] { parent });
Thread.currentThread().setContextClassLoader(sys);
diff --git a/openjdk/java/lang/StringHelper.java b/openjdk/java/lang/StringHelper.java
index 98f7816c..de318623 100644
--- a/openjdk/java/lang/StringHelper.java
+++ b/openjdk/java/lang/StringHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package java.lang;
import java.io.ObjectStreamField;
@@ -32,28 +33,30 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
+import java.util.Objects;
+import java.util.StringJoiner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
- * The <code>String</code> class represents character strings. All
- * string literals in Java programs, such as <code>"abc"</code>, are
+ * The {@code String} class represents character strings. All
+ * string literals in Java programs, such as {@code "abc"}, are
* implemented as instances of this class.
* <p>
* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared. For example:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>
* is equivalent to:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
* </pre></blockquote><p>
* Here are some more examples of how strings can be used:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* System.out.println("abc");
* String cde = "cde";
* System.out.println("abc" + cde);
@@ -61,7 +64,7 @@ import java.util.regex.PatternSyntaxException;
* String d = cde.substring(1, 2);
* </pre></blockquote>
* <p>
- * The class <code>String</code> includes methods for examining
+ * The class {@code String} includes methods for examining
* individual characters of the sequence, for comparing strings, for
* searching strings, for extracting substrings, and for creating a
* copy of a string with all characters translated to uppercase or to
@@ -71,10 +74,10 @@ import java.util.regex.PatternSyntaxException;
* The Java language provides special support for the string
* concatenation operator (&nbsp;+&nbsp;), and for conversion of
* other objects to strings. String concatenation is implemented
- * through the <code>StringBuilder</code>(or <code>StringBuffer</code>)
- * class and its <code>append</code> method.
+ * through the {@code StringBuilder}(or {@code StringBuffer})
+ * class and its {@code append} method.
* String conversions are implemented through the method
- * <code>toString</code>, defined by <code>Object</code> and
+ * {@code toString}, defined by {@code Object} and
* inherited by all classes in Java. For additional information on
* string concatenation and conversion, see Gosling, Joy, and Steele,
* <i>The Java Language Specification</i>.
@@ -83,16 +86,16 @@ import java.util.regex.PatternSyntaxException;
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
*
- * <p>A <code>String</code> represents a string in the UTF-16 format
+ * <p>A {@code String} represents a string in the UTF-16 format
* in which <em>supplementary characters</em> are represented by <em>surrogate
* pairs</em> (see the section <a href="Character.html#unicode">Unicode
- * Character Representations</a> in the <code>Character</code> class for
+ * Character Representations</a> in the {@code Character} class for
* more information).
- * Index values refer to <code>char</code> code units, so a supplementary
- * character uses two positions in a <code>String</code>.
- * <p>The <code>String</code> class provides methods for dealing with
+ * Index values refer to {@code char} code units, so a supplementary
+ * character uses two positions in a {@code String}.
+ * <p>The {@code String} class provides methods for dealing with
* Unicode code points (i.e., characters), in addition to those for
- * dealing with Unicode code units (i.e., <code>char</code> values).
+ * dealing with Unicode code units (i.e., {@code char} values).
*
* @author Lee Boynton
* @author Arthur van Hoff
@@ -495,30 +498,24 @@ final class StringHelper
return builder.toString();
}
-
- // Package private constructor which shares value array for speed.
- static String NewString(int offset, int count, char value[]) {
- return new String(value, offset, count);
- }
-
/**
* Returns the character (Unicode code point) at the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>0</code> to
- * {@link #length()}<code> - 1</code>.
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 0} to
+ * {@link #length()}{@code - 1}.
*
- * <p> If the <code>char</code> value specified at the given index
+ * <p> If the {@code char} value specified at the given index
* is in the high-surrogate range, the following index is less
- * than the length of this <code>String</code>, and the
- * <code>char</code> value at the following index is in the
+ * than the length of this {@code String}, and the
+ * {@code char} value at the following index is in the
* low-surrogate range, then the supplementary code point
* corresponding to this surrogate pair is returned. Otherwise,
- * the <code>char</code> value at the given index is returned.
+ * the {@code char} value at the given index is returned.
*
- * @param index the index to the <code>char</code> values
+ * @param index the index to the {@code char} values
* @return the code point value of the character at the
- * <code>index</code>
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * {@code index}
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is negative or not less than the length of this
* string.
* @since 1.5
@@ -541,22 +538,22 @@ final class StringHelper
/**
* Returns the character (Unicode code point) before the specified
- * index. The index refers to <code>char</code> values
- * (Unicode code units) and ranges from <code>1</code> to {@link
+ * index. The index refers to {@code char} values
+ * (Unicode code units) and ranges from {@code 1} to {@link
* CharSequence#length() length}.
*
- * <p> If the <code>char</code> value at <code>(index - 1)</code>
- * is in the low-surrogate range, <code>(index - 2)</code> is not
- * negative, and the <code>char</code> value at <code>(index -
- * 2)</code> is in the high-surrogate range, then the
+ * <p> If the {@code char} value at {@code (index - 1)}
+ * is in the low-surrogate range, {@code (index - 2)} is not
+ * negative, and the {@code char} value at {@code (index -
+ * 2)} is in the high-surrogate range, then the
* supplementary code point value of the surrogate pair is
- * returned. If the <code>char</code> value at <code>index -
- * 1</code> is an unpaired low-surrogate or a high-surrogate, the
+ * returned. If the {@code char} value at {@code index -
+ * 1} is an unpaired low-surrogate or a high-surrogate, the
* surrogate value is returned.
*
* @param index the index following the code point that should be returned
* @return the Unicode code point value before the given index.
- * @exception IndexOutOfBoundsException if the <code>index</code>
+ * @exception IndexOutOfBoundsException if the {@code index}
* argument is less than 1 or greater than the length
* of this string.
* @since 1.5
@@ -580,23 +577,23 @@ final class StringHelper
/**
* Returns the number of Unicode code points in the specified text
- * range of this <code>String</code>. The text range begins at the
- * specified <code>beginIndex</code> and extends to the
- * <code>char</code> at index <code>endIndex - 1</code>. Thus the
- * length (in <code>char</code>s) of the text range is
- * <code>endIndex-beginIndex</code>. Unpaired surrogates within
+ * range of this {@code String}. The text range begins at the
+ * specified {@code beginIndex} and extends to the
+ * {@code char} at index {@code endIndex - 1}. Thus the
+ * length (in {@code char}s) of the text range is
+ * {@code endIndex-beginIndex}. Unpaired surrogates within
* the text range count as one code point each.
*
- * @param beginIndex the index to the first <code>char</code> of
+ * @param beginIndex the index to the first {@code char} of
* the text range.
- * @param endIndex the index after the last <code>char</code> of
+ * @param endIndex the index after the last {@code char} of
* the text range.
* @return the number of Unicode code points in the specified text
* range
* @exception IndexOutOfBoundsException if the
- * <code>beginIndex</code> is negative, or <code>endIndex</code>
- * is larger than the length of this <code>String</code>, or
- * <code>beginIndex</code> is larger than <code>endIndex</code>.
+ * {@code beginIndex} is negative, or {@code endIndex}
+ * is larger than the length of this {@code String}, or
+ * {@code beginIndex} is larger than {@code endIndex}.
* @since 1.5
*/
static int codePointCount(String _this, int beginIndex, int endIndex) {
@@ -616,23 +613,23 @@ final class StringHelper
}
/**
- * Returns the index within this <code>String</code> that is
- * offset from the given <code>index</code> by
- * <code>codePointOffset</code> code points. Unpaired surrogates
- * within the text range given by <code>index</code> and
- * <code>codePointOffset</code> count as one code point each.
+ * Returns the index within this {@code String} that is
+ * offset from the given {@code index} by
+ * {@code codePointOffset} code points. Unpaired surrogates
+ * within the text range given by {@code index} and
+ * {@code codePointOffset} count as one code point each.
*
* @param index the index to be offset
* @param codePointOffset the offset in code points
- * @return the index within this <code>String</code>
- * @exception IndexOutOfBoundsException if <code>index</code>
+ * @return the index within this {@code String}
+ * @exception IndexOutOfBoundsException if {@code index}
* is negative or larger then the length of this
- * <code>String</code>, or if <code>codePointOffset</code> is positive
- * and the substring starting with <code>index</code> has fewer
- * than <code>codePointOffset</code> code points,
- * or if <code>codePointOffset</code> is negative and the substring
- * before <code>index</code> has fewer than the absolute value
- * of <code>codePointOffset</code> code points.
+ * {@code String}, or if {@code codePointOffset} is positive
+ * and the substring starting with {@code index} has fewer
+ * than {@code codePointOffset} code points,
+ * or if {@code codePointOffset} is negative and the substring
+ * before {@code index} has fewer than the absolute value
+ * of {@code codePointOffset} code points.
* @since 1.5
*/
static int offsetByCodePoints(String _this, int index, int codePointOffset) {
@@ -682,13 +679,13 @@ final class StringHelper
* Copies characters from this string into the destination character
* array.
* <p>
- * The first character to be copied is at index <code>srcBegin</code>;
- * the last character to be copied is at index <code>srcEnd-1</code>
+ * The first character to be copied is at index {@code srcBegin};
+ * the last character to be copied is at index {@code srcEnd-1}
* (thus the total number of characters to be copied is
- * <code>srcEnd-srcBegin</code>). The characters are copied into the
- * subarray of <code>dst</code> starting at index <code>dstBegin</code>
+ * {@code srcEnd-srcBegin}). The characters are copied into the
+ * subarray of {@code dst} starting at index {@code dstBegin}
* and ending at index:
- * <p><blockquote><pre>
+ * <blockquote><pre>
* dstbegin + (srcEnd-srcBegin) - 1
* </pre></blockquote>
*
@@ -700,13 +697,13 @@ final class StringHelper
* @param dstBegin the start offset in the destination array.
* @exception IndexOutOfBoundsException If any of the following
* is true:
- * <ul><li><code>srcBegin</code> is negative.
- * <li><code>srcBegin</code> is greater than <code>srcEnd</code>
- * <li><code>srcEnd</code> is greater than the length of this
+ * <ul><li>{@code srcBegin} is negative.
+ * <li>{@code srcBegin} is greater than {@code srcEnd}
+ * <li>{@code srcEnd} is greater than the length of this
* string
- * <li><code>dstBegin</code> is negative
- * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
- * <code>dst.length</code></ul>
+ * <li>{@code dstBegin} is negative
+ * <li>{@code dstBegin+(srcEnd-srcBegin)} is larger than
+ * {@code dst.length}</ul>
*/
static void getChars(cli.System.String _this, int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
@@ -775,6 +772,8 @@ final class StringHelper
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
+ Objects.requireNonNull(dst);
+
int j = dstBegin;
int n = srcEnd;
int i = srcBegin;
@@ -856,7 +855,8 @@ final class StringHelper
/**
* Compares this string to the specified {@code StringBuffer}. The result
* is {@code true} if and only if this {@code String} represents the same
- * sequence of characters as the specified {@code StringBuffer}.
+ * sequence of characters as the specified {@code StringBuffer}. This method
+ * synchronizes on the {@code StringBuffer}.
*
* @param sb
* The {@code StringBuffer} to compare this {@code String} against
@@ -868,15 +868,29 @@ final class StringHelper
* @since 1.4
*/
static boolean contentEquals(String _this, StringBuffer sb) {
- synchronized (sb) {
- return contentEquals(_this, (CharSequence) sb);
+ return contentEquals(_this, (CharSequence)sb);
+ }
+
+ private static boolean nonSyncContentEquals(String _this, AbstractStringBuilder sb) {
+ char v2[] = sb.getValue();
+ int n = _this.length();
+ if (n != sb.length()) {
+ return false;
}
+ for (int i = 0; i < n; i++) {
+ if (_this.charAt(i) != v2[i]) {
+ return false;
+ }
+ }
+ return true;
}
/**
- * Compares this string to the specified {@code CharSequence}. The result
- * is {@code true} if and only if this {@code String} represents the same
- * sequence of char values as the specified sequence.
+ * Compares this string to the specified {@code CharSequence}. The
+ * result is {@code true} if and only if this {@code String} represents the
+ * same sequence of char values as the specified sequence. Note that if the
+ * {@code CharSequence} is a {@code StringBuffer} then the method
+ * synchronizes on it.
*
* @param cs
* The sequence to compare this {@code String} against
@@ -888,30 +902,29 @@ final class StringHelper
* @since 1.5
*/
static boolean contentEquals(String _this, CharSequence cs) {
- if (_this.length() != cs.length())
- return false;
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
- char v2[] = ((AbstractStringBuilder) cs).getValue();
- int i = 0;
- int n = _this.length();
- while (n-- != 0) {
- if (_this.charAt(i) != v2[i])
- return false;
- i++;
+ if (cs instanceof StringBuffer) {
+ synchronized(cs) {
+ return nonSyncContentEquals(_this, (AbstractStringBuilder)cs);
+ }
+ } else {
+ return nonSyncContentEquals(_this, (AbstractStringBuilder)cs);
}
- return true;
}
// Argument is a String
- if (cs.equals(_this))
- return true;
+ if (cs instanceof String) {
+ return _this.equals(cs);
+ }
// Argument is a generic CharSequence
- int i = 0;
int n = _this.length();
- while (n-- != 0) {
- if (_this.charAt(i) != cs.charAt(i))
+ if (n != cs.length()) {
+ return false;
+ }
+ for (int i = 0; i < n; i++) {
+ if (_this.charAt(i) != cs.charAt(i)) {
return false;
- i++;
+ }
}
return true;
}
@@ -955,14 +968,14 @@ final class StringHelper
* Compares two strings lexicographically.
* The comparison is based on the Unicode value of each character in
* the strings. The character sequence represented by this
- * <code>String</code> object is compared lexicographically to the
+ * {@code String} object is compared lexicographically to the
* character sequence represented by the argument string. The result is
- * a negative integer if this <code>String</code> object
+ * a negative integer if this {@code String} object
* lexicographically precedes the argument string. The result is a
- * positive integer if this <code>String</code> object lexicographically
+ * positive integer if this {@code String} object lexicographically
* follows the argument string. The result is zero if the strings
- * are equal; <code>compareTo</code> returns <code>0</code> exactly when
- * the {@link #equals(Object)} method would return <code>true</code>.
+ * are equal; {@code compareTo} returns {@code 0} exactly when
+ * the {@link #equals(Object)} method would return {@code true}.
* <p>
* This is the definition of lexicographic ordering. If two strings are
* different, then either they have different characters at some index
@@ -971,25 +984,25 @@ final class StringHelper
* positions, let <i>k</i> be the smallest such index; then the string
* whose character at position <i>k</i> has the smaller value, as
* determined by using the &lt; operator, lexicographically precedes the
- * other string. In this case, <code>compareTo</code> returns the
- * difference of the two character values at position <code>k</code> in
+ * other string. In this case, {@code compareTo} returns the
+ * difference of the two character values at position {@code k} in
* the two string -- that is, the value:
* <blockquote><pre>
* this.charAt(k)-anotherString.charAt(k)
* </pre></blockquote>
* If there is no index position at which they differ, then the shorter
* string lexicographically precedes the longer string. In this case,
- * <code>compareTo</code> returns the difference of the lengths of the
+ * {@code compareTo} returns the difference of the lengths of the
* strings -- that is, the value:
* <blockquote><pre>
* this.length()-anotherString.length()
* </pre></blockquote>
*
- * @param anotherString the <code>String</code> to be compared.
- * @return the value <code>0</code> if the argument string is equal to
- * this string; a value less than <code>0</code> if this string
+ * @param anotherString the {@code String} to be compared.
+ * @return the value {@code 0} if the argument string is equal to
+ * this string; a value less than {@code 0} if this string
* is lexicographically less than the string argument; and a
- * value greater than <code>0</code> if this string is
+ * value greater than {@code 0} if this string is
* lexicographically greater than the string argument.
*/
static int compareTo(String _this, String anotherString) {
@@ -1008,9 +1021,9 @@ final class StringHelper
/**
* Compares two strings lexicographically, ignoring case
* differences. This method returns an integer whose sign is that of
- * calling <code>compareTo</code> with normalized versions of the strings
+ * calling {@code compareTo} with normalized versions of the strings
* where case differences have been eliminated by calling
- * <code>Character.toLowerCase(Character.toUpperCase(character))</code> on
+ * {@code Character.toLowerCase(Character.toUpperCase(character))} on
* each character.
* <p>
* Note that this method does <em>not</em> take locale into account,
@@ -1018,7 +1031,7 @@ final class StringHelper
* The java.text package provides <em>collators</em> to allow
* locale-sensitive ordering.
*
- * @param str the <code>String</code> to be compared.
+ * @param str the {@code String} to be compared.
* @return a negative integer, zero, or a positive integer as the
* specified String is greater than, equal to, or less
* than this String, ignoring case considerations.
@@ -1032,23 +1045,24 @@ final class StringHelper
/**
* Tests if two string regions are equal.
* <p>
- * A substring of this <tt>String</tt> object is compared to a substring
+ * A substring of this {@code String} object is compared to a substring
* of the argument other. The result is true if these substrings
* represent identical character sequences. The substring of this
- * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
- * and has length <tt>len</tt>. The substring of other to be compared
- * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
- * result is <tt>false</tt> if and only if at least one of the following
+ * {@code String} object to be compared begins at index {@code toffset}
+ * and has length {@code len}. The substring of other to be compared
+ * begins at index {@code ooffset} and has length {@code len}. The
+ * result is {@code false} if and only if at least one of the following
* is true:
- * <ul><li><tt>toffset</tt> is negative.
- * <li><tt>ooffset</tt> is negative.
- * <li><tt>toffset+len</tt> is greater than the length of this
- * <tt>String</tt> object.
- * <li><tt>ooffset+len</tt> is greater than the length of the other
+ * <ul><li>{@code toffset} is negative.
+ * <li>{@code ooffset} is negative.
+ * <li>{@code toffset+len} is greater than the length of this
+ * {@code String} object.
+ * <li>{@code ooffset+len} is greater than the length of the other
* argument.
- * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
+ * <li>There is some nonnegative integer <i>k</i> less than {@code len}
* such that:
- * <tt>this.charAt(toffset+<i>k</i>)&nbsp;!=&nbsp;other.charAt(ooffset+<i>k</i>)</tt>
+ * {@code this.charAt(toffset + }<i>k</i>{@code ) != other.charAt(ooffset + }
+ * <i>k</i>{@code )}
* </ul>
*
* @param toffset the starting offset of the subregion in this string.
@@ -1056,9 +1070,9 @@ final class StringHelper
* @param ooffset the starting offset of the subregion in the string
* argument.
* @param len the number of characters to compare.
- * @return <code>true</code> if the specified subregion of this string
+ * @return {@code true} if the specified subregion of this string
* exactly matches the specified subregion of the string argument;
- * <code>false</code> otherwise.
+ * {@code false} otherwise.
*/
static boolean regionMatches(String _this, int toffset, String other, int ooffset,
int len) {
@@ -1081,28 +1095,28 @@ final class StringHelper
/**
* Tests if two string regions are equal.
* <p>
- * A substring of this <tt>String</tt> object is compared to a substring
- * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
+ * A substring of this {@code String} object is compared to a substring
+ * of the argument {@code other}. The result is {@code true} if these
* substrings represent character sequences that are the same, ignoring
- * case if and only if <tt>ignoreCase</tt> is true. The substring of
- * this <tt>String</tt> object to be compared begins at index
- * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
- * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
- * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
+ * case if and only if {@code ignoreCase} is true. The substring of
+ * this {@code String} object to be compared begins at index
+ * {@code toffset} and has length {@code len}. The substring of
+ * {@code other} to be compared begins at index {@code ooffset} and
+ * has length {@code len}. The result is {@code false} if and only if
* at least one of the following is true:
- * <ul><li><tt>toffset</tt> is negative.
- * <li><tt>ooffset</tt> is negative.
- * <li><tt>toffset+len</tt> is greater than the length of this
- * <tt>String</tt> object.
- * <li><tt>ooffset+len</tt> is greater than the length of the other
+ * <ul><li>{@code toffset} is negative.
+ * <li>{@code ooffset} is negative.
+ * <li>{@code toffset+len} is greater than the length of this
+ * {@code String} object.
+ * <li>{@code ooffset+len} is greater than the length of the other
* argument.
- * <li><tt>ignoreCase</tt> is <tt>false</tt> and there is some nonnegative
- * integer <i>k</i> less than <tt>len</tt> such that:
+ * <li>{@code ignoreCase} is {@code false} and there is some nonnegative
+ * integer <i>k</i> less than {@code len} such that:
* <blockquote><pre>
* this.charAt(toffset+k) != other.charAt(ooffset+k)
* </pre></blockquote>
- * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
- * integer <i>k</i> less than <tt>len</tt> such that:
+ * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
+ * integer <i>k</i> less than {@code len} such that:
* <blockquote><pre>
* Character.toLowerCase(this.charAt(toffset+k)) !=
Character.toLowerCase(other.charAt(ooffset+k))
@@ -1114,7 +1128,7 @@ final class StringHelper
* </pre></blockquote>
* </ul>
*
- * @param ignoreCase if <code>true</code>, ignore case when comparing
+ * @param ignoreCase if {@code true}, ignore case when comparing
* characters.
* @param toffset the starting offset of the subregion in this
* string.
@@ -1122,10 +1136,10 @@ final class StringHelper
* @param ooffset the starting offset of the subregion in the string
* argument.
* @param len the number of characters to compare.
- * @return <code>true</code> if the specified subregion of this string
+ * @return {@code true} if the specified subregion of this string
* matches the specified subregion of the string argument;
- * <code>false</code> otherwise. Whether the matching is exact
- * or case insensitive depends on the <code>ignoreCase</code>
+ * {@code false} otherwise. Whether the matching is exact
+ * or case insensitive depends on the {@code ignoreCase}
* argument.
*/
static boolean regionMatches(String _this, boolean ignoreCase, int toffset,
@@ -1169,13 +1183,13 @@ final class StringHelper
/**
* Returns a hash code for this string. The hash code for a
- * <code>String</code> object is computed as
+ * {@code String} object is computed as
* <blockquote><pre>
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
* </pre></blockquote>
- * using <code>int</code> arithmetic, where <code>s[i]</code> is the
- * <i>i</i>th character of the string, <code>n</code> is the length of
- * the string, and <code>^</code> indicates exponentiation.
+ * using {@code int} arithmetic, where {@code s[i]} is the
+ * <i>i</i>th character of the string, {@code n} is the length of
+ * the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
@@ -1194,26 +1208,26 @@ final class StringHelper
/**
* Returns the index within this string of the first occurrence of
* the specified character. If a character with value
- * <code>ch</code> occurs in the character sequence represented by
- * this <code>String</code> object, then the index (in Unicode
+ * {@code ch} occurs in the character sequence represented by
+ * this {@code String} object, then the index (in Unicode
* code units) of the first such occurrence is returned. For
- * values of <code>ch</code> in the range from 0 to 0xFFFF
+ * values of {@code ch} in the range from 0 to 0xFFFF
* (inclusive), this is the smallest value <i>k</i> such that:
* <blockquote><pre>
* this.charAt(<i>k</i>) == ch
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* smallest value <i>k</i> such that:
* <blockquote><pre>
* this.codePointAt(<i>k</i>) == ch
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string, then <code>-1</code> is returned.
+ * string, then {@code -1} is returned.
*
* @param ch a character (Unicode code point).
* @return the index of the first occurrence of the character in the
* character sequence represented by this object, or
- * <code>-1</code> if the character does not occur.
+ * {@code -1} if the character does not occur.
*/
static int indexOf(cli.System.String _this, int ch) {
return indexOf(_this, ch, 0);
@@ -1223,39 +1237,39 @@ final class StringHelper
* Returns the index within this string of the first occurrence of the
* specified character, starting the search at the specified index.
* <p>
- * If a character with value <code>ch</code> occurs in the
- * character sequence represented by this <code>String</code>
- * object at an index no smaller than <code>fromIndex</code>, then
+ * If a character with value {@code ch} occurs in the
+ * character sequence represented by this {@code String}
+ * object at an index no smaller than {@code fromIndex}, then
* the index of the first such occurrence is returned. For values
- * of <code>ch</code> in the range from 0 to 0xFFFF (inclusive),
+ * of {@code ch} in the range from 0 to 0xFFFF (inclusive),
* this is the smallest value <i>k</i> such that:
* <blockquote><pre>
- * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+ * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* smallest value <i>k</i> such that:
* <blockquote><pre>
- * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &gt;= fromIndex)
+ * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &gt;= fromIndex)
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string at or after position <code>fromIndex</code>, then
- * <code>-1</code> is returned.
+ * string at or after position {@code fromIndex}, then
+ * {@code -1} is returned.
*
* <p>
- * There is no restriction on the value of <code>fromIndex</code>. If it
+ * There is no restriction on the value of {@code fromIndex}. If it
* is negative, it has the same effect as if it were zero: this entire
* string may be searched. If it is greater than the length of this
* string, it has the same effect as if it were equal to the length of
- * this string: <code>-1</code> is returned.
+ * this string: {@code -1} is returned.
*
- * <p>All indices are specified in <code>char</code> values
+ * <p>All indices are specified in {@code char} values
* (Unicode code units).
*
* @param ch a character (Unicode code point).
* @param fromIndex the index to start the search from.
* @return the index of the first occurrence of the character in the
* character sequence represented by this object that is greater
- * than or equal to <code>fromIndex</code>, or <code>-1</code>
+ * than or equal to {@code fromIndex}, or {@code -1}
* if the character does not occur.
*/
static int indexOf(cli.System.String _this, int ch, int fromIndex) {
@@ -1302,26 +1316,26 @@ final class StringHelper
/**
* Returns the index within this string of the last occurrence of
- * the specified character. For values of <code>ch</code> in the
+ * the specified character. For values of {@code ch} in the
* range from 0 to 0xFFFF (inclusive), the index (in Unicode code
* units) returned is the largest value <i>k</i> such that:
* <blockquote><pre>
* this.charAt(<i>k</i>) == ch
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* largest value <i>k</i> such that:
* <blockquote><pre>
* this.codePointAt(<i>k</i>) == ch
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string, then <code>-1</code> is returned. The
- * <code>String</code> is searched backwards starting at the last
+ * string, then {@code -1} is returned. The
+ * {@code String} is searched backwards starting at the last
* character.
*
* @param ch a character (Unicode code point).
* @return the index of the last occurrence of the character in the
* character sequence represented by this object, or
- * <code>-1</code> if the character does not occur.
+ * {@code -1} if the character does not occur.
*/
static int lastIndexOf(cli.System.String _this, int ch) {
return lastIndexOf(_this, ch, _this.get_Length() - 1);
@@ -1330,27 +1344,27 @@ final class StringHelper
/**
* Returns the index within this string of the last occurrence of
* the specified character, searching backward starting at the
- * specified index. For values of <code>ch</code> in the range
+ * specified index. For values of {@code ch} in the range
* from 0 to 0xFFFF (inclusive), the index returned is the largest
* value <i>k</i> such that:
* <blockquote><pre>
- * (this.charAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+ * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
* </pre></blockquote>
- * is true. For other values of <code>ch</code>, it is the
+ * is true. For other values of {@code ch}, it is the
* largest value <i>k</i> such that:
* <blockquote><pre>
- * (this.codePointAt(<i>k</i>) == ch) && (<i>k</i> &lt;= fromIndex)
+ * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> &lt;= fromIndex)
* </pre></blockquote>
* is true. In either case, if no such character occurs in this
- * string at or before position <code>fromIndex</code>, then
- * <code>-1</code> is returned.
+ * string at or before position {@code fromIndex}, then
+ * {@code -1} is returned.
*
- * <p>All indices are specified in <code>char</code> values
+ * <p>All indices are specified in {@code char} values
* (Unicode code units).
*
* @param ch a character (Unicode code point).
* @param fromIndex the index to start the search from. There is no
- * restriction on the value of <code>fromIndex</code>. If it is
+ * restriction on the value of {@code fromIndex}. If it is
* greater than or equal to the length of this string, it has
* the same effect as if it were equal to one less than the
* length of this string: this entire string may be searched.
@@ -1358,7 +1372,7 @@ final class StringHelper
* -1 is returned.
* @return the index of the last occurrence of the character in the
* character sequence represented by this object that is less
- * than or equal to <code>fromIndex</code>, or <code>-1</code>
+ * than or equal to {@code fromIndex}, or {@code -1}
* if the character does not occur before that point.
*/
static int lastIndexOf(cli.System.String _this, int ch, int fromIndex) {
@@ -1418,7 +1432,7 @@ final class StringHelper
*
* <p>The returned index is the smallest value <i>k</i> for which:
* <blockquote><pre>
- * <i>k</i> &gt;= fromIndex && this.startsWith(str, <i>k</i>)
+ * <i>k</i> &gt;= fromIndex {@code &&} this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
@@ -1456,6 +1470,56 @@ final class StringHelper
}
/**
+ * Code shared by String and AbstractStringBuilder to do searches. The
+ * source is the character array being searched, and the target
+ * is the string being searched for.
+ *
+ * @param source the characters being searched.
+ * @param sourceOffset offset of the source string.
+ * @param sourceCount count of the source string.
+ * @param target the characters being searched for.
+ * @param fromIndex the index to begin searching from.
+ */
+ static int indexOf(char[] source, int sourceOffset, int sourceCount,
+ String target, int fromIndex) {
+ final int targetOffset = 0;
+ final int targetCount = target.length();
+ if (fromIndex >= sourceCount) {
+ return (targetCount == 0 ? sourceCount : -1);
+ }
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ if (targetCount == 0) {
+ return fromIndex;
+ }
+
+ char first = target.charAt(targetOffset);
+ int max = sourceOffset + (sourceCount - targetCount);
+
+ for (int i = sourceOffset + fromIndex; i <= max; i++) {
+ /* Look for first character. */
+ if (source[i] != first) {
+ while (++i <= max && source[i] != first);
+ }
+
+ /* Found first character, now look at the rest of v2 */
+ if (i <= max) {
+ int j = i + 1;
+ int end = j + targetCount - 1;
+ for (int k = targetOffset + 1; j < end && source[j]
+ == target.charAt(k); j++, k++);
+
+ if (j == end) {
+ /* Found whole string. */
+ return i - sourceOffset;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
* Code shared by String and StringBuffer to do searches. The
* source is the character array being searched, and the target
* is the string being searched for.
@@ -1531,7 +1595,7 @@ final class StringHelper
*
* <p>The returned index is the largest value <i>k</i> for which:
* <blockquote><pre>
- * <i>k</i> &lt;= fromIndex && this.startsWith(str, <i>k</i>)
+ * <i>k</i> {@code <=} fromIndex {@code &&} this.startsWith(str, <i>k</i>)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then {@code -1} is returned.
*
@@ -1572,6 +1636,65 @@ final class StringHelper
return cli.System.String.CompareOrdinal(_this, 0, str, 0, olen) == 0 ? 0 : -1;
}
+
+ /**
+ * Code shared by String and AbstractStringBuilder to do searches. The
+ * source is the character array being searched, and the target
+ * is the string being searched for.
+ *
+ * @param source the characters being searched.
+ * @param sourceOffset offset of the source string.
+ * @param sourceCount count of the source string.
+ * @param target the characters being searched for.
+ * @param fromIndex the index to begin searching from.
+ */
+ static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
+ String target, int fromIndex) {
+ final int targetOffset = 0;
+ final int targetCount = target.length();
+ /*
+ * Check arguments; return immediately where possible. For
+ * consistency, don't check for null str.
+ */
+ int rightIndex = sourceCount - targetCount;
+ if (fromIndex < 0) {
+ return -1;
+ }
+ if (fromIndex > rightIndex) {
+ fromIndex = rightIndex;
+ }
+ /* Empty string always matches. */
+ if (targetCount == 0) {
+ return fromIndex;
+ }
+
+ int strLastIndex = targetOffset + targetCount - 1;
+ char strLastChar = target.charAt(strLastIndex);
+ int min = sourceOffset + targetCount - 1;
+ int i = min + fromIndex;
+
+ startSearchForLastChar:
+ while (true) {
+ while (i >= min && source[i] != strLastChar) {
+ i--;
+ }
+ if (i < min) {
+ return -1;
+ }
+ int j = i - 1;
+ int start = j - (targetCount - 1);
+ int k = strLastIndex - 1;
+
+ while (j > start) {
+ if (source[j--] != target.charAt(k--)) {
+ i--;
+ continue startSearchForLastChar;
+ }
+ }
+ return start - sourceOffset + 1;
+ }
+ }
+
/**
* Code shared by String and StringBuffer to do searches. The
* source is the character array being searched, and the target
@@ -1609,7 +1732,7 @@ final class StringHelper
int min = sourceOffset + targetCount - 1;
int i = min + fromIndex;
- startSearchForLastChar:
+ startSearchForLastChar:
while (true) {
while (i >= min && source[i] != strLastChar) {
i--;
@@ -1632,10 +1755,10 @@ final class StringHelper
}
/**
- * Returns a new string that is a substring of this string. The
- * substring begins at the specified <code>beginIndex</code> and
- * extends to the character at index <code>endIndex - 1</code>.
- * Thus the length of the substring is <code>endIndex-beginIndex</code>.
+ * Returns a string that is a substring of this string. The
+ * substring begins at the specified {@code beginIndex} and
+ * extends to the character at index {@code endIndex - 1}.
+ * Thus the length of the substring is {@code endIndex-beginIndex}.
* <p>
* Examples:
* <blockquote><pre>
@@ -1647,11 +1770,11 @@ final class StringHelper
* @param endIndex the ending index, exclusive.
* @return the specified substring.
* @exception IndexOutOfBoundsException if the
- * <code>beginIndex</code> is negative, or
- * <code>endIndex</code> is larger than the length of
- * this <code>String</code> object, or
- * <code>beginIndex</code> is larger than
- * <code>endIndex</code>.
+ * {@code beginIndex} is negative, or
+ * {@code endIndex} is larger than the length of
+ * this {@code String} object, or
+ * {@code beginIndex} is larger than
+ * {@code endIndex}.
*/
static String substring(cli.System.String _this, int beginIndex, int endIndex) {
if (beginIndex < 0) {
@@ -1671,11 +1794,11 @@ final class StringHelper
/**
* Concatenates the specified string to the end of this string.
* <p>
- * If the length of the argument string is <code>0</code>, then this
- * <code>String</code> object is returned. Otherwise, a new
- * <code>String</code> object is created, representing a character
+ * If the length of the argument string is {@code 0}, then this
+ * {@code String} object is returned. Otherwise, a
+ * {@code String} object is returned that represents a character
* sequence that is the concatenation of the character sequence
- * represented by this <code>String</code> object and the character
+ * represented by this {@code String} object and the character
* sequence represented by the argument string.<p>
* Examples:
* <blockquote><pre>
@@ -1683,8 +1806,8 @@ final class StringHelper
* "to".concat("get").concat("her") returns "together"
* </pre></blockquote>
*
- * @param str the <code>String</code> that is concatenated to the end
- * of this <code>String</code>.
+ * @param str the {@code String} that is concatenated to the end
+ * of this {@code String}.
* @return a string that represents the concatenation of this object's
* characters followed by the string argument's characters.
*/
@@ -1697,17 +1820,17 @@ final class StringHelper
}
/**
- * Returns a new string resulting from replacing all occurrences of
- * <code>oldChar</code> in this string with <code>newChar</code>.
+ * Returns a string resulting from replacing all occurrences of
+ * {@code oldChar} in this string with {@code newChar}.
* <p>
- * If the character <code>oldChar</code> does not occur in the
- * character sequence represented by this <code>String</code> object,
- * then a reference to this <code>String</code> object is returned.
- * Otherwise, a new <code>String</code> object is created that
+ * If the character {@code oldChar} does not occur in the
+ * character sequence represented by this {@code String} object,
+ * then a reference to this {@code String} object is returned.
+ * Otherwise, a {@code String} object is returned that
* represents a character sequence identical to the character sequence
- * represented by this <code>String</code> object, except that every
- * occurrence of <code>oldChar</code> is replaced by an occurrence
- * of <code>newChar</code>.
+ * represented by this {@code String} object, except that every
+ * occurrence of {@code oldChar} is replaced by an occurrence
+ * of {@code newChar}.
* <p>
* Examples:
* <blockquote><pre>
@@ -1723,7 +1846,7 @@ final class StringHelper
* @param oldChar the old character.
* @param newChar the new character.
* @return a string derived from this string by replacing every
- * occurrence of <code>oldChar</code> with <code>newChar</code>.
+ * occurrence of {@code oldChar} with {@code newChar}.
*/
static String replace(String _this, char oldChar, char newChar) {
if (oldChar != newChar) {
@@ -1756,8 +1879,7 @@ final class StringHelper
* sequence of char values.
*
* @param s the sequence to search for
- * @return true if this string contains <code>s</code>, false otherwise
- * @throws NullPointerException if <code>s</code> is <code>null</code>
+ * @return true if this string contains {@code s}, false otherwise
* @since 1.5
*/
static boolean contains(String _this, CharSequence s) {
@@ -1774,8 +1896,6 @@ final class StringHelper
* @param target The sequence of char values to be replaced
* @param replacement The replacement sequence of char values
* @return The resulting string
- * @throws NullPointerException if <code>target</code> or
- * <code>replacement</code> is <code>null</code>.
* @since 1.5
*/
static String replace(String _this, CharSequence target, CharSequence replacement) {
@@ -1794,7 +1914,12 @@ final class StringHelper
* expression does not match any part of the input then the resulting array
* has just one element, namely this string.
*
- * <p> The <tt>limit</tt> parameter controls the number of times the
+ * <p> When there is a positive-width match at the beginning of this
+ * string then an empty leading substring is included at the beginning
+ * of the resulting array. A zero-width match at the beginning however
+ * never produces such empty leading substring.
+ *
+ * <p> The {@code limit} parameter controls the number of times the
* pattern is applied and therefore affects the length of the resulting
* array. If the limit <i>n</i> is greater than zero then the pattern
* will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's
@@ -1805,7 +1930,7 @@ final class StringHelper
* the pattern will be applied as many times as possible, the array can
* have any length, and trailing empty strings will be discarded.
*
- * <p> The string <tt>"boo:and:foo"</tt>, for example, yields the
+ * <p> The string {@code "boo:and:foo"}, for example, yields the
* following results with these parameters:
*
* <blockquote><table cellpadding=1 cellspacing=0 summary="Split example showing regex, limit, and result">
@@ -1816,33 +1941,34 @@ final class StringHelper
* </tr>
* <tr><td align=center>:</td>
* <td align=center>2</td>
- * <td><tt>{ "boo", "and:foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and:foo" }}</td></tr>
* <tr><td align=center>:</td>
* <td align=center>5</td>
- * <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and", "foo" }}</td></tr>
* <tr><td align=center>:</td>
* <td align=center>-2</td>
- * <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
+ * <td>{@code { "boo", "and", "foo" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>5</td>
- * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>-2</td>
- * <td><tt>{ "b", "", ":and:f", "", "" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f", "", "" }}</td></tr>
* <tr><td align=center>o</td>
* <td align=center>0</td>
- * <td><tt>{ "b", "", ":and:f" }</tt></td></tr>
+ * <td>{@code { "b", "", ":and:f" }}</td></tr>
* </table></blockquote>
*
* <p> An invocation of this method of the form
- * <i>str.</i><tt>split(</tt><i>regex</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+ * <i>str.</i>{@code split(}<i>regex</i>{@code ,}&nbsp;<i>n</i>{@code )}
* yields the same result as the expression
*
* <blockquote>
- * {@link java.util.regex.Pattern}.{@link java.util.regex.Pattern#compile
- * compile}<tt>(</tt><i>regex</i><tt>)</tt>.{@link
- * java.util.regex.Pattern#split(java.lang.CharSequence,int)
- * split}<tt>(</tt><i>str</i><tt>,</tt>&nbsp;<i>n</i><tt>)</tt>
+ * <code>
+ * {@link java.util.regex.Pattern}.{@link
+ * java.util.regex.Pattern#compile compile}(<i>regex</i>).{@link
+ * java.util.regex.Pattern#split(java.lang.CharSequence,int) split}(<i>str</i>,&nbsp;<i>n</i>)
+ * </code>
* </blockquote>
*
*
@@ -1906,9 +2032,11 @@ final class StringHelper
// Construct result
int resultSize = list.size();
- if (limit == 0)
- while (resultSize > 0 && list.get(resultSize - 1).length() == 0)
+ if (limit == 0) {
+ while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
resultSize--;
+ }
+ }
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
@@ -1916,11 +2044,95 @@ final class StringHelper
}
/**
- * Converts all of the characters in this <code>String</code> to lower
- * case using the rules of the given <code>Locale</code>. Case mapping is based
+ * Returns a new String composed of copies of the
+ * {@code CharSequence elements} joined together with a copy of
+ * the specified {@code delimiter}.
+ *
+ * <blockquote>For example,
+ * <pre>{@code
+ * String message = String.join("-", "Java", "is", "cool");
+ * // message returned is: "Java-is-cool"
+ * }</pre></blockquote>
+ *
+ * Note that if an element is null, then {@code "null"} is added.
+ *
+ * @param delimiter the delimiter that separates each element
+ * @param elements the elements to join together.
+ *
+ * @return a new {@code String} that is composed of the {@code elements}
+ * separated by the {@code delimiter}
+ *
+ * @throws NullPointerException If {@code delimiter} or {@code elements}
+ * is {@code null}
+ *
+ * @see java.util.StringJoiner
+ * @since 1.8
+ */
+ public static String join(CharSequence delimiter, CharSequence... elements) {
+ Objects.requireNonNull(delimiter);
+ Objects.requireNonNull(elements);
+ // Number of elements not likely worth Arrays.stream overhead.
+ StringJoiner joiner = new StringJoiner(delimiter);
+ for (CharSequence cs: elements) {
+ joiner.add(cs);
+ }
+ return joiner.toString();
+ }
+
+ /**
+ * Returns a new {@code String} composed of copies of the
+ * {@code CharSequence elements} joined together with a copy of the
+ * specified {@code delimiter}.
+ *
+ * <blockquote>For example,
+ * <pre>{@code
+ * List<String> strings = new LinkedList<>();
+ * strings.add("Java");strings.add("is");
+ * strings.add("cool");
+ * String message = String.join(" ", strings);
+ * //message returned is: "Java is cool"
+ *
+ * Set<String> strings = new LinkedHashSet<>();
+ * strings.add("Java"); strings.add("is");
+ * strings.add("very"); strings.add("cool");
+ * String message = String.join("-", strings);
+ * //message returned is: "Java-is-very-cool"
+ * }</pre></blockquote>
+ *
+ * Note that if an individual element is {@code null}, then {@code "null"} is added.
+ *
+ * @param delimiter a sequence of characters that is used to separate each
+ * of the {@code elements} in the resulting {@code String}
+ * @param elements an {@code Iterable} that will have its {@code elements}
+ * joined together.
+ *
+ * @return a new {@code String} that is composed from the {@code elements}
+ * argument
+ *
+ * @throws NullPointerException If {@code delimiter} or {@code elements}
+ * is {@code null}
+ *
+ * @see #join(CharSequence,CharSequence...)
+ * @see java.util.StringJoiner
+ * @since 1.8
+ */
+ public static String join(CharSequence delimiter,
+ Iterable<? extends CharSequence> elements) {
+ Objects.requireNonNull(delimiter);
+ Objects.requireNonNull(elements);
+ StringJoiner joiner = new StringJoiner(delimiter);
+ for (CharSequence cs: elements) {
+ joiner.add(cs);
+ }
+ return joiner.toString();
+ }
+
+ /**
+ * Converts all of the characters in this {@code String} to lower
+ * case using the rules of the given {@code Locale}. Case mapping is based
* on the Unicode Standard version specified by the {@link java.lang.Character Character}
* class. Since case mappings are not always 1:1 char mappings, the resulting
- * <code>String</code> may be a different length than the original <code>String</code>.
+ * {@code String} may be a different length than the original {@code String}.
* <p>
* Examples of lowercase mappings are in the following table:
* <table border="1" summary="Lowercase mapping examples showing language code of locale, upper case, lower case, and description">
@@ -1961,7 +2173,7 @@ final class StringHelper
* </table>
*
* @param locale use the case transformation rules for this locale
- * @return the <code>String</code>, converted to lowercase.
+ * @return the {@code String}, converted to lowercase.
* @see java.lang.String#toLowerCase()
* @see java.lang.String#toUpperCase()
* @see java.lang.String#toUpperCase(Locale)
@@ -2019,23 +2231,18 @@ final class StringHelper
} else {
srcCount = 1;
}
- if (localeDependent || srcChar == '\u03A3') { // GREEK CAPITAL LETTER SIGMA
+ if (localeDependent ||
+ srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
+ srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(_this, i, locale);
- } else if (srcChar == '\u0130') { // LATIN CAPITAL LETTER I DOT
- lowerChar = Character.ERROR;
} else {
lowerChar = Character.toLowerCase(srcChar);
}
if ((lowerChar == Character.ERROR)
|| (lowerChar >= Character.MIN_SUPPLEMENTARY_CODE_POINT)) {
if (lowerChar == Character.ERROR) {
- if (!localeDependent && srcChar == '\u0130') {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, Locale.ENGLISH);
- } else {
- lowerCharArray =
- ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, locale);
- }
+ lowerCharArray =
+ ConditionalSpecialCasing.toLowerCaseCharArray(_this, i, locale);
} else if (srcCount == 2) {
resultOffset += Character.toChars(lowerChar, result, i + resultOffset) - srcCount;
continue;
@@ -2062,22 +2269,22 @@ final class StringHelper
}
/**
- * Converts all of the characters in this <code>String</code> to lower
+ * Converts all of the characters in this {@code String} to lower
* case using the rules of the default locale. This is equivalent to calling
- * <code>toLowerCase(Locale.getDefault())</code>.
+ * {@code toLowerCase(Locale.getDefault())}.
* <p>
* <b>Note:</b> This method is locale sensitive, and may produce unexpected
* results if used for strings that are intended to be interpreted locale
* independently.
* Examples are programming language identifiers, protocol keys, and HTML
* tags.
- * For instance, <code>"TITLE".toLowerCase()</code> in a Turkish locale
- * returns <code>"t\u005Cu0131tle"</code>, where '\u005Cu0131' is the
+ * For instance, {@code "TITLE".toLowerCase()} in a Turkish locale
+ * returns {@code "t\u005Cu0131tle"}, where '\u005Cu0131' is the
* LATIN SMALL LETTER DOTLESS I character.
* To obtain correct results for locale insensitive strings, use
- * <code>toLowerCase(Locale.ENGLISH)</code>.
+ * {@code toLowerCase(Locale.ROOT)}.
* <p>
- * @return the <code>String</code>, converted to lowercase.
+ * @return the {@code String}, converted to lowercase.
* @see java.lang.String#toLowerCase(Locale)
*/
static String toLowerCase(String _this) {
@@ -2085,14 +2292,14 @@ final class StringHelper
}
/**
- * Converts all of the characters in this <code>String</code> to upper
- * case using the rules of the given <code>Locale</code>. Case mapping is based
+ * Converts all of the characters in this {@code String} to upper
+ * case using the rules of the given {@code Locale}. Case mapping is based
* on the Unicode Standard version specified by the {@link java.lang.Character Character}
* class. Since case mappings are not always 1:1 char mappings, the resulting
- * <code>String</code> may be a different length than the original <code>String</code>.
+ * {@code String} may be a different length than the original {@code String}.
* <p>
* Examples of locale-sensitive and 1:M case mappings are in the following table.
- * <p>
+ *
* <table border="1" summary="Examples of locale-sensitive and 1:M case mappings. Shows Language code of locale, lower case, upper case, and description.">
* <tr>
* <th>Language Code of Locale</th>
@@ -2126,7 +2333,7 @@ final class StringHelper
* </tr>
* </table>
* @param locale use the case transformation rules for this locale
- * @return the <code>String</code>, converted to uppercase.
+ * @return the {@code String}, converted to uppercase.
* @see java.lang.String#toUpperCase()
* @see java.lang.String#toLowerCase()
* @see java.lang.String#toLowerCase(Locale)
@@ -2142,7 +2349,7 @@ final class StringHelper
/* Now check if there are any characters that need to be changed. */
scan: {
- for (firstLower = 0 ; firstLower < len; ) {
+ for (firstLower = 0 ; firstLower < len; ) {
int c = (int)_this.charAt(firstLower);
int srcCount;
if ((c >= Character.MIN_HIGH_SURROGATE)
@@ -2162,9 +2369,9 @@ final class StringHelper
return _this;
}
+ /* result may grow, so i+resultOffset is the write location in result */
+ int resultOffset = 0;
char[] result = new char[len]; /* may grow */
- int resultOffset = 0; /* result may grow, so i+resultOffset
- * is the write location in result */
/* Just copy the first few upperCase characters. */
_this.getChars(0, firstLower, result, 0);
@@ -2225,22 +2432,22 @@ final class StringHelper
}
/**
- * Converts all of the characters in this <code>String</code> to upper
+ * Converts all of the characters in this {@code String} to upper
* case using the rules of the default locale. This method is equivalent to
- * <code>toUpperCase(Locale.getDefault())</code>.
+ * {@code toUpperCase(Locale.getDefault())}.
* <p>
* <b>Note:</b> This method is locale sensitive, and may produce unexpected
* results if used for strings that are intended to be interpreted locale
* independently.
* Examples are programming language identifiers, protocol keys, and HTML
* tags.
- * For instance, <code>"title".toUpperCase()</code> in a Turkish locale
- * returns <code>"T\u005Cu0130TLE"</code>, where '\u005Cu0130' is the
+ * For instance, {@code "title".toUpperCase()} in a Turkish locale
+ * returns {@code "T\u005Cu0130TLE"}, where '\u005Cu0130' is the
* LATIN CAPITAL LETTER I WITH DOT ABOVE character.
* To obtain correct results for locale insensitive strings, use
- * <code>toUpperCase(Locale.ENGLISH)</code>.
+ * {@code toUpperCase(Locale.ROOT)}.
* <p>
- * @return the <code>String</code>, converted to uppercase.
+ * @return the {@code String}, converted to uppercase.
* @see java.lang.String#toUpperCase(Locale)
*/
static String toUpperCase(String _this) {
@@ -2248,33 +2455,33 @@ final class StringHelper
}
/**
- * Returns a copy of the string, with leading and trailing whitespace
- * omitted.
+ * Returns a string whose value is this string, with any leading and trailing
+ * whitespace removed.
* <p>
- * If this <code>String</code> object represents an empty character
+ * If this {@code String} object represents an empty character
* sequence, or the first and last characters of character sequence
- * represented by this <code>String</code> object both have codes
- * greater than <code>'&#92;u0020'</code> (the space character), then a
- * reference to this <code>String</code> object is returned.
+ * represented by this {@code String} object both have codes
+ * greater than {@code '\u005Cu0020'} (the space character), then a
+ * reference to this {@code String} object is returned.
* <p>
* Otherwise, if there is no character with a code greater than
- * <code>'&#92;u0020'</code> in the string, then a new
- * <code>String</code> object representing an empty string is created
- * and returned.
+ * {@code '\u005Cu0020'} in the string, then a
+ * {@code String} object representing an empty string is
+ * returned.
* <p>
* Otherwise, let <i>k</i> be the index of the first character in the
- * string whose code is greater than <code>'&#92;u0020'</code>, and let
+ * string whose code is greater than {@code '\u005Cu0020'}, and let
* <i>m</i> be the index of the last character in the string whose code
- * is greater than <code>'&#92;u0020'</code>. A new <code>String</code>
- * object is created, representing the substring of this string that
+ * is greater than {@code '\u005Cu0020'}. A {@code String}
+ * object is returned, representing the substring of this string that
* begins with the character at index <i>k</i> and ends with the
* character at index <i>m</i>-that is, the result of
- * <code>this.substring(<i>k</i>,&nbsp;<i>m</i>+1)</code>.
+ * {@code this.substring(k, m + 1)}.
* <p>
* This method may be used to trim whitespace (as defined above) from
* the beginning and end of a string.
*
- * @return A copy of this string with leading and trailing white
+ * @return A string whose value is this string, with any leading and trailing white
* space removed, or this string if it has no leading or
* trailing white space.
*/
@@ -2309,10 +2516,10 @@ final class StringHelper
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java&trade; Virtual Machine Specification</cite>.
* The behaviour on a
- * <tt>null</tt> argument depends on the <a
+ * {@code null} argument depends on the <a
* href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -2321,9 +2528,6 @@ final class StringHelper
* href="../util/Formatter.html#detail">Details</a> section of the
* formatter class specification.
*
- * @throws NullPointerException
- * If the <tt>format</tt> is <tt>null</tt>
- *
* @return A formatted string
*
* @see java.util.Formatter
@@ -2339,7 +2543,7 @@ final class StringHelper
*
* @param l
* The {@linkplain java.util.Locale locale} to apply during
- * formatting. If <tt>l</tt> is <tt>null</tt> then no localization
+ * formatting. If {@code l} is {@code null} then no localization
* is applied.
*
* @param format
@@ -2353,10 +2557,10 @@ final class StringHelper
* limited by the maximum dimension of a Java array as defined by
* <cite>The Java&trade; Virtual Machine Specification</cite>.
* The behaviour on a
- * <tt>null</tt> argument depends on the <a
- * href="../util/Formatter.html#syntax">conversion</a>.
+ * {@code null} argument depends on the
+ * <a href="../util/Formatter.html#syntax">conversion</a>.
*
- * @throws IllegalFormatException
+ * @throws java.util.IllegalFormatException
* If a format string contains an illegal syntax, a format
* specifier that is incompatible with the given arguments,
* insufficient arguments given the format string, or other
@@ -2365,9 +2569,6 @@ final class StringHelper
* href="../util/Formatter.html#detail">Details</a> section of the
* formatter class specification
*
- * @throws NullPointerException
- * If the <tt>format</tt> is <tt>null</tt>
- *
* @return A formatted string
*
* @see java.util.Formatter
@@ -2378,12 +2579,12 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>Object</code> argument.
+ * Returns the string representation of the {@code Object} argument.
*
- * @param obj an <code>Object</code>.
- * @return if the argument is <code>null</code>, then a string equal to
- * <code>"null"</code>; otherwise, the value of
- * <code>obj.toString()</code> is returned.
+ * @param obj an {@code Object}.
+ * @return if the argument is {@code null}, then a string equal to
+ * {@code "null"}; otherwise, the value of
+ * {@code obj.toString()} is returned.
* @see java.lang.Object#toString()
*/
public static String valueOf(Object obj) {
@@ -2391,14 +2592,14 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>char</code> array
+ * Returns the string representation of the {@code char} array
* argument. The contents of the character array are copied; subsequent
- * modification of the character array does not affect the newly
- * created string.
+ * modification of the character array does not affect the returned
+ * string.
*
- * @param data a <code>char</code> array.
- * @return a newly allocated string representing the same sequence of
- * characters contained in the character array argument.
+ * @param data the character array.
+ * @return a {@code String} that contains the characters of the
+ * character array.
*/
public static String valueOf(char data[]) {
return new String(data);
@@ -2406,50 +2607,50 @@ final class StringHelper
/**
* Returns the string representation of a specific subarray of the
- * <code>char</code> array argument.
+ * {@code char} array argument.
* <p>
- * The <code>offset</code> argument is the index of the first
- * character of the subarray. The <code>count</code> argument
+ * The {@code offset} argument is the index of the first
+ * character of the subarray. The {@code count} argument
* specifies the length of the subarray. The contents of the subarray
* are copied; subsequent modification of the character array does not
- * affect the newly created string.
+ * affect the returned string.
*
* @param data the character array.
- * @param offset the initial offset into the value of the
- * <code>String</code>.
- * @param count the length of the value of the <code>String</code>.
- * @return a string representing the sequence of characters contained
- * in the subarray of the character array argument.
- * @exception IndexOutOfBoundsException if <code>offset</code> is
- * negative, or <code>count</code> is negative, or
- * <code>offset+count</code> is larger than
- * <code>data.length</code>.
+ * @param offset initial offset of the subarray.
+ * @param count length of the subarray.
+ * @return a {@code String} that contains the characters of the
+ * specified subarray of the character array.
+ * @exception IndexOutOfBoundsException if {@code offset} is
+ * negative, or {@code count} is negative, or
+ * {@code offset+count} is larger than
+ * {@code data.length}.
*/
public static String valueOf(char data[], int offset, int count) {
return new String(data, offset, count);
}
/**
- * Returns a String that represents the character sequence in the
- * array specified.
+ * Equivalent to {@link #valueOf(char[], int, int)}.
*
* @param data the character array.
* @param offset initial offset of the subarray.
* @param count length of the subarray.
- * @return a <code>String</code> that contains the characters of the
+ * @return a {@code String} that contains the characters of the
* specified subarray of the character array.
+ * @exception IndexOutOfBoundsException if {@code offset} is
+ * negative, or {@code count} is negative, or
+ * {@code offset+count} is larger than
+ * {@code data.length}.
*/
public static String copyValueOf(char data[], int offset, int count) {
- // All public String constructors now copy the data.
return new String(data, offset, count);
}
/**
- * Returns a String that represents the character sequence in the
- * array specified.
+ * Equivalent to {@link #valueOf(char[])}.
*
* @param data the character array.
- * @return a <code>String</code> that contains the characters of the
+ * @return a {@code String} that contains the characters of the
* character array.
*/
public static String copyValueOf(char data[]) {
@@ -2457,25 +2658,25 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>boolean</code> argument.
+ * Returns the string representation of the {@code boolean} argument.
*
- * @param b a <code>boolean</code>.
- * @return if the argument is <code>true</code>, a string equal to
- * <code>"true"</code> is returned; otherwise, a string equal to
- * <code>"false"</code> is returned.
+ * @param b a {@code boolean}.
+ * @return if the argument is {@code true}, a string equal to
+ * {@code "true"} is returned; otherwise, a string equal to
+ * {@code "false"} is returned.
*/
public static String valueOf(boolean b) {
return b ? "true" : "false";
}
/**
- * Returns the string representation of the <code>int</code> argument.
+ * Returns the string representation of the {@code int} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Integer.toString</code> method of one argument.
+ * {@code Integer.toString} method of one argument.
*
- * @param i an <code>int</code>.
- * @return a string representation of the <code>int</code> argument.
+ * @param i an {@code int}.
+ * @return a string representation of the {@code int} argument.
* @see java.lang.Integer#toString(int, int)
*/
public static String valueOf(int i) {
@@ -2483,13 +2684,13 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>long</code> argument.
+ * Returns the string representation of the {@code long} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Long.toString</code> method of one argument.
+ * {@code Long.toString} method of one argument.
*
- * @param l a <code>long</code>.
- * @return a string representation of the <code>long</code> argument.
+ * @param l a {@code long}.
+ * @return a string representation of the {@code long} argument.
* @see java.lang.Long#toString(long)
*/
public static String valueOf(long l) {
@@ -2497,13 +2698,13 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>float</code> argument.
+ * Returns the string representation of the {@code float} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Float.toString</code> method of one argument.
+ * {@code Float.toString} method of one argument.
*
- * @param f a <code>float</code>.
- * @return a string representation of the <code>float</code> argument.
+ * @param f a {@code float}.
+ * @return a string representation of the {@code float} argument.
* @see java.lang.Float#toString(float)
*/
public static String valueOf(float f) {
@@ -2511,82 +2712,16 @@ final class StringHelper
}
/**
- * Returns the string representation of the <code>double</code> argument.
+ * Returns the string representation of the {@code double} argument.
* <p>
* The representation is exactly the one returned by the
- * <code>Double.toString</code> method of one argument.
+ * {@code Double.toString} method of one argument.
*
- * @param d a <code>double</code>.
- * @return a string representation of the <code>double</code> argument.
+ * @param d a {@code double}.
+ * @return a string representation of the {@code double} argument.
* @see java.lang.Double#toString(double)
*/
public static String valueOf(double d) {
return Double.toString(d);
}
-
- /**
- * Seed value used for each alternative hash calculated.
- */
- private static final int HASHING_SEED;
-
- static {
- long nanos = System.nanoTime();
- long now = System.currentTimeMillis();
- int SEED_MATERIAL[] = {
- System.identityHashCode(String.class),
- System.identityHashCode(System.class),
- (int) (nanos >>> 32),
- (int) nanos,
- (int) (now >>> 32),
- (int) now,
- (int) (System.nanoTime() >>> 2)
- };
-
- // Use murmur3 to scramble the seeding material.
- // Inline implementation to avoid loading classes
- int h1 = 0;
-
- // body
- for (int k1 : SEED_MATERIAL) {
- k1 *= 0xcc9e2d51;
- k1 = (k1 << 15) | (k1 >>> 17);
- k1 *= 0x1b873593;
-
- h1 ^= k1;
- h1 = (h1 << 13) | (h1 >>> 19);
- h1 = h1 * 5 + 0xe6546b64;
- }
-
- // tail (always empty, as body is always 32-bit chunks)
-
- // finalization
-
- h1 ^= SEED_MATERIAL.length * 4;
-
- // finalization mix force all bits of a hash block to avalanche
- h1 ^= h1 >>> 16;
- h1 *= 0x85ebca6b;
- h1 ^= h1 >>> 13;
- h1 *= 0xc2b2ae35;
- h1 ^= h1 >>> 16;
-
- HASHING_SEED = h1;
- }
-
- /**
- * Calculates a 32-bit hash value for this string.
- *
- * @return a 32-bit hash value for this string.
- */
- static int hash32(String _this) {
- // [IKVM] We don't bother with murmur32 and just use the .NET hash code
- // and hope that it is good enough. We xor with HASHING_SEED to avoid
- // returning predictable values (this does not help against DoS attacks,
- // but it will surface constant hash code dependencies).
- // If truly randomized string hashes are required (to protect against
- // DoS) the .NET 4.5 <UseRandomizedStringHashAlgorithm enabled="1" />
- // app.config setting can be used.
- return HASHING_SEED ^ ((cli.System.String)(Object)_this).GetHashCode();
- }
-
}
diff --git a/openjdk/java/lang/System.java b/openjdk/java/lang/System.java
index e74187b9..d0121b4e 100644
--- a/openjdk/java/lang/System.java
+++ b/openjdk/java/lang/System.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -25,24 +25,30 @@
package java.lang;
import java.io.*;
+import java.lang.reflect.Executable;
+import java.lang.annotation.Annotation;
+import java.security.AccessControlContext;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.StringTokenizer;
+import java.util.Map;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.AllPermission;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
+import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
+import sun.reflect.annotation.AnnotationType;
final class StdIO
{
private StdIO() { }
static InputStream in = new BufferedInputStream(new FileInputStream(FileDescriptor.in));
- static PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out), 128), true);
- static PrintStream err = new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.err), 128), true);
+ static PrintStream out = System.newPrintStream(new FileOutputStream(FileDescriptor.out), Props.props.getProperty("sun.stdout.encoding"));
+ static PrintStream err = System.newPrintStream(new FileOutputStream(FileDescriptor.err), Props.props.getProperty("sun.stderr.encoding"));
}
final class Props
@@ -597,7 +603,7 @@ public final class System {
* <tr><td><code>java.version</code></td>
* <td>Java Runtime Environment version</td></tr>
* <tr><td><code>java.vendor</code></td>
- * <td>Java Runtime Environment vendor</td></tr
+ * <td>Java Runtime Environment vendor</td></tr>
* <tr><td><code>java.vendor.url</code></td>
* <td>Java vendor URL</td></tr>
* <tr><td><code>java.home</code></td>
@@ -631,7 +637,10 @@ public final class System {
* <tr><td><code>java.compiler</code></td>
* <td>Name of JIT compiler to use</td></tr>
* <tr><td><code>java.ext.dirs</code></td>
- * <td>Path of extension directory or directories</td></tr>
+ * <td>Path of extension directory or directories
+ * <b>Deprecated.</b> <i>This property, and the mechanism
+ * which implements it, may be removed in a future
+ * release.</i> </td></tr>
* <tr><td><code>os.name</code></td>
* <td>Operating system name</td></tr>
* <tr><td><code>os.arch</code></td>
@@ -684,6 +693,9 @@ public final class System {
*
* <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
* Windows systems it returns {@code "\r\n"}.
+ *
+ * @return the system-dependent line separator string
+ * @since 1.7
*/
public static String lineSeparator() {
return Props.lineSeparator;
@@ -1081,13 +1093,25 @@ public final class System {
*/
@Deprecated
public static void runFinalizersOnExit(boolean value) {
- Runtime.getRuntime().runFinalizersOnExit(value);
+ Runtime.runFinalizersOnExit(value);
}
/**
- * Loads a code file with the specified filename from the local file
- * system as a dynamic library. The filename
- * argument must be a complete path name.
+ * Loads the native library specified by the filename argument. The filename
+ * argument must be an absolute path name.
+ *
+ * If the filename argument, when stripped of any platform-specific library
+ * prefix, path, and file extension, indicates a library whose name is,
+ * for example, L, and a native library called L is statically linked
+ * with the VM, then the JNI_OnLoad_L function exported by the library
+ * is invoked rather than attempting to load a dynamic library.
+ * A filename matching the argument does not have to exist in the
+ * file system.
+ * See the JNI Specification for more details.
+ *
+ * Otherwise, the filename argument is mapped to a native library image in
+ * an implementation-dependent manner.
+ *
* <p>
* The call <code>System.load(name)</code> is effectively equivalent
* to the call:
@@ -1099,7 +1123,10 @@ public final class System {
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
- * @exception UnsatisfiedLinkError if the file does not exist.
+ * @exception UnsatisfiedLinkError if either the filename is not an
+ * absolute path name, the native library is not statically
+ * linked with the VM, or the library cannot be mapped to
+ * a native library image by the host system.
* @exception NullPointerException if <code>filename</code> is
* <code>null</code>
* @see java.lang.Runtime#load(java.lang.String)
@@ -1111,9 +1138,16 @@ public final class System {
}
/**
- * Loads the system library specified by the <code>libname</code>
- * argument. The manner in which a library name is mapped to the
- * actual system library is system dependent.
+ * Loads the native library specified by the <code>libname</code>
+ * argument. The <code>libname</code> argument must not contain any platform
+ * specific prefix, file extension or path. If a native library
+ * called <code>libname</code> is statically linked with the VM, then the
+ * JNI_OnLoad_<code>libname</code> function exported by the library is invoked.
+ * See the JNI Specification for more details.
+ *
+ * Otherwise, the libname argument is loaded from a system library
+ * location and mapped to a native library image in an implementation-
+ * dependent manner.
* <p>
* The call <code>System.loadLibrary(name)</code> is effectively
* equivalent to the call
@@ -1125,7 +1159,10 @@ public final class System {
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
- * @exception UnsatisfiedLinkError if the library does not exist.
+ * @exception UnsatisfiedLinkError if either the libname argument
+ * contains a file path, the native library is not statically
+ * linked with the VM, or the library cannot be mapped to a
+ * native library image by the host system.
* @exception NullPointerException if <code>libname</code> is
* <code>null</code>
* @see java.lang.Runtime#loadLibrary(java.lang.String)
@@ -1160,9 +1197,16 @@ public final class System {
return "lib" + libname + ".so";
}
}
- /* returns the class of the caller. */
- static Class<?> getCallerClass() {
- // NOTE use of more generic Reflection.getCallerClass()
- return Reflection.getCallerClass(3);
+
+ /**
+ * Create PrintStream for stdout/err based on encoding.
+ */
+ /*private*/ static PrintStream newPrintStream(FileOutputStream fos, String enc) {
+ if (enc != null) {
+ try {
+ return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
+ } catch (UnsupportedEncodingException uee) {}
+ }
+ return new PrintStream(new BufferedOutputStream(fos, 128), true);
}
}
diff --git a/openjdk/java/lang/reflect/Constructor.java b/openjdk/java/lang/reflect/Constructor.java
index b13d30a5..9e01975d 100644
--- a/openjdk/java/lang/reflect/Constructor.java
+++ b/openjdk/java/lang/reflect/Constructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -28,15 +28,14 @@ package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection;
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.generics.repository.ConstructorRepository;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.scope.ConstructorScope;
import java.lang.annotation.Annotation;
-import java.util.Map;
-import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.AnnotationFormatError;
-import java.lang.reflect.Modifier;
/**
* {@code Constructor} provides information about, and access to, a single
@@ -58,11 +57,7 @@ import java.lang.reflect.Modifier;
* @author Kenneth Russell
* @author Nakul Saraiya
*/
-public final
- class Constructor<T> extends AccessibleObject implements
- GenericDeclaration,
- Member {
-
+public final class Constructor<T> extends Executable {
private Class<T> clazz;
private int slot;
private Class<?>[] parameterTypes;
@@ -81,7 +76,8 @@ public final
}
// Accessor for generic info repository
- private ConstructorRepository getGenericInfo() {
+ @Override
+ ConstructorRepository getGenericInfo() {
// lazily initialize repository if necessary
if (genericInfo == null) {
// create and cache generic info repository
@@ -96,9 +92,20 @@ public final
// For sharing of ConstructorAccessors. This branching structure
// is currently only two levels deep (i.e., one root Constructor
// and potentially many Constructor objects pointing to it.)
+ //
+ // If this branching structure would ever contain cycles, deadlocks can
+ // occur in annotation code.
private Constructor<T> root;
/**
+ * Used by Excecutable for annotation sharing.
+ */
+ @Override
+ Executable getRoot() {
+ return root;
+ }
+
+ /**
* Package-private constructor used by ReflectAccess to enable
* instantiation of these objects in Java code from the java.lang
* package via sun.reflect.LangReflectAccess.
@@ -110,8 +117,7 @@ public final
int slot,
String signature,
byte[] unused1,
- byte[] unused2)
- {
+ byte[] unused2) {
this.clazz = declaringClass;
this.parameterTypes = parameterTypes;
this.exceptionTypes = checkedExceptions;
@@ -133,22 +139,30 @@ public final
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
+ if (this.root != null)
+ throw new IllegalArgumentException("Can not copy a non-root Constructor");
+
Constructor<T> res = new Constructor<>(clazz,
- parameterTypes,
- exceptionTypes, modifiers, slot,
- signature,
- null,
- null);
+ parameterTypes,
+ exceptionTypes, modifiers, slot,
+ signature,
+ null,
+ null);
res.root = this;
// Might as well eagerly propagate this if already present
res.constructorAccessor = constructorAccessor;
return res;
}
+ @Override
+ boolean hasGenericInformation() {
+ return (getSignature() != null);
+ }
+
/**
- * Returns the {@code Class} object representing the class that declares
- * the constructor represented by this {@code Constructor} object.
+ * {@inheritDoc}
*/
+ @Override
public Class<T> getDeclaringClass() {
return clazz;
}
@@ -157,36 +171,26 @@ public final
* Returns the name of this constructor, as a string. This is
* the binary name of the constructor's declaring class.
*/
+ @Override
public String getName() {
return getDeclaringClass().getName();
}
/**
- * Returns the Java language modifiers for the constructor
- * represented by this {@code Constructor} object, as an integer. The
- * {@code Modifier} class should be used to decode the modifiers.
- *
- * @see Modifier
+ * {@inheritDoc}
*/
+ @Override
public int getModifiers() {
return modifiers;
}
/**
- * Returns an array of {@code TypeVariable} objects that represent the
- * type variables declared by the generic declaration represented by this
- * {@code GenericDeclaration} object, in declaration order. Returns an
- * array of length 0 if the underlying generic declaration declares no type
- * variables.
- *
- * @return an array of {@code TypeVariable} objects that represent
- * the type variables declared by this generic declaration
- * @throws GenericSignatureFormatError if the generic
- * signature of this generic declaration does not conform to
- * the format specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
* @since 1.5
*/
+ @Override
+ @SuppressWarnings({"rawtypes", "unchecked"})
public TypeVariable<Constructor<T>>[] getTypeParameters() {
if (getSignature() != null) {
return (TypeVariable<Constructor<T>>[])getGenericInfo().getTypeParameters();
@@ -196,98 +200,50 @@ public final
/**
- * Returns an array of {@code Class} objects that represent the formal
- * parameter types, in declaration order, of the constructor
- * represented by this {@code Constructor} object. Returns an array of
- * length 0 if the underlying constructor takes no parameters.
- *
- * @return the parameter types for the constructor this object
- * represents
+ * {@inheritDoc}
*/
+ @Override
public Class<?>[] getParameterTypes() {
- return (Class<?>[]) parameterTypes.clone();
+ return parameterTypes.clone();
}
+ /**
+ * {@inheritDoc}
+ */
+ public int getParameterCount() { return parameterTypes.length; }
/**
- * Returns an array of {@code Type} objects that represent the formal
- * parameter types, in declaration order, of the method represented by
- * this {@code Constructor} object. Returns an array of length 0 if the
- * underlying method takes no parameters.
- *
- * <p>If a formal parameter type is a parameterized type,
- * the {@code Type} object returned for it must accurately reflect
- * the actual type parameters used in the source code.
- *
- * <p>If a formal parameter type is a type variable or a parameterized
- * type, it is created. Otherwise, it is resolved.
- *
- * @return an array of {@code Type}s that represent the formal
- * parameter types of the underlying method, in declaration order
- * @throws GenericSignatureFormatError
- * if the generic method signature does not conform to the format
- * specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
- * @throws TypeNotPresentException if any of the parameter
- * types of the underlying method refers to a non-existent type
- * declaration
- * @throws MalformedParameterizedTypeException if any of
- * the underlying method's parameter types refer to a parameterized
- * type that cannot be instantiated for any reason
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
+ * @throws TypeNotPresentException {@inheritDoc}
+ * @throws MalformedParameterizedTypeException {@inheritDoc}
* @since 1.5
*/
+ @Override
public Type[] getGenericParameterTypes() {
- if (getSignature() != null)
- return getGenericInfo().getParameterTypes();
- else
- return getParameterTypes();
+ return super.getGenericParameterTypes();
}
-
/**
- * Returns an array of {@code Class} objects that represent the types
- * of exceptions declared to be thrown by the underlying constructor
- * represented by this {@code Constructor} object. Returns an array of
- * length 0 if the constructor declares no exceptions in its {@code throws} clause.
- *
- * @return the exception types declared as being thrown by the
- * constructor this object represents
+ * {@inheritDoc}
*/
+ @Override
public Class<?>[] getExceptionTypes() {
- return (Class<?>[])exceptionTypes.clone();
+ return exceptionTypes.clone();
}
/**
- * Returns an array of {@code Type} objects that represent the
- * exceptions declared to be thrown by this {@code Constructor} object.
- * Returns an array of length 0 if the underlying method declares
- * no exceptions in its {@code throws} clause.
- *
- * <p>If an exception type is a type variable or a parameterized
- * type, it is created. Otherwise, it is resolved.
- *
- * @return an array of Types that represent the exception types
- * thrown by the underlying method
- * @throws GenericSignatureFormatError
- * if the generic method signature does not conform to the format
- * specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
- * @throws TypeNotPresentException if the underlying method's
- * {@code throws} clause refers to a non-existent type declaration
- * @throws MalformedParameterizedTypeException if
- * the underlying method's {@code throws} clause refers to a
- * parameterized type that cannot be instantiated for any reason
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
+ * @throws TypeNotPresentException {@inheritDoc}
+ * @throws MalformedParameterizedTypeException {@inheritDoc}
* @since 1.5
*/
- public Type[] getGenericExceptionTypes() {
- Type[] result;
- if (getSignature() != null &&
- ( (result = getGenericInfo().getExceptionTypes()).length > 0 ))
- return result;
- else
- return getExceptionTypes();
- }
+ @Override
+ public Type[] getGenericExceptionTypes() {
+ return super.getGenericExceptionTypes();
+ }
/**
* Compares this {@code Constructor} against the specified object.
@@ -299,16 +255,7 @@ public final
if (obj != null && obj instanceof Constructor) {
Constructor<?> other = (Constructor<?>)obj;
if (getDeclaringClass() == other.getDeclaringClass()) {
- /* Avoid unnecessary cloning */
- Class<?>[] params1 = parameterTypes;
- Class<?>[] params2 = other.parameterTypes;
- if (params1.length == params2.length) {
- for (int i = 0; i < params1.length; i++) {
- if (params1[i] != params2[i])
- return false;
- }
- return true;
- }
+ return equalParamTypes(parameterTypes, other.parameterTypes);
}
}
return false;
@@ -337,36 +284,20 @@ public final
* modifiers {@code public}, {@code protected} or
* {@code private}. Only one of these may appear, or none if the
* constructor has default (package) access.
+ *
+ * @return a string describing this {@code Constructor}
+ * @jls 8.8.3. Constructor Modifiers
*/
public String toString() {
- try {
- StringBuffer sb = new StringBuffer();
- int mod = getModifiers() & Modifier.constructorModifiers();
- if (mod != 0) {
- sb.append(Modifier.toString(mod) + " ");
- }
- sb.append(Field.getTypeName(getDeclaringClass()));
- sb.append("(");
- Class<?>[] params = parameterTypes; // avoid clone
- for (int j = 0; j < params.length; j++) {
- sb.append(Field.getTypeName(params[j]));
- if (j < (params.length - 1))
- sb.append(",");
- }
- sb.append(")");
- Class<?>[] exceptions = exceptionTypes; // avoid clone
- if (exceptions.length > 0) {
- sb.append(" throws ");
- for (int k = 0; k < exceptions.length; k++) {
- sb.append(exceptions[k].getName());
- if (k < (exceptions.length - 1))
- sb.append(",");
- }
- }
- return sb.toString();
- } catch (Exception e) {
- return "<" + e + ">";
- }
+ return sharedToString(Modifier.constructorModifiers(),
+ false,
+ parameterTypes,
+ exceptionTypes);
+ }
+
+ @Override
+ void specificToStringHeader(StringBuilder sb) {
+ sb.append(getDeclaringClass().getTypeName());
}
/**
@@ -401,57 +332,16 @@ public final
* include type parameters
*
* @since 1.5
+ * @jls 8.8.3. Constructor Modifiers
*/
+ @Override
public String toGenericString() {
- try {
- StringBuilder sb = new StringBuilder();
- int mod = getModifiers() & Modifier.constructorModifiers();
- if (mod != 0) {
- sb.append(Modifier.toString(mod) + " ");
- }
- TypeVariable<?>[] typeparms = getTypeParameters();
- if (typeparms.length > 0) {
- boolean first = true;
- sb.append("<");
- for(TypeVariable<?> typeparm: typeparms) {
- if (!first)
- sb.append(",");
- // Class objects can't occur here; no need to test
- // and call Class.getName().
- sb.append(typeparm.toString());
- first = false;
- }
- sb.append("> ");
- }
- sb.append(Field.getTypeName(getDeclaringClass()));
- sb.append("(");
- Type[] params = getGenericParameterTypes();
- for (int j = 0; j < params.length; j++) {
- String param = (params[j] instanceof Class<?>)?
- Field.getTypeName((Class<?>)params[j]):
- (params[j].toString());
- if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
- param = param.replaceFirst("\\[\\]$", "...");
- sb.append(param);
- if (j < (params.length - 1))
- sb.append(",");
- }
- sb.append(")");
- Type[] exceptions = getGenericExceptionTypes();
- if (exceptions.length > 0) {
- sb.append(" throws ");
- for (int k = 0; k < exceptions.length; k++) {
- sb.append((exceptions[k] instanceof Class)?
- ((Class<?>)exceptions[k]).getName():
- exceptions[k].toString());
- if (k < (exceptions.length - 1))
- sb.append(",");
- }
- }
- return sb.toString();
- } catch (Exception e) {
- return "<" + e + ">";
- }
+ return sharedToGenericString(Modifier.constructorModifiers(), false);
+ }
+
+ @Override
+ void specificToGenericStringHeader(StringBuilder sb) {
+ specificToStringHeader(sb);
}
/**
@@ -519,33 +409,28 @@ public final
if (ca == null) {
ca = acquireConstructorAccessor();
}
- return (T) ca.newInstance(initargs);
+ @SuppressWarnings("unchecked")
+ T inst = (T) ca.newInstance(initargs);
+ return inst;
}
/**
- * Returns {@code true} if this constructor was declared to take
- * a variable number of arguments; returns {@code false}
- * otherwise.
- *
- * @return {@code true} if an only if this constructor was declared to
- * take a variable number of arguments.
+ * {@inheritDoc}
* @since 1.5
*/
+ @Override
public boolean isVarArgs() {
- return (getModifiers() & Modifier.VARARGS) != 0;
+ return super.isVarArgs();
}
/**
- * Returns {@code true} if this constructor is a synthetic
- * constructor; returns {@code false} otherwise.
- *
- * @return true if and only if this constructor is a synthetic
- * constructor as defined by
- * <cite>The Java&trade; Language Specification</cite>.
+ * {@inheritDoc}
+ * @jls 13.1 The Form of a Binary
* @since 1.5
*/
+ @Override
public boolean isSynthetic() {
- return Modifier.isSynthetic(getModifiers());
+ return super.isSynthetic();
}
// NOTE that there is no synchronization used here. It is correct
@@ -589,9 +474,9 @@ public final
return slot;
}
- String getSignature() {
- return signature;
- }
+ String getSignature() {
+ return signature;
+ }
byte[] getRawAnnotations() {
return null;
@@ -601,74 +486,77 @@ public final
return null;
}
+
/**
- * @throws NullPointerException {@inheritDoc}
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
* @since 1.5
*/
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
-
- return (T) declaredAnnotations().get(annotationClass);
+ return super.getAnnotation(annotationClass);
}
- private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0];
-
/**
+ * {@inheritDoc}
* @since 1.5
*/
public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
- }
-
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
-
- private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
- if (declaredAnnotations == null) {
- declaredAnnotations = Method.getDeclaredAnnotationsImpl(this);
- }
- return declaredAnnotations;
+ return super.getDeclaredAnnotations();
}
/**
- * Returns an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by
- * this {@code Constructor} object. (Returns an array of length zero if the
- * underlying method is parameterless. If the method has one or more
- * parameters, a nested array of length zero is returned for each parameter
- * with no annotations.) The annotation objects contained in the returned
- * arrays are serializable. The caller of this method is free to modify
- * the returned arrays; it will have no effect on the arrays returned to
- * other callers.
- *
- * @return an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by this
- * Constructor object
+ * {@inheritDoc}
* @since 1.5
*/
+ @Override
public Annotation[][] getParameterAnnotations() {
- int numParameters = parameterTypes.length;
- Annotation[][] result = Method.getParameterAnnotationsImpl(this);
- if (result == null)
- return new Annotation[numParameters][0];
- if (result.length != numParameters) {
- Class<?> declaringClass = getDeclaringClass();
- if (declaringClass.isEnum() ||
- declaringClass.isAnonymousClass() ||
- declaringClass.isLocalClass() )
- ; // Can't do reliable parameter counting
- else {
- if (!declaringClass.isMemberClass() || // top-level
- // Check for the enclosing instance parameter for
- // non-static member classes
- (declaringClass.isMemberClass() &&
- ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
- result.length + 1 != numParameters) ) {
- throw new AnnotationFormatError(
- "Parameter annotations don't match number of parameters");
- }
+ return sharedGetParameterAnnotations(parameterTypes);
+ }
+
+ @Override
+ void handleParameterNumberMismatch(int resultLength, int numParameters) {
+ Class<?> declaringClass = getDeclaringClass();
+ if (declaringClass.isEnum() ||
+ declaringClass.isAnonymousClass() ||
+ declaringClass.isLocalClass() )
+ return ; // Can't do reliable parameter counting
+ else {
+ if (!declaringClass.isMemberClass() || // top-level
+ // Check for the enclosing instance parameter for
+ // non-static member classes
+ (declaringClass.isMemberClass() &&
+ ((declaringClass.getModifiers() & Modifier.STATIC) == 0) &&
+ resultLength + 1 != numParameters) ) {
+ throw new AnnotationFormatError(
+ "Parameter annotations don't match number of parameters");
}
}
- return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public AnnotatedType getAnnotatedReturnType() {
+ return getAnnotatedReturnType0(getDeclaringClass());
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public AnnotatedType getAnnotatedReceiverType() {
+ if (getDeclaringClass().getEnclosingClass() == null)
+ return super.getAnnotatedReceiverType();
+
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getDeclaringClass().getEnclosingClass(),
+ TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
}
}
diff --git a/openjdk/java/lang/reflect/Executable.java b/openjdk/java/lang/reflect/Executable.java
new file mode 100644
index 00000000..be6ac0dd
--- /dev/null
+++ b/openjdk/java/lang/reflect/Executable.java
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2012, 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 java.lang.reflect;
+
+import java.lang.annotation.*;
+import java.util.Map;
+import java.util.Objects;
+import sun.reflect.annotation.AnnotationParser;
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotationParser;
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.generics.repository.ConstructorRepository;
+
+/**
+ * A shared superclass for the common functionality of {@link Method}
+ * and {@link Constructor}.
+ *
+ * @since 1.8
+ */
+public abstract class Executable extends AccessibleObject
+ implements Member, GenericDeclaration {
+ /*
+ * Only grant package-visibility to the constructor.
+ */
+ Executable() {}
+
+ /**
+ * Accessor method to allow code sharing
+ */
+ abstract Executable getRoot();
+
+ /**
+ * Does the Executable have generic information.
+ */
+ abstract boolean hasGenericInformation();
+
+ abstract ConstructorRepository getGenericInfo();
+
+ boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
+ /* Avoid unnecessary cloning */
+ if (params1.length == params2.length) {
+ for (int i = 0; i < params1.length; i++) {
+ if (params1[i] != params2[i])
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ void separateWithCommas(Class<?>[] types, StringBuilder sb) {
+ for (int j = 0; j < types.length; j++) {
+ sb.append(types[j].getTypeName());
+ if (j < (types.length - 1))
+ sb.append(",");
+ }
+
+ }
+
+ void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) {
+ int mod = getModifiers() & mask;
+
+ if (mod != 0 && !isDefault) {
+ sb.append(Modifier.toString(mod)).append(' ');
+ } else {
+ int access_mod = mod & Modifier.ACCESS_MODIFIERS;
+ if (access_mod != 0)
+ sb.append(Modifier.toString(access_mod)).append(' ');
+ if (isDefault)
+ sb.append("default ");
+ mod = (mod & ~Modifier.ACCESS_MODIFIERS);
+ if (mod != 0)
+ sb.append(Modifier.toString(mod)).append(' ');
+ }
+ }
+
+ String sharedToString(int modifierMask,
+ boolean isDefault,
+ Class<?>[] parameterTypes,
+ Class<?>[] exceptionTypes) {
+ try {
+ StringBuilder sb = new StringBuilder();
+
+ printModifiersIfNonzero(sb, modifierMask, isDefault);
+ specificToStringHeader(sb);
+
+ sb.append('(');
+ separateWithCommas(parameterTypes, sb);
+ sb.append(')');
+ if (exceptionTypes.length > 0) {
+ sb.append(" throws ");
+ separateWithCommas(exceptionTypes, sb);
+ }
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Generate toString header information specific to a method or
+ * constructor.
+ */
+ abstract void specificToStringHeader(StringBuilder sb);
+
+ String sharedToGenericString(int modifierMask, boolean isDefault) {
+ try {
+ StringBuilder sb = new StringBuilder();
+
+ printModifiersIfNonzero(sb, modifierMask, isDefault);
+
+ TypeVariable<?>[] typeparms = getTypeParameters();
+ if (typeparms.length > 0) {
+ boolean first = true;
+ sb.append('<');
+ for(TypeVariable<?> typeparm: typeparms) {
+ if (!first)
+ sb.append(',');
+ // Class objects can't occur here; no need to test
+ // and call Class.getName().
+ sb.append(typeparm.toString());
+ first = false;
+ }
+ sb.append("> ");
+ }
+
+ specificToGenericStringHeader(sb);
+
+ sb.append('(');
+ Type[] params = getGenericParameterTypes();
+ for (int j = 0; j < params.length; j++) {
+ String param = params[j].getTypeName();
+ if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
+ param = param.replaceFirst("\\[\\]$", "...");
+ sb.append(param);
+ if (j < (params.length - 1))
+ sb.append(',');
+ }
+ sb.append(')');
+ Type[] exceptions = getGenericExceptionTypes();
+ if (exceptions.length > 0) {
+ sb.append(" throws ");
+ for (int k = 0; k < exceptions.length; k++) {
+ sb.append((exceptions[k] instanceof Class)?
+ ((Class)exceptions[k]).getName():
+ exceptions[k].toString());
+ if (k < (exceptions.length - 1))
+ sb.append(',');
+ }
+ }
+ return sb.toString();
+ } catch (Exception e) {
+ return "<" + e + ">";
+ }
+ }
+
+ /**
+ * Generate toGenericString header information specific to a
+ * method or constructor.
+ */
+ abstract void specificToGenericStringHeader(StringBuilder sb);
+
+ /**
+ * Returns the {@code Class} object representing the class or interface
+ * that declares the executable represented by this object.
+ */
+ public abstract Class<?> getDeclaringClass();
+
+ /**
+ * Returns the name of the executable represented by this object.
+ */
+ public abstract String getName();
+
+ /**
+ * Returns the Java language {@linkplain Modifier modifiers} for
+ * the executable represented by this object.
+ */
+ public abstract int getModifiers();
+
+ /**
+ * Returns an array of {@code TypeVariable} objects that represent the
+ * type variables declared by the generic declaration represented by this
+ * {@code GenericDeclaration} object, in declaration order. Returns an
+ * array of length 0 if the underlying generic declaration declares no type
+ * variables.
+ *
+ * @return an array of {@code TypeVariable} objects that represent
+ * the type variables declared by this generic declaration
+ * @throws GenericSignatureFormatError if the generic
+ * signature of this generic declaration does not conform to
+ * the format specified in
+ * <cite>The Java&trade; Virtual Machine Specification</cite>
+ */
+ public abstract TypeVariable<?>[] getTypeParameters();
+
+ /**
+ * Returns an array of {@code Class} objects that represent the formal
+ * parameter types, in declaration order, of the executable
+ * represented by this object. Returns an array of length
+ * 0 if the underlying executable takes no parameters.
+ *
+ * @return the parameter types for the executable this object
+ * represents
+ */
+ public abstract Class<?>[] getParameterTypes();
+
+ /**
+ * Returns the number of formal parameters (whether explicitly
+ * declared or implicitly declared or neither) for the executable
+ * represented by this object.
+ *
+ * @since 1.8
+ * @return The number of formal parameters for the executable this
+ * object represents
+ */
+ public int getParameterCount() {
+ throw new AbstractMethodError();
+ }
+
+ /**
+ * Returns an array of {@code Type} objects that represent the formal
+ * parameter types, in declaration order, of the executable represented by
+ * this object. Returns an array of length 0 if the
+ * underlying executable takes no parameters.
+ *
+ * <p>If a formal parameter type is a parameterized type,
+ * the {@code Type} object returned for it must accurately reflect
+ * the actual type parameters used in the source code.
+ *
+ * <p>If a formal parameter type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of {@code Type}s that represent the formal
+ * parameter types of the underlying executable, in declaration order
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in
+ * <cite>The Java&trade; Virtual Machine Specification</cite>
+ * @throws TypeNotPresentException if any of the parameter
+ * types of the underlying executable refers to a non-existent type
+ * declaration
+ * @throws MalformedParameterizedTypeException if any of
+ * the underlying executable's parameter types refer to a parameterized
+ * type that cannot be instantiated for any reason
+ */
+ public Type[] getGenericParameterTypes() {
+ if (hasGenericInformation())
+ return getGenericInfo().getParameterTypes();
+ else
+ return getParameterTypes();
+ }
+
+ /**
+ * Behaves like {@code getGenericParameterTypes}, but returns type
+ * information for all parameters, including synthetic parameters.
+ */
+ Type[] getAllGenericParameterTypes() {
+ final boolean genericInfo = hasGenericInformation();
+
+ // Easy case: we don't have generic parameter information. In
+ // this case, we just return the result of
+ // getParameterTypes().
+ if (!genericInfo) {
+ return getParameterTypes();
+ } else {
+ final boolean realParamData = hasRealParameterData();
+ final Type[] genericParamTypes = getGenericParameterTypes();
+ final Type[] nonGenericParamTypes = getParameterTypes();
+ final Type[] out = new Type[nonGenericParamTypes.length];
+ final Parameter[] params = getParameters();
+ int fromidx = 0;
+ // If we have real parameter data, then we use the
+ // synthetic and mandate flags to our advantage.
+ if (realParamData) {
+ for (int i = 0; i < out.length; i++) {
+ final Parameter param = params[i];
+ if (param.isSynthetic() || param.isImplicit()) {
+ // If we hit a synthetic or mandated parameter,
+ // use the non generic parameter info.
+ out[i] = nonGenericParamTypes[i];
+ } else {
+ // Otherwise, use the generic parameter info.
+ out[i] = genericParamTypes[fromidx];
+ fromidx++;
+ }
+ }
+ } else {
+ // Otherwise, use the non-generic parameter data.
+ // Without method parameter reflection data, we have
+ // no way to figure out which parameters are
+ // synthetic/mandated, thus, no way to match up the
+ // indexes.
+ return genericParamTypes.length == nonGenericParamTypes.length ?
+ genericParamTypes : nonGenericParamTypes;
+ }
+ return out;
+ }
+ }
+
+ /**
+ * Returns an array of {@code Parameter} objects that represent
+ * all the parameters to the underlying executable represented by
+ * this object. Returns an array of length 0 if the executable
+ * has no parameters.
+ *
+ * <p>The parameters of the underlying executable do not necessarily
+ * have unique names, or names that are legal identifiers in the
+ * Java programming language (JLS 3.8).
+ *
+ * @since 1.8
+ * @throws MalformedParametersException if the class file contains
+ * a MethodParameters attribute that is improperly formatted.
+ * @return an array of {@code Parameter} objects representing all
+ * the parameters to the executable this object represents.
+ */
+ public Parameter[] getParameters() {
+ // TODO: This may eventually need to be guarded by security
+ // mechanisms similar to those in Field, Method, etc.
+ //
+ // Need to copy the cached array to prevent users from messing
+ // with it. Since parameters are immutable, we can
+ // shallow-copy.
+ return privateGetParameters().clone();
+ }
+
+ private Parameter[] synthesizeAllParams() {
+ final int realparams = getParameterCount();
+ final Parameter[] out = new Parameter[realparams];
+ for (int i = 0; i < realparams; i++)
+ // TODO: is there a way to synthetically derive the
+ // modifiers? Probably not in the general case, since
+ // we'd have no way of knowing about them, but there
+ // may be specific cases.
+ out[i] = new Parameter("arg" + i, 0, this, i);
+ return out;
+ }
+
+ private void verifyParameters(final Parameter[] parameters) {
+ final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED;
+
+ if (getParameterTypes().length != parameters.length)
+ throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute");
+
+ for (Parameter parameter : parameters) {
+ final String name = parameter.getRealName();
+ final int mods = parameter.getModifiers();
+
+ if (name != null) {
+ if (name.isEmpty() || name.indexOf('.') != -1 ||
+ name.indexOf(';') != -1 || name.indexOf('[') != -1 ||
+ name.indexOf('/') != -1) {
+ throw new MalformedParametersException("Invalid parameter name \"" + name + "\"");
+ }
+ }
+
+ if (mods != (mods & mask)) {
+ throw new MalformedParametersException("Invalid parameter modifiers");
+ }
+ }
+ }
+
+ private Parameter[] privateGetParameters() {
+ // Use tmp to avoid multiple writes to a volatile.
+ Parameter[] tmp = parameters;
+
+ if (tmp == null) {
+
+ // Otherwise, go to the JVM to get them
+ try {
+ tmp = getParameters0();
+ } catch(IllegalArgumentException e) {
+ // Rethrow ClassFormatErrors
+ throw new MalformedParametersException("Invalid constant pool index");
+ }
+
+ // If we get back nothing, then synthesize parameters
+ if (tmp == null) {
+ hasRealParameterData = false;
+ tmp = synthesizeAllParams();
+ } else {
+ hasRealParameterData = true;
+ verifyParameters(tmp);
+ }
+
+ parameters = tmp;
+ }
+
+ return tmp;
+ }
+
+ boolean hasRealParameterData() {
+ // If this somehow gets called before parameters gets
+ // initialized, force it into existence.
+ if (parameters == null) {
+ privateGetParameters();
+ }
+ return hasRealParameterData;
+ }
+
+ private transient volatile boolean hasRealParameterData;
+ private transient volatile Parameter[] parameters;
+
+ private native Parameter[] getParameters0();
+ native byte[] getTypeAnnotationBytes0();
+
+ // Needed by reflectaccess
+ byte[] getTypeAnnotationBytes() {
+ return getTypeAnnotationBytes0();
+ }
+
+ /**
+ * Returns an array of {@code Class} objects that represent the
+ * types of exceptions declared to be thrown by the underlying
+ * executable represented by this object. Returns an array of
+ * length 0 if the executable declares no exceptions in its {@code
+ * throws} clause.
+ *
+ * @return the exception types declared as being thrown by the
+ * executable this object represents
+ */
+ public abstract Class<?>[] getExceptionTypes();
+
+ /**
+ * Returns an array of {@code Type} objects that represent the
+ * exceptions declared to be thrown by this executable object.
+ * Returns an array of length 0 if the underlying executable declares
+ * no exceptions in its {@code throws} clause.
+ *
+ * <p>If an exception type is a type variable or a parameterized
+ * type, it is created. Otherwise, it is resolved.
+ *
+ * @return an array of Types that represent the exception types
+ * thrown by the underlying executable
+ * @throws GenericSignatureFormatError
+ * if the generic method signature does not conform to the format
+ * specified in
+ * <cite>The Java&trade; Virtual Machine Specification</cite>
+ * @throws TypeNotPresentException if the underlying executable's
+ * {@code throws} clause refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if
+ * the underlying executable's {@code throws} clause refers to a
+ * parameterized type that cannot be instantiated for any reason
+ */
+ public Type[] getGenericExceptionTypes() {
+ Type[] result;
+ if (hasGenericInformation() &&
+ ((result = getGenericInfo().getExceptionTypes()).length > 0))
+ return result;
+ else
+ return getExceptionTypes();
+ }
+
+ /**
+ * Returns a string describing this {@code Executable}, including
+ * any type parameters.
+ * @return a string describing this {@code Executable}, including
+ * any type parameters
+ */
+ public abstract String toGenericString();
+
+ /**
+ * Returns {@code true} if this executable was declared to take a
+ * variable number of arguments; returns {@code false} otherwise.
+ *
+ * @return {@code true} if an only if this executable was declared
+ * to take a variable number of arguments.
+ */
+ public boolean isVarArgs() {
+ return (getModifiers() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Returns {@code true} if this executable is a synthetic
+ * construct; returns {@code false} otherwise.
+ *
+ * @return true if and only if this executable is a synthetic
+ * construct as defined by
+ * <cite>The Java&trade; Language Specification</cite>.
+ * @jls 13.1 The Form of a Binary
+ */
+ public boolean isSynthetic() {
+ return Modifier.isSynthetic(getModifiers());
+ }
+
+ /**
+ * Returns an array of arrays of {@code Annotation}s that
+ * represent the annotations on the formal parameters, in
+ * declaration order, of the {@code Executable} represented by
+ * this object. Synthetic and mandated parameters (see
+ * explanation below), such as the outer "this" parameter to an
+ * inner class constructor will be represented in the returned
+ * array. If the executable has no parameters (meaning no formal,
+ * no synthetic, and no mandated parameters), a zero-length array
+ * will be returned. If the {@code Executable} has one or more
+ * parameters, a nested array of length zero is returned for each
+ * parameter with no annotations. The annotation objects contained
+ * in the returned arrays are serializable. The caller of this
+ * method is free to modify the returned arrays; it will have no
+ * effect on the arrays returned to other callers.
+ *
+ * A compiler may add extra parameters that are implicitly
+ * declared in source ("mandated"), as well as parameters that
+ * are neither implicitly nor explicitly declared in source
+ * ("synthetic") to the parameter list for a method. See {@link
+ * java.lang.reflect.Parameter} for more information.
+ *
+ * @see java.lang.reflect.Parameter
+ * @see java.lang.reflect.Parameter#getAnnotations
+ * @return an array of arrays that represent the annotations on
+ * the formal and implicit parameters, in declaration order, of
+ * the executable represented by this object
+ */
+ public abstract Annotation[][] getParameterAnnotations();
+
+ Annotation[][] sharedGetParameterAnnotations(Class<?>[] parameterTypes) {
+ int numParameters = parameterTypes.length;
+
+ Annotation[][] result = sharedGetParameterAnnotationsImpl();
+ if (result == null)
+ return new Annotation[numParameters][0];
+
+ if (result.length != numParameters)
+ handleParameterNumberMismatch(result.length, numParameters);
+ return result;
+ }
+
+ private native Annotation[][] sharedGetParameterAnnotationsImpl();
+
+ abstract void handleParameterNumberMismatch(int resultLength, int numParameters);
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ return annotationClass.cast(declaredAnnotations().get(annotationClass));
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ return AnnotationParser.toArray(declaredAnnotations());
+ }
+
+ private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
+
+ private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
+ if (declaredAnnotations == null) {
+ Executable root = getRoot();
+ if (root != null) {
+ declaredAnnotations = root.declaredAnnotations();
+ } else {
+ declaredAnnotations = declaredAnnotationsImpl();
+ }
+ }
+ return declaredAnnotations;
+ }
+
+ private native Map<Class<? extends Annotation>, Annotation> declaredAnnotationsImpl();
+
+ /**
+ * Returns an {@code AnnotatedType} object that represents the use of a type to
+ * specify the return type of the method/constructor represented by this
+ * Executable.
+ *
+ * If this {@code Executable} object represents a constructor, the {@code
+ * AnnotatedType} object represents the type of the constructed object.
+ *
+ * If this {@code Executable} object represents a method, the {@code
+ * AnnotatedType} object represents the use of a type to specify the return
+ * type of the method.
+ *
+ * @return an object representing the return type of the method
+ * or constructor represented by this {@code Executable}
+ *
+ * @since 1.8
+ */
+ public abstract AnnotatedType getAnnotatedReturnType();
+
+ /* Helper for subclasses of Executable.
+ *
+ * Returns an AnnotatedType object that represents the use of a type to
+ * specify the return type of the method/constructor represented by this
+ * Executable.
+ *
+ * @since 1.8
+ */
+ AnnotatedType getAnnotatedReturnType0(Type returnType) {
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ returnType,
+ TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN);
+ }
+
+ /**
+ * Returns an {@code AnnotatedType} object that represents the use of a
+ * type to specify the receiver type of the method/constructor represented
+ * by this Executable object. The receiver type of a method/constructor is
+ * available only if the method/constructor has a <em>receiver
+ * parameter</em> (JLS 8.4.1).
+ *
+ * If this {@code Executable} object represents a constructor or instance
+ * method that does not have a receiver parameter, or has a receiver
+ * parameter with no annotations on its type, then the return value is an
+ * {@code AnnotatedType} object representing an element with no
+ * annotations.
+ *
+ * If this {@code Executable} object represents a static method, then the
+ * return value is null.
+ *
+ * @return an object representing the receiver type of the method or
+ * constructor represented by this {@code Executable}
+ *
+ * @since 1.8
+ */
+ public AnnotatedType getAnnotatedReceiverType() {
+ if (Modifier.isStatic(this.getModifiers()))
+ return null;
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getDeclaringClass(),
+ TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
+ }
+
+ /**
+ * Returns an array of {@code AnnotatedType} objects that represent the use
+ * of types to specify formal parameter types of the method/constructor
+ * represented by this Executable. The order of the objects in the array
+ * corresponds to the order of the formal parameter types in the
+ * declaration of the method/constructor.
+ *
+ * Returns an array of length 0 if the method/constructor declares no
+ * parameters.
+ *
+ * @return an array of objects representing the types of the
+ * formal parameters of the method or constructor represented by this
+ * {@code Executable}
+ *
+ * @since 1.8
+ */
+ public AnnotatedType[] getAnnotatedParameterTypes() {
+ return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getAllGenericParameterTypes(),
+ TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
+ }
+
+ /**
+ * Returns an array of {@code AnnotatedType} objects that represent the use
+ * of types to specify the declared exceptions of the method/constructor
+ * represented by this Executable. The order of the objects in the array
+ * corresponds to the order of the exception types in the declaration of
+ * the method/constructor.
+ *
+ * Returns an array of length 0 if the method/constructor declares no
+ * exceptions.
+ *
+ * @return an array of objects representing the declared
+ * exceptions of the method or constructor represented by this {@code
+ * Executable}
+ *
+ * @since 1.8
+ */
+ public AnnotatedType[] getAnnotatedExceptionTypes() {
+ return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getGenericExceptionTypes(),
+ TypeAnnotation.TypeAnnotationTarget.THROWS);
+ }
+
+}
diff --git a/openjdk/java/lang/reflect/Field.java b/openjdk/java/lang/reflect/Field.java
index b2cb46b3..a683e59a 100644
--- a/openjdk/java/lang/reflect/Field.java
+++ b/openjdk/java/lang/reflect/Field.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -34,8 +34,11 @@ import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.scope.ClassScope;
import java.lang.annotation.Annotation;
import java.util.Map;
+import java.util.Objects;
import sun.reflect.annotation.AnnotationParser;
-
+import sun.reflect.annotation.AnnotationSupport;
+import sun.reflect.annotation.TypeAnnotation;
+import sun.reflect.annotation.TypeAnnotationParser;
/**
* A {@code Field} provides information about, and dynamic access to, a
@@ -77,6 +80,9 @@ class Field extends AccessibleObject implements Member {
// For sharing of FieldAccessors. This branching structure is
// currently only two levels deep (i.e., one root Field and
// potentially many Field objects pointing to it.)
+ //
+ // If this branching structure would ever contain cycles, deadlocks can
+ // occur in annotation code.
private Field root;
// Generics infrastructure
@@ -136,11 +142,15 @@ class Field extends AccessibleObject implements Member {
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
+ if (this.root != null)
+ throw new IllegalArgumentException("Can not copy a non-root Field");
+
Field res = new Field(clazz, name, type, modifiers, slot, signature, null);
res.root = this;
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
res.overrideFieldAccessor = overrideFieldAccessor;
+
return res;
}
@@ -280,12 +290,15 @@ class Field extends AccessibleObject implements Member {
* {@code protected} or {@code private} first, and then other
* modifiers in the following order: {@code static}, {@code final},
* {@code transient}, {@code volatile}.
+ *
+ * @return a string describing this {@code Field}
+ * @jls 8.3.1 Field Modifiers
*/
public String toString() {
int mod = getModifiers();
return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
- + getTypeName(getType()) + " "
- + getTypeName(getDeclaringClass()) + "."
+ + getType().getTypeName() + " "
+ + getDeclaringClass().getTypeName() + "."
+ getName());
}
@@ -307,14 +320,14 @@ class Field extends AccessibleObject implements Member {
* its generic type
*
* @since 1.5
+ * @jls 8.3.1 Field Modifiers
*/
public String toGenericString() {
int mod = getModifiers();
Type fieldType = getGenericType();
return (((mod == 0) ? "" : (Modifier.toString(mod) + " "))
- + ((fieldType instanceof Class) ?
- getTypeName((Class)fieldType): fieldType.toString())+ " "
- + getTypeName(getDeclaringClass()) + "."
+ + fieldType.getTypeName() + " "
+ + getDeclaringClass().getTypeName() + "."
+ getName());
}
@@ -371,7 +384,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).get(obj);
@@ -405,7 +419,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getBoolean(obj);
@@ -439,7 +454,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getByte(obj);
@@ -475,7 +491,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getChar(obj);
@@ -511,7 +528,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getShort(obj);
@@ -547,7 +565,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getInt(obj);
@@ -583,7 +602,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getLong(obj);
@@ -619,7 +639,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getFloat(obj);
@@ -655,7 +676,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getDouble(obj);
@@ -733,7 +755,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).set(obj, value);
@@ -769,7 +792,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setBoolean(obj, z);
@@ -805,7 +829,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setByte(obj, b);
@@ -841,7 +866,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setChar(obj, c);
@@ -877,7 +903,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setShort(obj, s);
@@ -913,7 +940,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setInt(obj, i);
@@ -949,7 +977,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setLong(obj, l);
@@ -985,7 +1014,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setFloat(obj, f);
@@ -1021,7 +1051,8 @@ class Field extends AccessibleObject implements Member {
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
- checkAccess(Reflection.getCallerClass(), clazz, obj, modifiers);
+ Class<?> caller = Reflection.getCallerClass();
+ checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setDouble(obj, d);
@@ -1078,57 +1109,66 @@ class Field extends AccessibleObject implements Member {
}
}
- /*
- * Utility routine to paper over array type names
+ /**
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
*/
- static String getTypeName(Class<?> type) {
- if (type.isArray()) {
- try {
- Class<?> cl = type;
- int dimensions = 0;
- while (cl.isArray()) {
- dimensions++;
- cl = cl.getComponentType();
- }
- StringBuffer sb = new StringBuffer();
- sb.append(cl.getName());
- for (int i = 0; i < dimensions; i++) {
- sb.append("[]");
- }
- return sb.toString();
- } catch (Throwable e) { /*FALLTHRU*/ }
- }
- return type.getName();
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
+ return annotationClass.cast(declaredAnnotations().get(annotationClass));
}
/**
+ * {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
- * @since 1.5
+ * @since 1.8
*/
- public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
+ @Override
+ public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+ Objects.requireNonNull(annotationClass);
- return (T) declaredAnnotations().get(annotationClass);
+ return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
}
- private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0];
-
/**
- * @since 1.5
+ * {@inheritDoc}
*/
public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
+ return AnnotationParser.toArray(declaredAnnotations());
}
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
if (declaredAnnotations == null) {
- declaredAnnotations = getDeclaredAnnotationsImpl();
+ Field root = this.root;
+ if (root != null) {
+ declaredAnnotations = root.declaredAnnotations();
+ } else {
+ declaredAnnotations = getDeclaredAnnotationsImpl();
+ }
}
return declaredAnnotations;
}
-
+
private native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl();
+ private native byte[] getTypeAnnotationBytes0();
+
+ /**
+ * Returns an AnnotatedType object that represents the use of a type to specify
+ * the declared type of the field represented by this Field.
+ * @return an object representing the declared type of the field
+ * represented by this Field
+ *
+ * @since 1.8
+ */
+ public AnnotatedType getAnnotatedType() {
+ return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ getConstantPool(getDeclaringClass()),
+ this,
+ getDeclaringClass(),
+ getGenericType(),
+ TypeAnnotation.TypeAnnotationTarget.FIELD);
+}
}
diff --git a/openjdk/java/lang/reflect/Method.java b/openjdk/java/lang/reflect/Method.java
index dce789a4..c8705ba1 100644
--- a/openjdk/java/lang/reflect/Method.java
+++ b/openjdk/java/lang/reflect/Method.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,7 +25,6 @@
package java.lang.reflect;
-import ikvm.internal.CallerID;
import sun.reflect.CallerSensitive;
import sun.reflect.MethodAccessor;
import sun.reflect.Reflection;
@@ -38,7 +37,6 @@ import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.nio.ByteBuffer;
-import java.util.Map;
/**
* A {@code Method} provides information about, and access to, a single method
@@ -60,9 +58,7 @@ import java.util.Map;
* @author Kenneth Russell
* @author Nakul Saraiya
*/
-public final
- class Method extends AccessibleObject implements GenericDeclaration,
- Member {
+public final class Method extends Executable {
private Class<?> clazz;
private int slot;
// This is guaranteed to be interned by the VM in the 1.4
@@ -80,10 +76,12 @@ public final
// For sharing of MethodAccessors. This branching structure is
// currently only two levels deep (i.e., one root Method and
// potentially many Method objects pointing to it.)
+ //
+ // If this branching structure would ever contain cycles, deadlocks can
+ // occur in annotation code.
private Method root;
- // Generics infrastructure
-
+ // Generics infrastructure
private String getGenericSignature() {return signature;}
// Accessor for factory
@@ -93,7 +91,8 @@ public final
}
// Accessor for generic info repository
- private MethodRepository getGenericInfo() {
+ @Override
+ MethodRepository getGenericInfo() {
// lazily initialize repository if necessary
if (genericInfo == null) {
// create and cache generic info repository
@@ -118,8 +117,7 @@ public final
String signature,
byte[] unused1,
byte[] unused2,
- byte[] unused3)
- {
+ byte[] unused3) {
this.clazz = declaringClass;
this.name = name;
this.parameterTypes = parameterTypes;
@@ -143,6 +141,9 @@ public final
// which implicitly requires that new java.lang.reflect
// objects be fabricated for each reflective call on Class
// objects.)
+ if (this.root != null)
+ throw new IllegalArgumentException("Can not copy a non-root Method");
+
Method res = new Method(clazz, name, parameterTypes, returnType,
exceptionTypes, modifiers, slot, signature,
null, null, null);
@@ -153,9 +154,22 @@ public final
}
/**
- * Returns the {@code Class} object representing the class or interface
- * that declares the method represented by this {@code Method} object.
+ * Used by Excecutable for annotation sharing.
*/
+ @Override
+ Executable getRoot() {
+ return root;
+ }
+
+ @Override
+ boolean hasGenericInformation() {
+ return (getGenericSignature() != null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public Class<?> getDeclaringClass() {
return clazz;
}
@@ -164,36 +178,26 @@ public final
* Returns the name of the method represented by this {@code Method}
* object, as a {@code String}.
*/
+ @Override
public String getName() {
return name;
}
/**
- * Returns the Java language modifiers for the method represented
- * by this {@code Method} object, as an integer. The {@code Modifier} class should
- * be used to decode the modifiers.
- *
- * @see Modifier
+ * {@inheritDoc}
*/
+ @Override
public int getModifiers() {
return modifiers;
}
/**
- * Returns an array of {@code TypeVariable} objects that represent the
- * type variables declared by the generic declaration represented by this
- * {@code GenericDeclaration} object, in declaration order. Returns an
- * array of length 0 if the underlying generic declaration declares no type
- * variables.
- *
- * @return an array of {@code TypeVariable} objects that represent
- * the type variables declared by this generic declaration
- * @throws GenericSignatureFormatError if the generic
- * signature of this generic declaration does not conform to
- * the format specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
* @since 1.5
*/
+ @Override
+ @SuppressWarnings({"rawtypes", "unchecked"})
public TypeVariable<Method>[] getTypeParameters() {
if (getGenericSignature() != null)
return (TypeVariable<Method>[])getGenericInfo().getTypeParameters();
@@ -241,99 +245,51 @@ public final
} else { return getReturnType();}
}
-
/**
- * Returns an array of {@code Class} objects that represent the formal
- * parameter types, in declaration order, of the method
- * represented by this {@code Method} object. Returns an array of length
- * 0 if the underlying method takes no parameters.
- *
- * @return the parameter types for the method this object
- * represents
+ * {@inheritDoc}
*/
+ @Override
public Class<?>[] getParameterTypes() {
- return (Class<?>[]) parameterTypes.clone();
+ return parameterTypes.clone();
}
/**
- * Returns an array of {@code Type} objects that represent the formal
- * parameter types, in declaration order, of the method represented by
- * this {@code Method} object. Returns an array of length 0 if the
- * underlying method takes no parameters.
- *
- * <p>If a formal parameter type is a parameterized type,
- * the {@code Type} object returned for it must accurately reflect
- * the actual type parameters used in the source code.
- *
- * <p>If a formal parameter type is a type variable or a parameterized
- * type, it is created. Otherwise, it is resolved.
- *
- * @return an array of Types that represent the formal
- * parameter types of the underlying method, in declaration order
- * @throws GenericSignatureFormatError
- * if the generic method signature does not conform to the format
- * specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
- * @throws TypeNotPresentException if any of the parameter
- * types of the underlying method refers to a non-existent type
- * declaration
- * @throws MalformedParameterizedTypeException if any of
- * the underlying method's parameter types refer to a parameterized
- * type that cannot be instantiated for any reason
+ * {@inheritDoc}
+ */
+ public int getParameterCount() { return parameterTypes.length; }
+
+
+ /**
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
+ * @throws TypeNotPresentException {@inheritDoc}
+ * @throws MalformedParameterizedTypeException {@inheritDoc}
* @since 1.5
*/
+ @Override
public Type[] getGenericParameterTypes() {
- if (getGenericSignature() != null)
- return getGenericInfo().getParameterTypes();
- else
- return getParameterTypes();
+ return super.getGenericParameterTypes();
}
-
/**
- * Returns an array of {@code Class} objects that represent
- * the types of the exceptions declared to be thrown
- * by the underlying method
- * represented by this {@code Method} object. Returns an array of length
- * 0 if the method declares no exceptions in its {@code throws} clause.
- *
- * @return the exception types declared as being thrown by the
- * method this object represents
+ * {@inheritDoc}
*/
+ @Override
public Class<?>[] getExceptionTypes() {
- return (Class<?>[]) exceptionTypes.clone();
+ return exceptionTypes.clone();
}
/**
- * Returns an array of {@code Type} objects that represent the
- * exceptions declared to be thrown by this {@code Method} object.
- * Returns an array of length 0 if the underlying method declares
- * no exceptions in its {@code throws} clause.
- *
- * <p>If an exception type is a type variable or a parameterized
- * type, it is created. Otherwise, it is resolved.
- *
- * @return an array of Types that represent the exception types
- * thrown by the underlying method
- * @throws GenericSignatureFormatError
- * if the generic method signature does not conform to the format
- * specified in
- * <cite>The Java&trade; Virtual Machine Specification</cite>
- * @throws TypeNotPresentException if the underlying method's
- * {@code throws} clause refers to a non-existent type declaration
- * @throws MalformedParameterizedTypeException if
- * the underlying method's {@code throws} clause refers to a
- * parameterized type that cannot be instantiated for any reason
+ * {@inheritDoc}
+ * @throws GenericSignatureFormatError {@inheritDoc}
+ * @throws TypeNotPresentException {@inheritDoc}
+ * @throws MalformedParameterizedTypeException {@inheritDoc}
* @since 1.5
*/
- public Type[] getGenericExceptionTypes() {
- Type[] result;
- if (getGenericSignature() != null &&
- ((result = getGenericInfo().getExceptionTypes()).length > 0))
- return result;
- else
- return getExceptionTypes();
- }
+ @Override
+ public Type[] getGenericExceptionTypes() {
+ return super.getGenericExceptionTypes();
+ }
/**
* Compares this {@code Method} against the specified object. Returns
@@ -348,16 +304,7 @@ public final
&& (getName() == other.getName())) {
if (!returnType.equals(other.getReturnType()))
return false;
- /* Avoid unnecessary cloning */
- Class<?>[] params1 = parameterTypes;
- Class<?>[] params2 = other.parameterTypes;
- if (params1.length == params2.length) {
- for (int i = 0; i < params1.length; i++) {
- if (params1[i] != params2[i])
- return false;
- }
- return true;
- }
+ return equalParamTypes(parameterTypes, other.parameterTypes);
}
}
return false;
@@ -391,39 +338,25 @@ public final
* specified by "The Java Language Specification". This is
* {@code public}, {@code protected} or {@code private} first,
* and then other modifiers in the following order:
- * {@code abstract}, {@code static}, {@code final},
+ * {@code abstract}, {@code default}, {@code static}, {@code final},
* {@code synchronized}, {@code native}, {@code strictfp}.
+ *
+ * @return a string describing this {@code Method}
+ *
+ * @jls 8.4.3 Method Modifiers
*/
public String toString() {
- try {
- StringBuilder sb = new StringBuilder();
- int mod = getModifiers() & Modifier.methodModifiers();
- if (mod != 0) {
- sb.append(Modifier.toString(mod)).append(' ');
- }
- sb.append(Field.getTypeName(getReturnType())).append(' ');
- sb.append(Field.getTypeName(getDeclaringClass())).append('.');
- sb.append(getName()).append('(');
- Class<?>[] params = parameterTypes; // avoid clone
- for (int j = 0; j < params.length; j++) {
- sb.append(Field.getTypeName(params[j]));
- if (j < (params.length - 1))
- sb.append(',');
- }
- sb.append(')');
- Class<?>[] exceptions = exceptionTypes; // avoid clone
- if (exceptions.length > 0) {
- sb.append(" throws ");
- for (int k = 0; k < exceptions.length; k++) {
- sb.append(exceptions[k].getName());
- if (k < (exceptions.length - 1))
- sb.append(',');
- }
- }
- return sb.toString();
- } catch (Exception e) {
- return "<" + e + ">";
- }
+ return sharedToString(Modifier.methodModifiers(),
+ isDefault(),
+ parameterTypes,
+ exceptionTypes);
+ }
+
+ @Override
+ void specificToStringHeader(StringBuilder sb) {
+ sb.append(getReturnType().getTypeName()).append(' ');
+ sb.append(getDeclaringClass().getTypeName()).append('.');
+ sb.append(getName());
}
/**
@@ -449,77 +382,33 @@ public final
* class name. If the method is declared to throw exceptions, the
* parameter list is followed by a space, followed by the word
* throws followed by a comma-separated list of the generic thrown
- * exception types. If there are no type parameters, the type
- * parameter list is elided.
+ * exception types.
*
* <p>The access modifiers are placed in canonical order as
* specified by "The Java Language Specification". This is
* {@code public}, {@code protected} or {@code private} first,
* and then other modifiers in the following order:
- * {@code abstract}, {@code static}, {@code final},
+ * {@code abstract}, {@code default}, {@code static}, {@code final},
* {@code synchronized}, {@code native}, {@code strictfp}.
*
* @return a string describing this {@code Method},
* include type parameters
*
* @since 1.5
+ *
+ * @jls 8.4.3 Method Modifiers
*/
+ @Override
public String toGenericString() {
- try {
- StringBuilder sb = new StringBuilder();
- int mod = getModifiers() & Modifier.methodModifiers();
- if (mod != 0) {
- sb.append(Modifier.toString(mod)).append(' ');
- }
- TypeVariable<?>[] typeparms = getTypeParameters();
- if (typeparms.length > 0) {
- boolean first = true;
- sb.append('<');
- for(TypeVariable<?> typeparm: typeparms) {
- if (!first)
- sb.append(',');
- // Class objects can't occur here; no need to test
- // and call Class.getName().
- sb.append(typeparm.toString());
- first = false;
- }
- sb.append("> ");
- }
+ return sharedToGenericString(Modifier.methodModifiers(), isDefault());
+ }
- Type genRetType = getGenericReturnType();
- sb.append( ((genRetType instanceof Class<?>)?
- Field.getTypeName((Class<?>)genRetType):genRetType.toString()))
- .append(' ');
-
- sb.append(Field.getTypeName(getDeclaringClass())).append('.');
- sb.append(getName()).append('(');
- Type[] params = getGenericParameterTypes();
- for (int j = 0; j < params.length; j++) {
- String param = (params[j] instanceof Class)?
- Field.getTypeName((Class)params[j]):
- (params[j].toString());
- if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
- param = param.replaceFirst("\\[\\]$", "...");
- sb.append(param);
- if (j < (params.length - 1))
- sb.append(',');
- }
- sb.append(')');
- Type[] exceptions = getGenericExceptionTypes();
- if (exceptions.length > 0) {
- sb.append(" throws ");
- for (int k = 0; k < exceptions.length; k++) {
- sb.append((exceptions[k] instanceof Class)?
- ((Class)exceptions[k]).getName():
- exceptions[k].toString());
- if (k < (exceptions.length - 1))
- sb.append(',');
- }
- }
- return sb.toString();
- } catch (Exception e) {
- return "<" + e + ">";
- }
+ @Override
+ void specificToGenericStringHeader(StringBuilder sb) {
+ Type genRetType = getGenericReturnType();
+ sb.append(genRetType.getTypeName()).append(' ');
+ sb.append(getDeclaringClass().getTypeName()).append('.');
+ sb.append(getName());
}
/**
@@ -594,7 +483,7 @@ public final
if (ma == null) {
ma = acquireMethodAccessor();
}
- return ma.invoke(obj, args, CallerID.getCallerID());
+ return ma.invoke(obj, args, ikvm.internal.CallerID.getCallerID());
}
/**
@@ -610,28 +499,41 @@ public final
}
/**
- * Returns {@code true} if this method was declared to take
- * a variable number of arguments; returns {@code false}
- * otherwise.
- *
- * @return {@code true} if an only if this method was declared to
- * take a variable number of arguments.
+ * {@inheritDoc}
* @since 1.5
*/
+ @Override
public boolean isVarArgs() {
- return (getModifiers() & Modifier.VARARGS) != 0;
+ return super.isVarArgs();
}
/**
- * Returns {@code true} if this method is a synthetic
+ * {@inheritDoc}
+ * @jls 13.1 The Form of a Binary
+ * @since 1.5
+ */
+ @Override
+ public boolean isSynthetic() {
+ return super.isSynthetic();
+ }
+
+ /**
+ * Returns {@code true} if this method is a default
* method; returns {@code false} otherwise.
*
- * @return true if and only if this method is a synthetic
+ * A default method is a public non-abstract instance method, that
+ * is, a non-static method with a body, declared in an interface
+ * type.
+ *
+ * @return true if and only if this method is a default
* method as defined by the Java Language Specification.
- * @since 1.5
+ * @since 1.8
*/
- public boolean isSynthetic() {
- return Modifier.isSynthetic(getModifiers());
+ public boolean isDefault() {
+ // Default methods are public non-abstract instance methods
+ // declared in an interface.
+ return ((getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) ==
+ Modifier.PUBLIC) && getDeclaringClass().isInterface();
}
// NOTE that there is no synchronization used here. It is correct
@@ -671,37 +573,6 @@ public final
}
/**
- * @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
-
- return (T) declaredAnnotations().get(annotationClass);
- }
-
- private static final Annotation[] EMPTY_ANNOTATION_ARRAY=new Annotation[0];
-
- /**
- * @since 1.5
- */
- public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATION_ARRAY);
- }
-
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
-
- private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
- if (declaredAnnotations == null) {
- declaredAnnotations = getDeclaredAnnotationsImpl(this);
- }
- return declaredAnnotations;
- }
-
- static native Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationsImpl(Object methodOrConstructor);
-
- /**
* Returns the default value for the annotation member represented by
* this {@code Method} instance. If the member is of a primitive type,
* an instance of the corresponding wrapper type is returned. Returns
@@ -718,32 +589,42 @@ public final
public native Object getDefaultValue();
/**
- * Returns an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by
- * this {@code Method} object. (Returns an array of length zero if the
- * underlying method is parameterless. If the method has one or more
- * parameters, a nested array of length zero is returned for each parameter
- * with no annotations.) The annotation objects contained in the returned
- * arrays are serializable. The caller of this method is free to modify
- * the returned arrays; it will have no effect on the arrays returned to
- * other callers.
- *
- * @return an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by this
- * Method object
+ * {@inheritDoc}
+ * @throws NullPointerException {@inheritDoc}
+ * @since 1.5
+ */
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+ return super.getAnnotation(annotationClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations() {
+ return super.getDeclaredAnnotations();
+ }
+
+ /**
+ * {@inheritDoc}
* @since 1.5
*/
+ @Override
public Annotation[][] getParameterAnnotations() {
- Annotation[][] result = getParameterAnnotationsImpl(this);
- int numParameters = parameterTypes.length;
- if (result == null)
- return new Annotation[numParameters][0];
+ return sharedGetParameterAnnotations(parameterTypes);
+ }
- if (result.length != numParameters)
- throw new java.lang.annotation.AnnotationFormatError(
- "Parameter annotations don't match number of parameters");
- return result;
+ /**
+ * {@inheritDoc}
+ * @since 1.8
+ */
+ @Override
+ public AnnotatedType getAnnotatedReturnType() {
+ return getAnnotatedReturnType0(getGenericReturnType());
}
- static native Annotation[][] getParameterAnnotationsImpl(Object methodOrConstructor);
+ @Override
+ void handleParameterNumberMismatch(int resultLength, int numParameters) {
+ throw new AnnotationFormatError("Parameter annotations don't match number of parameters");
+ }
}
diff --git a/openjdk/java/lang/reflect/Proxy.java b/openjdk/java/lang/reflect/Proxy.java
index 3d9850e0..de7416db 100644
--- a/openjdk/java/lang/reflect/Proxy.java
+++ b/openjdk/java/lang/reflect/Proxy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,20 +25,17 @@
package java.lang.reflect;
-import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.security.AccessController;
-import java.security.Permission;
import java.security.PrivilegedAction;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.Map;
-import java.util.Set;
-import java.util.List;
-import java.util.WeakHashMap;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiFunction;
import sun.misc.ProxyGenerator;
+import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
@@ -52,16 +49,14 @@ import sun.security.util.SecurityConstants;
* <p>To create a proxy for some interface {@code Foo}:
* <pre>
* InvocationHandler handler = new MyInvocationHandler(...);
- * Class proxyClass = Proxy.getProxyClass(
- * Foo.class.getClassLoader(), new Class[] { Foo.class });
- * Foo f = (Foo) proxyClass.
- * getConstructor(new Class[] { InvocationHandler.class }).
- * newInstance(new Object[] { handler });
+ * Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
+ * Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
+ * newInstance(handler);
* </pre>
* or more simply:
* <pre>
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
- * new Class[] { Foo.class },
+ * new Class&lt;?&gt;[] { Foo.class },
* handler);
* </pre>
*
@@ -90,7 +85,11 @@ import sun.security.util.SecurityConstants;
* <p>A proxy class has the following properties:
*
* <ul>
- * <li>Proxy classes are public, final, and not abstract.
+ * <li>Proxy classes are <em>public, final, and not abstract</em> if
+ * all proxy interfaces are public.</li>
+ *
+ * <li>Proxy classes are <em>non-public, final, and not abstract</em> if
+ * any of the proxy interfaces is non-public.</li>
*
* <li>The unqualified name of a proxy class is unspecified. The space
* of class names that begin with the string {@code "$Proxy"}
@@ -230,27 +229,15 @@ public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
- /** prefix for all proxy class names */
- private final static String proxyClassNamePrefix = "$Proxy";
-
/** parameter types of a proxy class constructor */
- private final static Class[] constructorParams =
+ private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
- /** maps a class loader to the proxy class cache for that loader */
- private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
- = new WeakHashMap<>();
-
- /** marks that a particular proxy class is currently being generated */
- private static Object pendingGenerationMarker = new Object();
-
- /** next number to use for generation of unique proxy class names */
- private static long nextUniqueNumber = 0;
- private static Object nextUniqueNumberLock = new Object();
-
- /** set of all generated proxy classes, for isProxyClass implementation */
- private static Map<Class<?>, Void> proxyClasses =
- Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
+ /**
+ * a cache of proxy classes
+ */
+ private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
+ proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
/**
* the invocation handler for this proxy instance.
@@ -269,77 +256,24 @@ public class Proxy implements java.io.Serializable {
* (typically, a dynamic proxy class) with the specified value
* for its invocation handler.
*
- * @param h the invocation handler for this proxy instance
+ * @param h the invocation handler for this proxy instance
+ *
+ * @throws NullPointerException if the given invocation handler, {@code h},
+ * is {@code null}.
*/
protected Proxy(InvocationHandler h) {
- doNewInstanceCheck();
+ Objects.requireNonNull(h);
this.h = h;
}
- private static class ProxyAccessHelper {
- // The permission is implementation specific.
- static final Permission PROXY_PERMISSION =
- new ReflectPermission("proxyConstructorNewInstance");
- // These system properties are defined to provide a short-term
- // workaround if customers need to disable the new security checks.
- static final boolean allowNewInstance;
- static final boolean allowNullLoader;
- static {
- allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
- allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
- }
-
- private static boolean getBooleanProperty(final String key) {
- String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- return System.getProperty(key);
- }
- });
- return Boolean.valueOf(s);
- }
-
- static boolean needsNewInstanceCheck(Class<?> proxyClass) {
- if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
- return false;
- }
-
- if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
- for (Class<?> intf : proxyClass.getInterfaces()) {
- if (!Modifier.isPublic(intf.getModifiers())) {
- return true;
- }
- }
- }
- return false;
- }
- }
-
- /*
- * Access check on a proxy class that implements any non-public interface.
- *
- * @throws SecurityException if a security manager exists, and
- * the caller does not have the permission.
- */
- private void doNewInstanceCheck() {
- SecurityManager sm = System.getSecurityManager();
- Class<?> proxyClass = this.getClass();
- if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
- try {
- sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
- } catch (SecurityException e) {
- throw new SecurityException("Not allowed to construct a Proxy "
- + "instance that implements a non-public interface", e);
- }
- }
- }
-
/**
* Returns the {@code java.lang.Class} object for a proxy class
* given a class loader and an array of interfaces. The proxy class
* will be defined by the specified class loader and will implement
- * all of the supplied interfaces. If a proxy class for the same
- * permutation of interfaces has already been defined by the class
- * loader, then the existing proxy class will be returned; otherwise,
+ * all of the supplied interfaces. If any of the given interfaces
+ * is non-public, the proxy class will be non-public. If a proxy class
+ * for the same permutation of interfaces has already been defined by the
+ * class loader, then the existing proxy class will be returned; otherwise,
* a proxy class for those interfaces will be generated dynamically
* and defined by the class loader.
*
@@ -404,6 +338,22 @@ public class Proxy implements java.io.Serializable {
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
+ * @throws SecurityException if a security manager, <em>s</em>, is present
+ * and any of the following conditions is met:
+ * <ul>
+ * <li> the given {@code loader} is {@code null} and
+ * the caller's class loader is not {@code null} and the
+ * invocation of {@link SecurityManager#checkPermission
+ * s.checkPermission} with
+ * {@code RuntimePermission("getClassLoader")} permission
+ * denies access.</li>
+ * <li> for each proxy interface, {@code intf},
+ * the caller's class loader is not the same as or an
+ * ancestor of the class loader for {@code intf} and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to {@code intf}.</li>
+ * </ul>
+
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
*/
@@ -412,12 +362,13 @@ public class Proxy implements java.io.Serializable {
Class<?>... interfaces)
throws IllegalArgumentException
{
- SecurityManager sm = System.getSecurityManager();
+ final Class<?>[] intfs = interfaces.clone();
+ final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
+ checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
- return getProxyClass0(loader, interfaces);
+ return getProxyClass0(loader, intfs);
}
/*
@@ -445,10 +396,8 @@ public class Proxy implements java.io.Serializable {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader ccl = caller.getClassLoader();
- if (loader == null && ccl != null) {
- if (!ProxyAccessHelper.allowNullLoader) {
- sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
- }
+ if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
@@ -464,142 +413,204 @@ public class Proxy implements java.io.Serializable {
throw new IllegalArgumentException("interface limit exceeded");
}
- Class<?> proxyClass = null;
+ // If the proxy class defined by the given loader implementing
+ // the given interfaces exists, this will simply return the cached copy;
+ // otherwise, it will create the proxy class via the ProxyClassFactory
+ return proxyClassCache.get(loader, interfaces);
+ }
- /* collect interface names to use as key for proxy class cache */
- String[] interfaceNames = new String[interfaces.length];
+ /*
+ * a key used for proxy class with 0 implemented interfaces
+ */
+ private static final Object key0 = new Object();
- // for detecting duplicates
- Set<Class<?>> interfaceSet = new HashSet<>();
+ /*
+ * Key1 and Key2 are optimized for the common use of dynamic proxies
+ * that implement 1 or 2 interfaces.
+ */
- for (int i = 0; i < interfaces.length; i++) {
- /*
- * Verify that the class loader resolves the name of this
- * interface to the same Class object.
- */
- String interfaceName = interfaces[i].getName();
- Class<?> interfaceClass = null;
- try {
- interfaceClass = Class.forName(interfaceName, false, loader);
- } catch (ClassNotFoundException e) {
- }
- if (interfaceClass != interfaces[i]) {
- throw new IllegalArgumentException(
- interfaces[i] + " is not visible from class loader");
- }
+ /*
+ * a key used for proxy class with 1 implemented interface
+ */
+ private static final class Key1 extends WeakReference<Class<?>> {
+ private final int hash;
- /*
- * Verify that the Class object actually represents an
- * interface.
- */
- if (!interfaceClass.isInterface()) {
- throw new IllegalArgumentException(
- interfaceClass.getName() + " is not an interface");
- }
+ Key1(Class<?> intf) {
+ super(intf);
+ this.hash = intf.hashCode();
+ }
- /*
- * Verify that this interface is not a duplicate.
- */
- if (interfaceSet.contains(interfaceClass)) {
- throw new IllegalArgumentException(
- "repeated interface: " + interfaceClass.getName());
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ Class<?> intf;
+ return this == obj ||
+ obj != null &&
+ obj.getClass() == Key1.class &&
+ (intf = get()) != null &&
+ intf == ((Key1) obj).get();
+ }
+ }
+
+ /*
+ * a key used for proxy class with 2 implemented interfaces
+ */
+ private static final class Key2 extends WeakReference<Class<?>> {
+ private final int hash;
+ private final WeakReference<Class<?>> ref2;
+
+ Key2(Class<?> intf1, Class<?> intf2) {
+ super(intf1);
+ hash = 31 * intf1.hashCode() + intf2.hashCode();
+ ref2 = new WeakReference<Class<?>>(intf2);
+ }
+
+ @Override
+ public int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ Class<?> intf1, intf2;
+ return this == obj ||
+ obj != null &&
+ obj.getClass() == Key2.class &&
+ (intf1 = get()) != null &&
+ intf1 == ((Key2) obj).get() &&
+ (intf2 = ref2.get()) != null &&
+ intf2 == ((Key2) obj).ref2.get();
+ }
+ }
+
+ /*
+ * a key used for proxy class with any number of implemented interfaces
+ * (used here for 3 or more only)
+ */
+ private static final class KeyX {
+ private final int hash;
+ private final WeakReference<Class<?>>[] refs;
+
+ @SuppressWarnings("unchecked")
+ KeyX(Class<?>[] interfaces) {
+ hash = Arrays.hashCode(interfaces);
+ refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
+ for (int i = 0; i < interfaces.length; i++) {
+ refs[i] = new WeakReference<>(interfaces[i]);
}
- interfaceSet.add(interfaceClass);
+ }
- interfaceNames[i] = interfaceName;
+ @Override
+ public int hashCode() {
+ return hash;
}
- /*
- * Using string representations of the proxy interfaces as
- * keys in the proxy class cache (instead of their Class
- * objects) is sufficient because we require the proxy
- * interfaces to be resolvable by name through the supplied
- * class loader, and it has the advantage that using a string
- * representation of a class makes for an implicit weak
- * reference to the class.
- */
- List<String> key = Arrays.asList(interfaceNames);
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj ||
+ obj != null &&
+ obj.getClass() == KeyX.class &&
+ equals(refs, ((KeyX) obj).refs);
+ }
- /*
- * Find or create the proxy class cache for the class loader.
- */
- Map<List<String>, Object> cache;
- synchronized (loaderToCache) {
- cache = loaderToCache.get(loader);
- if (cache == null) {
- cache = new HashMap<>();
- loaderToCache.put(loader, cache);
+ private static boolean equals(WeakReference<Class<?>>[] refs1,
+ WeakReference<Class<?>>[] refs2) {
+ if (refs1.length != refs2.length) {
+ return false;
}
- /*
- * This mapping will remain valid for the duration of this
- * method, without further synchronization, because the mapping
- * will only be removed if the class loader becomes unreachable.
- */
+ for (int i = 0; i < refs1.length; i++) {
+ Class<?> intf = refs1[i].get();
+ if (intf == null || intf != refs2[i].get()) {
+ return false;
+ }
+ }
+ return true;
}
+ }
- /*
- * Look up the list of interfaces in the proxy class cache using
- * the key. This lookup will result in one of three possible
- * kinds of values:
- * null, if there is currently no proxy class for the list of
- * interfaces in the class loader,
- * the pendingGenerationMarker object, if a proxy class for the
- * list of interfaces is currently being generated,
- * or a weak reference to a Class object, if a proxy class for
- * the list of interfaces has already been generated.
- */
- synchronized (cache) {
- /*
- * Note that we need not worry about reaping the cache for
- * entries with cleared weak references because if a proxy class
- * has been garbage collected, its class loader will have been
- * garbage collected as well, so the entire cache will be reaped
- * from the loaderToCache map.
- */
- do {
- Object value = cache.get(key);
- if (value instanceof Reference) {
- proxyClass = (Class<?>) ((Reference) value).get();
+ /**
+ * A function that maps an array of interfaces to an optimal key where
+ * Class objects representing interfaces are weakly referenced.
+ */
+ private static final class KeyFactory
+ implements BiFunction<ClassLoader, Class<?>[], Object>
+ {
+ @Override
+ public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
+ switch (interfaces.length) {
+ case 1: return new Key1(interfaces[0]); // the most frequent
+ case 2: return new Key2(interfaces[0], interfaces[1]);
+ case 0: return key0;
+ default: return new KeyX(interfaces);
+ }
+ }
+ }
+
+ /**
+ * A factory function that generates, defines and returns the proxy class given
+ * the ClassLoader and array of interfaces.
+ */
+ private static final class ProxyClassFactory
+ implements BiFunction<ClassLoader, Class<?>[], Class<?>>
+ {
+ // prefix for all proxy class names
+ private static final String proxyClassNamePrefix = "$Proxy";
+
+ // next number to use for generation of unique proxy class names
+ private static final AtomicLong nextUniqueNumber = new AtomicLong();
+
+ @Override
+ public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
+
+ Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
+ for (Class<?> intf : interfaces) {
+ /*
+ * Verify that the class loader resolves the name of this
+ * interface to the same Class object.
+ */
+ Class<?> interfaceClass = null;
+ try {
+ interfaceClass = Class.forName(intf.getName(), false, loader);
+ } catch (ClassNotFoundException e) {
}
- if (proxyClass != null) {
- // proxy class already generated: return it
- return proxyClass;
- } else if (value == pendingGenerationMarker) {
- // proxy class being generated: wait for it
- try {
- cache.wait();
- } catch (InterruptedException e) {
- /*
- * The class generation that we are waiting for should
- * take a small, bounded time, so we can safely ignore
- * thread interrupts here.
- */
- }
- continue;
- } else {
- /*
- * No proxy class for this list of interfaces has been
- * generated or is being generated, so we will go and
- * generate it now. Mark it as pending generation.
- */
- cache.put(key, pendingGenerationMarker);
- break;
+ if (interfaceClass != intf) {
+ throw new IllegalArgumentException(
+ intf + " is not visible from class loader");
}
- } while (true);
- }
+ /*
+ * Verify that the Class object actually represents an
+ * interface.
+ */
+ if (!interfaceClass.isInterface()) {
+ throw new IllegalArgumentException(
+ interfaceClass.getName() + " is not an interface");
+ }
+ /*
+ * Verify that this interface is not a duplicate.
+ */
+ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
+ throw new IllegalArgumentException(
+ "repeated interface: " + interfaceClass.getName());
+ }
+ }
- try {
String proxyPkg = null; // package to define proxy class in
+ int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
- for (int i = 0; i < interfaces.length; i++) {
- int flags = interfaces[i].getModifiers();
+ for (Class<?> intf : interfaces) {
+ int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
- String name = interfaces[i].getName();
+ accessFlags = Modifier.FINAL;
+ String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
@@ -616,77 +627,42 @@ public class Proxy implements java.io.Serializable {
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
-generate: do
- {
- /*
- * Choose a name for the proxy class to generate.
- */
- long num;
- synchronized (nextUniqueNumberLock) {
- num = nextUniqueNumber++;
- }
- String proxyName = proxyPkg + proxyClassNamePrefix + num;
- /*
- * Verify that the class loader hasn't already
- * defined a class with the chosen name.
- */
-
- proxyClass = getPrecompiledProxy(loader, proxyName, interfaces);
- if (proxyClass != null)
- break generate;
+ /*
+ * Choose a name for the proxy class to generate.
+ */
+ long num = nextUniqueNumber.getAndIncrement();
+ String proxyName = proxyPkg + proxyClassNamePrefix + num;
- /*
- * Generate the specified proxy class.
- */
- byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
- proxyName, interfaces);
- try {
- proxyClass = defineClass0(loader, proxyName,
- proxyClassFile, 0, proxyClassFile.length);
- } catch (ClassFormatError e) {
- /*
- * A ClassFormatError here means that (barring bugs in the
- * proxy class generation code) there was some other
- * invalid aspect of the arguments supplied to the proxy
- * class creation (such as virtual machine limitations
- * exceeded).
- */
- throw new IllegalArgumentException(e.toString());
- }
+ Class precompiledProxyClass = getPrecompiledProxy(loader, proxyName, interfaces);
+ if (precompiledProxyClass != null) {
+ return precompiledProxyClass;
}
- while (false);
- // add to set of all generated proxy classes, for isProxyClass
- proxyClasses.put(proxyClass, null);
- } finally {
/*
- * We must clean up the "pending generation" state of the proxy
- * class cache entry somehow. If a proxy class was successfully
- * generated, store it in the cache (with a weak reference);
- * otherwise, remove the reserved entry. In all cases, notify
- * all waiters on reserved entries in this cache.
+ * Generate the specified proxy class.
*/
- synchronized (cache) {
- if (proxyClass != null) {
- cache.put(key, new WeakReference<Class<?>>(proxyClass));
- } else {
- cache.remove(key);
- }
- cache.notifyAll();
+ byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
+ proxyName, interfaces, accessFlags);
+ try {
+ return defineClass0(loader, proxyName,
+ proxyClassFile, 0, proxyClassFile.length);
+ } catch (ClassFormatError e) {
+ /*
+ * A ClassFormatError here means that (barring bugs in the
+ * proxy class generation code) there was some other
+ * invalid aspect of the arguments supplied to the proxy
+ * class creation (such as virtual machine limitations
+ * exceeded).
+ */
+ throw new IllegalArgumentException(e.toString());
}
}
- return proxyClass;
}
/**
* Returns an instance of a proxy class for the specified interfaces
* that dispatches method invocations to the specified invocation
- * handler. This method is equivalent to:
- * <pre>
- * Proxy.getProxyClass(loader, interfaces).
- * getConstructor(new Class[] { InvocationHandler.class }).
- * newInstance(new Object[] { handler });
- * </pre>
+ * handler.
*
* <p>{@code Proxy.newProxyInstance} throws
* {@code IllegalArgumentException} for the same reasons that
@@ -702,6 +678,27 @@ generate: do
* @throws IllegalArgumentException if any of the restrictions on the
* parameters that may be passed to {@code getProxyClass}
* are violated
+ * @throws SecurityException if a security manager, <em>s</em>, is present
+ * and any of the following conditions is met:
+ * <ul>
+ * <li> the given {@code loader} is {@code null} and
+ * the caller's class loader is not {@code null} and the
+ * invocation of {@link SecurityManager#checkPermission
+ * s.checkPermission} with
+ * {@code RuntimePermission("getClassLoader")} permission
+ * denies access;</li>
+ * <li> for each proxy interface, {@code intf},
+ * the caller's class loader is not the same as or an
+ * ancestor of the class loader for {@code intf} and
+ * invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to {@code intf};</li>
+ * <li> any of the given proxy interfaces is non-public and the
+ * caller class is not in the same {@linkplain Package runtime package}
+ * as the non-public interface and the invocation of
+ * {@link SecurityManager#checkPermission s.checkPermission} with
+ * {@code ReflectPermission("newProxyInPackage.{package name}")}
+ * permission denies access.</li>
+ * </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
@@ -713,53 +710,70 @@ generate: do
InvocationHandler h)
throws IllegalArgumentException
{
- if (h == null) {
- throw new NullPointerException();
- }
+ Objects.requireNonNull(h);
+ final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
- checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
+ checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
- Class<?> cl = getProxyClass0(loader, interfaces);
+ Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
+ if (sm != null) {
+ checkNewProxyPermission(Reflection.getCallerClass(), cl);
+ }
+
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
- if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
- // create proxy instance with doPrivilege as the proxy class may
- // implement non-public interfaces that requires a special permission
- return AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- return newInstance(cons, ih);
+ if (!Modifier.isPublic(cl.getModifiers())) {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ cons.setAccessible(true);
+ return null;
}
});
- } else {
- return newInstance(cons, ih);
}
- } catch (NoSuchMethodException e) {
- throw new InternalError(e.toString());
- }
- }
-
- private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
- try {
- return cons.newInstance(new Object[] {h} );
- } catch (IllegalAccessException | InstantiationException e) {
- throw new InternalError(e.toString());
+ return cons.newInstance(new Object[]{h});
+ } catch (IllegalAccessException|InstantiationException e) {
+ throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
- throw new InternalError(t.toString());
+ throw new InternalError(t.toString(), t);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new InternalError(e.toString(), e);
+ }
+ }
+
+ private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
+ ClassLoader ccl = caller.getClassLoader();
+ ClassLoader pcl = proxyClass.getClassLoader();
+
+ // do permission check if the caller is in a different runtime package
+ // of the proxy class
+ int n = proxyClass.getName().lastIndexOf('.');
+ String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);
+
+ n = caller.getName().lastIndexOf('.');
+ String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
+
+ if (pcl != ccl || !pkg.equals(callerPkg)) {
+ sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
+ }
}
}
}
@@ -779,11 +793,7 @@ generate: do
* @throws NullPointerException if {@code cl} is {@code null}
*/
public static boolean isProxyClass(Class<?> cl) {
- if (cl == null) {
- throw new NullPointerException();
- }
-
- return proxyClasses.containsKey(cl);
+ return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
/**
@@ -793,7 +803,14 @@ generate: do
* @return the invocation handler for the proxy instance
* @throws IllegalArgumentException if the argument is not a
* proxy instance
+ * @throws SecurityException if a security manager, <em>s</em>, is present
+ * and the caller's class loader is not the same as or an
+ * ancestor of the class loader for the invocation handler
+ * and invocation of {@link SecurityManager#checkPackageAccess
+ * s.checkPackageAccess()} denies access to the invocation
+ * handler's class.
*/
+ @CallerSensitive
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
@@ -804,12 +821,23 @@ generate: do
throw new IllegalArgumentException("not a proxy instance");
}
- Proxy p = (Proxy) proxy;
- return p.h;
+ final Proxy p = (Proxy) proxy;
+ final InvocationHandler ih = p.h;
+ if (System.getSecurityManager() != null) {
+ Class<?> ihClass = ih.getClass();
+ Class<?> caller = Reflection.getCallerClass();
+ if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
+ ihClass.getClassLoader()))
+ {
+ ReflectUtil.checkPackageAccess(ihClass);
+ }
+ }
+
+ return ih;
}
- private static native Class defineClass0(ClassLoader loader, String name,
- byte[] b, int off, int len);
+ private static native Class<?> defineClass0(ClassLoader loader, String name,
+ byte[] b, int off, int len);
private static native Class<?> getPrecompiledProxy(ClassLoader loader, String proxyName, Class[] interfaces);
}
diff --git a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java
index 1f4ed69b..98e364d3 100644
--- a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java
+++ b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -263,15 +263,14 @@ static int socketReceiveOrPeekData
packetBuffer = dpObj.buf;
packetBufferOffset = dpObj.offset;
packetBufferLen = dpObj.bufLength;
+ /* Note: the buffer needn't be greater than 65,536 (0xFFFF)
+ * the max size of an IP packet. Anything bigger is truncated anyway.
+ *-/
+ if (packetBufferLen > MAX_PACKET_LEN) {
+ packetBufferLen = MAX_PACKET_LEN;
+ }
- /*
if (packetBufferLen > MAX_BUFFER_LEN) {
- /* Note: the buffer needn't be greater than 65,536 (0xFFFF)
- * the max size of an IP packet. Anything bigger is truncated anyway.
- *-/
- if (packetBufferLen > MAX_PACKET_LEN) {
- packetBufferLen = MAX_PACKET_LEN;
- }
fullPacket = (char *)malloc(packetBufferLen);
if (!fullPacket) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
@@ -380,8 +379,10 @@ static int socketReceiveOrPeekData
int[] tmp = { port };
packetAddress = NET_SockaddrToInetAddress(sa, tmp);
port = tmp[0];
- /* stuff the new Inetaddress into the packet */
- dpObj.address = packetAddress;
+ if (packetAddress != NULL) {
+ /* stuff the new Inetaddress into the packet */
+ dpObj.address = packetAddress;
+ }
}
/* populate the packet */
diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java
index d84a427b..1b44ccec 100644
--- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java
+++ b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java
@@ -515,6 +515,9 @@ static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this,
}
}
} else {
+ /* NET_BindV6() closes both sockets upon a failure */
+ _this.fd = null;
+ _this.fd1 = null;
NET_ThrowCurrent (env, "Cannot bind");
return;
}
diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
index d86e84d0..d51845e3 100644
--- a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
+++ b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -58,7 +58,6 @@ static final int java_net_SocketOptions_SO_LINGER = SocketOptions.SO_LINGER;
#include "java_net_SocketOptions.h"
#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_SocketImpl.h"
#include "java_net_InetAddress.h"
#include "java_io_FileDescriptor.h"
#include "java_lang_Integer.h"
@@ -486,6 +485,10 @@ static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this,
/* socket was re-created */
fd1Obj.setSocket(fd1);
}
+ } else {
+ /* NET_BindV6() closes both sockets upon a failure */
+ _this.fd = null;
+ _this.fd1 = null;
}
}
} else {
diff --git a/openjdk/java/net/net_util_md.java b/openjdk/java/net/net_util_md.java
index 724ba4cc..03fe929d 100644
--- a/openjdk/java/net/net_util_md.java
+++ b/openjdk/java/net/net_util_md.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -318,6 +318,11 @@ final class net_util_md
{
int rv;
+ if (level == IPPROTO_IPV6 && optname == IPV6_TCLASS) {
+ ((int[])optval)[0] = 0;
+ return 0;
+ }
+
rv = getsockopt(s, level, optname, optval);
@@ -645,17 +650,17 @@ final class net_util_md
* structure for an IPv4 InetAddress.
*/
static int NET_InetAddressToSockaddr(JNIEnv env, InetAddress iaObj, int port, SOCKETADDRESS him, boolean v4MappedAddress) {
- if (iaObj.family == InetAddress.IPv4) {
- him.set(new IPEndPoint(new IPAddress(htonl(iaObj.address) & 0xFFFFFFFFL), port));
+ if (iaObj.holder().family == InetAddress.IPv4) {
+ him.set(new IPEndPoint(new IPAddress(htonl(iaObj.holder().address) & 0xFFFFFFFFL), port));
return 0;
} else {
Inet6Address v6addr = (Inet6Address)iaObj;
int scope = v6addr.getScopeId();
if (scope == 0) {
- him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress), port));
+ him.set(new IPEndPoint(new IPAddress(v6addr.getAddress()), port));
return 0;
} else {
- him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress, scope & 0xFFFFFFFFL), port));
+ him.set(new IPEndPoint(new IPAddress(v6addr.getAddress(), scope & 0xFFFFFFFFL), port));
return 0;
}
}
@@ -725,7 +730,7 @@ final class net_util_md
}
static boolean NET_SockaddrEqualsInetAddress(SOCKETADDRESS him, InetAddress iaObj) {
- int family = iaObj.family == InetAddress.IPv4 ? AF_INET : AF_INET6;
+ int family = iaObj.holder().family == InetAddress.IPv4 ? AF_INET : AF_INET6;
if (him.sa_family == AF_INET6) {
byte[] caddrNew = him.him6.sin6_addr;
@@ -736,7 +741,7 @@ final class net_util_md
return false;
}
addrNew = NET_IPv4MappedToIPv4(caddrNew);
- addrCur = iaObj.address;
+ addrCur = iaObj.holder().address;
if (addrNew == addrCur) {
return true;
} else {
@@ -750,7 +755,7 @@ final class net_util_md
return false;
}
scope = ((Inet6Address)iaObj).getScopeId();
- caddrCur = ((Inet6Address)iaObj).ipaddress;
+ caddrCur = ((Inet6Address)iaObj).getAddress();
if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
return true;
} else {
@@ -763,7 +768,7 @@ final class net_util_md
return false;
}
addrNew = ntohl(him.him4.sin_addr.s_addr);
- addrCur = iaObj.address;
+ addrCur = iaObj.holder().address;
if (addrNew == addrCur) {
return true;
} else {
@@ -875,10 +880,10 @@ final class net_util_md
}
static int getInetAddress_addr(JNIEnv env, InetAddress iaObj) {
- return iaObj.address;
+ return iaObj.holder().address;
}
static int getInetAddress_family(JNIEnv env, InetAddress iaObj) {
- return iaObj.family;
+ return iaObj.holder().family;
}
}
diff --git a/openjdk/java/util/concurrent/ForkJoinPool.java b/openjdk/java/util/concurrent/ForkJoinPool.java
deleted file mode 100644
index 4b157962..00000000
--- a/openjdk/java/util/concurrent/ForkJoinPool.java
+++ /dev/null
@@ -1,3363 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-package java.util.concurrent;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.security.AccessControlContext;
-import java.security.ProtectionDomain;
-import java.security.Permissions;
-
-/**
- * An {@link ExecutorService} for running {@link ForkJoinTask}s.
- * A {@code ForkJoinPool} provides the entry point for submissions
- * from non-{@code ForkJoinTask} clients, as well as management and
- * monitoring operations.
- *
- * <p>A {@code ForkJoinPool} differs from other kinds of {@link
- * ExecutorService} mainly by virtue of employing
- * <em>work-stealing</em>: all threads in the pool attempt to find and
- * execute tasks submitted to the pool and/or created by other active
- * tasks (eventually blocking waiting for work if none exist). This
- * enables efficient processing when most tasks spawn other subtasks
- * (as do most {@code ForkJoinTask}s), as well as when many small
- * tasks are submitted to the pool from external clients. Especially
- * when setting <em>asyncMode</em> to true in constructors, {@code
- * ForkJoinPool}s may also be appropriate for use with event-style
- * tasks that are never joined.
- *
- * <p>A static {@link #commonPool()} is available and appropriate for
- * most applications. The common pool is used by any ForkJoinTask that
- * is not explicitly submitted to a specified pool. Using the common
- * pool normally reduces resource usage (its threads are slowly
- * reclaimed during periods of non-use, and reinstated upon subsequent
- * use).
- *
- * <p>For applications that require separate or custom pools, a {@code
- * ForkJoinPool} may be constructed with a given target parallelism
- * level; by default, equal to the number of available processors. The
- * pool attempts to maintain enough active (or available) threads by
- * dynamically adding, suspending, or resuming internal worker
- * threads, even if some tasks are stalled waiting to join others.
- * However, no such adjustments are guaranteed in the face of blocked
- * I/O or other unmanaged synchronization. The nested {@link
- * ManagedBlocker} interface enables extension of the kinds of
- * synchronization accommodated.
- *
- * <p>In addition to execution and lifecycle control methods, this
- * class provides status check methods (for example
- * {@link #getStealCount}) that are intended to aid in developing,
- * tuning, and monitoring fork/join applications. Also, method
- * {@link #toString} returns indications of pool state in a
- * convenient form for informal monitoring.
- *
- * <p>As is the case with other ExecutorServices, there are three
- * main task execution methods summarized in the following table.
- * These are designed to be used primarily by clients not already
- * engaged in fork/join computations in the current pool. The main
- * forms of these methods accept instances of {@code ForkJoinTask},
- * but overloaded forms also allow mixed execution of plain {@code
- * Runnable}- or {@code Callable}- based activities as well. However,
- * tasks that are already executing in a pool should normally instead
- * use the within-computation forms listed in the table unless using
- * async event-style tasks that are not usually joined, in which case
- * there is little difference among choice of methods.
- *
- * <table BORDER CELLPADDING=3 CELLSPACING=1>
- * <caption>Summary of task execution methods</caption>
- * <tr>
- * <td></td>
- * <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td>
- * <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td>
- * </tr>
- * <tr>
- * <td> <b>Arrange async execution</b></td>
- * <td> {@link #execute(ForkJoinTask)}</td>
- * <td> {@link ForkJoinTask#fork}</td>
- * </tr>
- * <tr>
- * <td> <b>Await and obtain result</b></td>
- * <td> {@link #invoke(ForkJoinTask)}</td>
- * <td> {@link ForkJoinTask#invoke}</td>
- * </tr>
- * <tr>
- * <td> <b>Arrange exec and obtain Future</b></td>
- * <td> {@link #submit(ForkJoinTask)}</td>
- * <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td>
- * </tr>
- * </table>
- *
- * <p>The common pool is by default constructed with default
- * parameters, but these may be controlled by setting three
- * {@linkplain System#getProperty system properties}:
- * <ul>
- * <li>{@code java.util.concurrent.ForkJoinPool.common.parallelism}
- * - the parallelism level, a non-negative integer
- * <li>{@code java.util.concurrent.ForkJoinPool.common.threadFactory}
- * - the class name of a {@link ForkJoinWorkerThreadFactory}
- * <li>{@code java.util.concurrent.ForkJoinPool.common.exceptionHandler}
- * - the class name of a {@link UncaughtExceptionHandler}
- * </ul>
- * If a {@link SecurityManager} is present and no factory is
- * specified, then the default pool uses a factory supplying
- * threads that have no {@link Permissions} enabled.
- * The system class loader is used to load these classes.
- * Upon any error in establishing these settings, default parameters
- * are used. It is possible to disable or limit the use of threads in
- * the common pool by setting the parallelism property to zero, and/or
- * using a factory that may return {@code null}. However doing so may
- * cause unjoined tasks to never be executed.
- *
- * <p><b>Implementation notes</b>: This implementation restricts the
- * maximum number of running threads to 32767. Attempts to create
- * pools with greater than the maximum number result in
- * {@code IllegalArgumentException}.
- *
- * <p>This implementation rejects submitted tasks (that is, by throwing
- * {@link RejectedExecutionException}) only when the pool is shut down
- * or internal resources have been exhausted.
- *
- * @since 1.7
- * @author Doug Lea
- */
-@sun.misc.Contended
-public class ForkJoinPool extends AbstractExecutorService {
-
- /*
- * Implementation Overview
- *
- * This class and its nested classes provide the main
- * functionality and control for a set of worker threads:
- * Submissions from non-FJ threads enter into submission queues.
- * Workers take these tasks and typically split them into subtasks
- * that may be stolen by other workers. Preference rules give
- * first priority to processing tasks from their own queues (LIFO
- * or FIFO, depending on mode), then to randomized FIFO steals of
- * tasks in other queues.
- *
- * WorkQueues
- * ==========
- *
- * Most operations occur within work-stealing queues (in nested
- * class WorkQueue). These are special forms of Deques that
- * support only three of the four possible end-operations -- push,
- * pop, and poll (aka steal), under the further constraints that
- * push and pop are called only from the owning thread (or, as
- * extended here, under a lock), while poll may be called from
- * other threads. (If you are unfamiliar with them, you probably
- * want to read Herlihy and Shavit's book "The Art of
- * Multiprocessor programming", chapter 16 describing these in
- * more detail before proceeding.) The main work-stealing queue
- * design is roughly similar to those in the papers "Dynamic
- * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
- * (http://research.sun.com/scalable/pubs/index.html) and
- * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
- * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
- * See also "Correct and Efficient Work-Stealing for Weak Memory
- * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
- * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
- * analysis of memory ordering (atomic, volatile etc) issues. The
- * main differences ultimately stem from GC requirements that we
- * null out taken slots as soon as we can, to maintain as small a
- * footprint as possible even in programs generating huge numbers
- * of tasks. To accomplish this, we shift the CAS arbitrating pop
- * vs poll (steal) from being on the indices ("base" and "top") to
- * the slots themselves. So, both a successful pop and poll
- * mainly entail a CAS of a slot from non-null to null. Because
- * we rely on CASes of references, we do not need tag bits on base
- * or top. They are simple ints as used in any circular
- * array-based queue (see for example ArrayDeque). Updates to the
- * indices must still be ordered in a way that guarantees that top
- * == base means the queue is empty, but otherwise may err on the
- * side of possibly making the queue appear nonempty when a push,
- * pop, or poll have not fully committed. Note that this means
- * that the poll operation, considered individually, is not
- * wait-free. One thief cannot successfully continue until another
- * in-progress one (or, if previously empty, a push) completes.
- * However, in the aggregate, we ensure at least probabilistic
- * non-blockingness. If an attempted steal fails, a thief always
- * chooses a different random victim target to try next. So, in
- * order for one thief to progress, it suffices for any
- * in-progress poll or new push on any empty queue to
- * complete. (This is why we normally use method pollAt and its
- * variants that try once at the apparent base index, else
- * consider alternative actions, rather than method poll.)
- *
- * This approach also enables support of a user mode in which local
- * task processing is in FIFO, not LIFO order, simply by using
- * poll rather than pop. This can be useful in message-passing
- * frameworks in which tasks are never joined. However neither
- * mode considers affinities, loads, cache localities, etc, so
- * rarely provide the best possible performance on a given
- * machine, but portably provide good throughput by averaging over
- * these factors. (Further, even if we did try to use such
- * information, we do not usually have a basis for exploiting it.
- * For example, some sets of tasks profit from cache affinities,
- * but others are harmed by cache pollution effects.)
- *
- * WorkQueues are also used in a similar way for tasks submitted
- * to the pool. We cannot mix these tasks in the same queues used
- * for work-stealing (this would contaminate lifo/fifo
- * processing). Instead, we randomly associate submission queues
- * with submitting threads, using a form of hashing. The
- * ThreadLocalRandom probe value serves as a hash code for
- * choosing existing queues, and may be randomly repositioned upon
- * contention with other submitters. In essence, submitters act
- * like workers except that they are restricted to executing local
- * tasks that they submitted (or in the case of CountedCompleters,
- * others with the same root task). However, because most
- * shared/external queue operations are more expensive than
- * internal, and because, at steady state, external submitters
- * will compete for CPU with workers, ForkJoinTask.join and
- * related methods disable them from repeatedly helping to process
- * tasks if all workers are active. Insertion of tasks in shared
- * mode requires a lock (mainly to protect in the case of
- * resizing) but we use only a simple spinlock (using bits in
- * field qlock), because submitters encountering a busy queue move
- * on to try or create other queues -- they block only when
- * creating and registering new queues.
- *
- * Management
- * ==========
- *
- * The main throughput advantages of work-stealing stem from
- * decentralized control -- workers mostly take tasks from
- * themselves or each other. We cannot negate this in the
- * implementation of other management responsibilities. The main
- * tactic for avoiding bottlenecks is packing nearly all
- * essentially atomic control state into two volatile variables
- * that are by far most often read (not written) as status and
- * consistency checks.
- *
- * Field "ctl" contains 64 bits holding all the information needed
- * to atomically decide to add, inactivate, enqueue (on an event
- * queue), dequeue, and/or re-activate workers. To enable this
- * packing, we restrict maximum parallelism to (1<<15)-1 (which is
- * far in excess of normal operating range) to allow ids, counts,
- * and their negations (used for thresholding) to fit into 16bit
- * fields.
- *
- * Field "plock" is a form of sequence lock with a saturating
- * shutdown bit (similarly for per-queue "qlocks"), mainly
- * protecting updates to the workQueues array, as well as to
- * enable shutdown. When used as a lock, it is normally only very
- * briefly held, so is nearly always available after at most a
- * brief spin, but we use a monitor-based backup strategy to
- * block when needed.
- *
- * Recording WorkQueues. WorkQueues are recorded in the
- * "workQueues" array that is created upon first use and expanded
- * if necessary. Updates to the array while recording new workers
- * and unrecording terminated ones are protected from each other
- * by a lock but the array is otherwise concurrently readable, and
- * accessed directly. To simplify index-based operations, the
- * array size is always a power of two, and all readers must
- * tolerate null slots. Worker queues are at odd indices. Shared
- * (submission) queues are at even indices, up to a maximum of 64
- * slots, to limit growth even if array needs to expand to add
- * more workers. Grouping them together in this way simplifies and
- * speeds up task scanning.
- *
- * All worker thread creation is on-demand, triggered by task
- * submissions, replacement of terminated workers, and/or
- * compensation for blocked workers. However, all other support
- * code is set up to work with other policies. To ensure that we
- * do not hold on to worker references that would prevent GC, ALL
- * accesses to workQueues are via indices into the workQueues
- * array (which is one source of some of the messy code
- * constructions here). In essence, the workQueues array serves as
- * a weak reference mechanism. Thus for example the wait queue
- * field of ctl stores indices, not references. Access to the
- * workQueues in associated methods (for example signalWork) must
- * both index-check and null-check the IDs. All such accesses
- * ignore bad IDs by returning out early from what they are doing,
- * since this can only be associated with termination, in which
- * case it is OK to give up. All uses of the workQueues array
- * also check that it is non-null (even if previously
- * non-null). This allows nulling during termination, which is
- * currently not necessary, but remains an option for
- * resource-revocation-based shutdown schemes. It also helps
- * reduce JIT issuance of uncommon-trap code, which tends to
- * unnecessarily complicate control flow in some methods.
- *
- * Event Queuing. Unlike HPC work-stealing frameworks, we cannot
- * let workers spin indefinitely scanning for tasks when none can
- * be found immediately, and we cannot start/resume workers unless
- * there appear to be tasks available. On the other hand, we must
- * quickly prod them into action when new tasks are submitted or
- * generated. In many usages, ramp-up time to activate workers is
- * the main limiting factor in overall performance (this is
- * compounded at program start-up by JIT compilation and
- * allocation). So we try to streamline this as much as possible.
- * We park/unpark workers after placing in an event wait queue
- * when they cannot find work. This "queue" is actually a simple
- * Treiber stack, headed by the "id" field of ctl, plus a 15bit
- * counter value (that reflects the number of times a worker has
- * been inactivated) to avoid ABA effects (we need only as many
- * version numbers as worker threads). Successors are held in
- * field WorkQueue.nextWait. Queuing deals with several intrinsic
- * races, mainly that a task-producing thread can miss seeing (and
- * signalling) another thread that gave up looking for work but
- * has not yet entered the wait queue. We solve this by requiring
- * a full sweep of all workers (via repeated calls to method
- * scan()) both before and after a newly waiting worker is added
- * to the wait queue. Because enqueued workers may actually be
- * rescanning rather than waiting, we set and clear the "parker"
- * field of WorkQueues to reduce unnecessary calls to unpark.
- * (This requires a secondary recheck to avoid missed signals.)
- * Note the unusual conventions about Thread.interrupts
- * surrounding parking and other blocking: Because interrupts are
- * used solely to alert threads to check termination, which is
- * checked anyway upon blocking, we clear status (using
- * Thread.interrupted) before any call to park, so that park does
- * not immediately return due to status being set via some other
- * unrelated call to interrupt in user code.
- *
- * Signalling. We create or wake up workers only when there
- * appears to be at least one task they might be able to find and
- * execute. When a submission is added or another worker adds a
- * task to a queue that has fewer than two tasks, they signal
- * waiting workers (or trigger creation of new ones if fewer than
- * the given parallelism level -- signalWork). These primary
- * signals are buttressed by others whenever other threads remove
- * a task from a queue and notice that there are other tasks there
- * as well. So in general, pools will be over-signalled. On most
- * platforms, signalling (unpark) overhead time is noticeably
- * long, and the time between signalling a thread and it actually
- * making progress can be very noticeably long, so it is worth
- * offloading these delays from critical paths as much as
- * possible. Additionally, workers spin-down gradually, by staying
- * alive so long as they see the ctl state changing. Similar
- * stability-sensing techniques are also used before blocking in
- * awaitJoin and helpComplete.
- *
- * Trimming workers. To release resources after periods of lack of
- * use, a worker starting to wait when the pool is quiescent will
- * time out and terminate if the pool has remained quiescent for a
- * given period -- a short period if there are more threads than
- * parallelism, longer as the number of threads decreases. This
- * will slowly propagate, eventually terminating all workers after
- * periods of non-use.
- *
- * Shutdown and Termination. A call to shutdownNow atomically sets
- * a plock bit and then (non-atomically) sets each worker's
- * qlock status, cancels all unprocessed tasks, and wakes up
- * all waiting workers. Detecting whether termination should
- * commence after a non-abrupt shutdown() call requires more work
- * and bookkeeping. We need consensus about quiescence (i.e., that
- * there is no more work). The active count provides a primary
- * indication but non-abrupt shutdown still requires a rechecking
- * scan for any workers that are inactive but not queued.
- *
- * Joining Tasks
- * =============
- *
- * Any of several actions may be taken when one worker is waiting
- * to join a task stolen (or always held) by another. Because we
- * are multiplexing many tasks on to a pool of workers, we can't
- * just let them block (as in Thread.join). We also cannot just
- * reassign the joiner's run-time stack with another and replace
- * it later, which would be a form of "continuation", that even if
- * possible is not necessarily a good idea since we sometimes need
- * both an unblocked task and its continuation to progress.
- * Instead we combine two tactics:
- *
- * Helping: Arranging for the joiner to execute some task that it
- * would be running if the steal had not occurred.
- *
- * Compensating: Unless there are already enough live threads,
- * method tryCompensate() may create or re-activate a spare
- * thread to compensate for blocked joiners until they unblock.
- *
- * A third form (implemented in tryRemoveAndExec) amounts to
- * helping a hypothetical compensator: If we can readily tell that
- * a possible action of a compensator is to steal and execute the
- * task being joined, the joining thread can do so directly,
- * without the need for a compensation thread (although at the
- * expense of larger run-time stacks, but the tradeoff is
- * typically worthwhile).
- *
- * The ManagedBlocker extension API can't use helping so relies
- * only on compensation in method awaitBlocker.
- *
- * The algorithm in tryHelpStealer entails a form of "linear"
- * helping: Each worker records (in field currentSteal) the most
- * recent task it stole from some other worker. Plus, it records
- * (in field currentJoin) the task it is currently actively
- * joining. Method tryHelpStealer uses these markers to try to
- * find a worker to help (i.e., steal back a task from and execute
- * it) that could hasten completion of the actively joined task.
- * In essence, the joiner executes a task that would be on its own
- * local deque had the to-be-joined task not been stolen. This may
- * be seen as a conservative variant of the approach in Wagner &
- * Calder "Leapfrogging: a portable technique for implementing
- * efficient futures" SIGPLAN Notices, 1993
- * (http://portal.acm.org/citation.cfm?id=155354). It differs in
- * that: (1) We only maintain dependency links across workers upon
- * steals, rather than use per-task bookkeeping. This sometimes
- * requires a linear scan of workQueues array to locate stealers,
- * but often doesn't because stealers leave hints (that may become
- * stale/wrong) of where to locate them. It is only a hint
- * because a worker might have had multiple steals and the hint
- * records only one of them (usually the most current). Hinting
- * isolates cost to when it is needed, rather than adding to
- * per-task overhead. (2) It is "shallow", ignoring nesting and
- * potentially cyclic mutual steals. (3) It is intentionally
- * racy: field currentJoin is updated only while actively joining,
- * which means that we miss links in the chain during long-lived
- * tasks, GC stalls etc (which is OK since blocking in such cases
- * is usually a good idea). (4) We bound the number of attempts
- * to find work (see MAX_HELP) and fall back to suspending the
- * worker and if necessary replacing it with another.
- *
- * Helping actions for CountedCompleters are much simpler: Method
- * helpComplete can take and execute any task with the same root
- * as the task being waited on. However, this still entails some
- * traversal of completer chains, so is less efficient than using
- * CountedCompleters without explicit joins.
- *
- * It is impossible to keep exactly the target parallelism number
- * of threads running at any given time. Determining the
- * existence of conservatively safe helping targets, the
- * availability of already-created spares, and the apparent need
- * to create new spares are all racy, so we rely on multiple
- * retries of each. Compensation in the apparent absence of
- * helping opportunities is challenging to control on JVMs, where
- * GC and other activities can stall progress of tasks that in
- * turn stall out many other dependent tasks, without us being
- * able to determine whether they will ever require compensation.
- * Even though work-stealing otherwise encounters little
- * degradation in the presence of more threads than cores,
- * aggressively adding new threads in such cases entails risk of
- * unwanted positive feedback control loops in which more threads
- * cause more dependent stalls (as well as delayed progress of
- * unblocked threads to the point that we know they are available)
- * leading to more situations requiring more threads, and so
- * on. This aspect of control can be seen as an (analytically
- * intractable) game with an opponent that may choose the worst
- * (for us) active thread to stall at any time. We take several
- * precautions to bound losses (and thus bound gains), mainly in
- * methods tryCompensate and awaitJoin.
- *
- * Common Pool
- * ===========
- *
- * The static common pool always exists after static
- * initialization. Since it (or any other created pool) need
- * never be used, we minimize initial construction overhead and
- * footprint to the setup of about a dozen fields, with no nested
- * allocation. Most bootstrapping occurs within method
- * fullExternalPush during the first submission to the pool.
- *
- * When external threads submit to the common pool, they can
- * perform subtask processing (see externalHelpJoin and related
- * methods). This caller-helps policy makes it sensible to set
- * common pool parallelism level to one (or more) less than the
- * total number of available cores, or even zero for pure
- * caller-runs. We do not need to record whether external
- * submissions are to the common pool -- if not, externalHelpJoin
- * returns quickly (at the most helping to signal some common pool
- * workers). These submitters would otherwise be blocked waiting
- * for completion, so the extra effort (with liberally sprinkled
- * task status checks) in inapplicable cases amounts to an odd
- * form of limited spin-wait before blocking in ForkJoinTask.join.
- *
- * As a more appropriate default in managed environments, unless
- * overridden by system properties, we use workers of subclass
- * InnocuousForkJoinWorkerThread when there is a SecurityManager
- * present. These workers have no permissions set, do not belong
- * to any user-defined ThreadGroup, and erase all ThreadLocals
- * after executing any top-level task (see WorkQueue.runTask). The
- * associated mechanics (mainly in ForkJoinWorkerThread) may be
- * JVM-dependent and must access particular Thread class fields to
- * achieve this effect.
- *
- * Style notes
- * ===========
- *
- * There is a lot of representation-level coupling among classes
- * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The
- * fields of WorkQueue maintain data structures managed by
- * ForkJoinPool, so are directly accessed. There is little point
- * trying to reduce this, since any associated future changes in
- * representations will need to be accompanied by algorithmic
- * changes anyway. Several methods intrinsically sprawl because
- * they must accumulate sets of consistent reads of volatiles held
- * in local variables. Methods signalWork() and scan() are the
- * main bottlenecks, so are especially heavily
- * micro-optimized/mangled. There are lots of inline assignments
- * (of form "while ((local = field) != 0)") which are usually the
- * simplest way to ensure the required read orderings (which are
- * sometimes critical). This leads to a "C"-like style of listing
- * declarations of these locals at the heads of methods or blocks.
- * There are several occurrences of the unusual "do {} while
- * (!cas...)" which is the simplest way to force an update of a
- * CAS'ed variable. There are also other coding oddities (including
- * several unnecessary-looking hoisted null checks) that help
- * some methods perform reasonably even when interpreted (not
- * compiled).
- *
- * The order of declarations in this file is:
- * (1) Static utility functions
- * (2) Nested (static) classes
- * (3) Static fields
- * (4) Fields, along with constants used when unpacking some of them
- * (5) Internal control methods
- * (6) Callbacks and other support for ForkJoinTask methods
- * (7) Exported methods
- * (8) Static block initializing statics in minimally dependent order
- */
-
- // Static utilities
-
- /**
- * If there is a security manager, makes sure caller has
- * permission to modify threads.
- */
- private static void checkPermission() {
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkPermission(modifyThreadPermission);
- }
-
- // Nested classes
-
- /**
- * Factory for creating new {@link ForkJoinWorkerThread}s.
- * A {@code ForkJoinWorkerThreadFactory} must be defined and used
- * for {@code ForkJoinWorkerThread} subclasses that extend base
- * functionality or initialize threads with different contexts.
- */
- public static interface ForkJoinWorkerThreadFactory {
- /**
- * Returns a new worker thread operating in the given pool.
- *
- * @param pool the pool this thread works in
- * @return the new worker thread
- * @throws NullPointerException if the pool is null
- */
- public ForkJoinWorkerThread newThread(ForkJoinPool pool);
- }
-
- /**
- * Default ForkJoinWorkerThreadFactory implementation; creates a
- * new ForkJoinWorkerThread.
- */
- static final class DefaultForkJoinWorkerThreadFactory
- implements ForkJoinWorkerThreadFactory {
- public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return new ForkJoinWorkerThread(pool);
- }
- }
-
- /**
- * Class for artificial tasks that are used to replace the target
- * of local joins if they are removed from an interior queue slot
- * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
- * actually do anything beyond having a unique identity.
- */
- static final class EmptyTask extends ForkJoinTask<Void> {
- private static final long serialVersionUID = -7721805057305804111L;
- EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
- public final Void getRawResult() { return null; }
- public final void setRawResult(Void x) {}
- public final boolean exec() { return true; }
- }
-
- /**
- * Queues supporting work-stealing as well as external task
- * submission. See above for main rationale and algorithms.
- * Implementation relies heavily on "Unsafe" intrinsics
- * and selective use of "volatile":
- *
- * Field "base" is the index (mod array.length) of the least valid
- * queue slot, which is always the next position to steal (poll)
- * from if nonempty. Reads and writes require volatile orderings
- * but not CAS, because updates are only performed after slot
- * CASes.
- *
- * Field "top" is the index (mod array.length) of the next queue
- * slot to push to or pop from. It is written only by owner thread
- * for push, or under lock for external/shared push, and accessed
- * by other threads only after reading (volatile) base. Both top
- * and base are allowed to wrap around on overflow, but (top -
- * base) (or more commonly -(base - top) to force volatile read of
- * base before top) still estimates size. The lock ("qlock") is
- * forced to -1 on termination, causing all further lock attempts
- * to fail. (Note: we don't need CAS for termination state because
- * upon pool shutdown, all shared-queues will stop being used
- * anyway.) Nearly all lock bodies are set up so that exceptions
- * within lock bodies are "impossible" (modulo JVM errors that
- * would cause failure anyway.)
- *
- * The array slots are read and written using the emulation of
- * volatiles/atomics provided by Unsafe. Insertions must in
- * general use putOrderedObject as a form of releasing store to
- * ensure that all writes to the task object are ordered before
- * its publication in the queue. All removals entail a CAS to
- * null. The array is always a power of two. To ensure safety of
- * Unsafe array operations, all accesses perform explicit null
- * checks and implicit bounds checks via power-of-two masking.
- *
- * In addition to basic queuing support, this class contains
- * fields described elsewhere to control execution. It turns out
- * to work better memory-layout-wise to include them in this class
- * rather than a separate class.
- *
- * Performance on most platforms is very sensitive to placement of
- * instances of both WorkQueues and their arrays -- we absolutely
- * do not want multiple WorkQueue instances or multiple queue
- * arrays sharing cache lines. (It would be best for queue objects
- * and their arrays to share, but there is nothing available to
- * help arrange that). The @Contended annotation alerts JVMs to
- * try to keep instances apart.
- */
- @sun.misc.Contended
- static final class WorkQueue {
- /**
- * Capacity of work-stealing queue array upon initialization.
- * Must be a power of two; at least 4, but should be larger to
- * reduce or eliminate cacheline sharing among queues.
- * Currently, it is much larger, as a partial workaround for
- * the fact that JVMs often place arrays in locations that
- * share GC bookkeeping (especially cardmarks) such that
- * per-write accesses encounter serious memory contention.
- */
- static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
-
- /**
- * Maximum size for queue arrays. Must be a power of two less
- * than or equal to 1 << (31 - width of array entry) to ensure
- * lack of wraparound of index calculations, but defined to a
- * value a bit less than this to help users trap runaway
- * programs before saturating systems.
- */
- static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
-
- volatile int eventCount; // encoded inactivation count; < 0 if inactive
- int nextWait; // encoded record of next event waiter
- int nsteals; // number of steals
- int hint; // steal index hint
- short poolIndex; // index of this queue in pool
- final short mode; // 0: lifo, > 0: fifo, < 0: shared
- volatile int qlock; // 1: locked, -1: terminate; else 0
- volatile int base; // index of next slot for poll
- int top; // index of next slot for push
- ForkJoinTask<?>[] array; // the elements (initially unallocated)
- final ForkJoinPool pool; // the containing pool (may be null)
- final ForkJoinWorkerThread owner; // owning thread or null if shared
- volatile Thread parker; // == owner during call to park; else null
- volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
- ForkJoinTask<?> currentSteal; // current non-local task being executed
-
- WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
- int seed) {
- this.pool = pool;
- this.owner = owner;
- this.mode = (short)mode;
- this.hint = seed; // store initial seed for runWorker
- // Place indices in the center of array (that is not yet allocated)
- base = top = INITIAL_QUEUE_CAPACITY >>> 1;
- }
-
- /**
- * Returns the approximate number of tasks in the queue.
- */
- final int queueSize() {
- int n = base - top; // non-owner callers must read base first
- return (n >= 0) ? 0 : -n; // ignore transient negative
- }
-
- /**
- * Provides a more accurate estimate of whether this queue has
- * any tasks than does queueSize, by checking whether a
- * near-empty queue has at least one unclaimed task.
- */
- final boolean isEmpty() {
- ForkJoinTask<?>[] a; int m, s;
- int n = base - (s = top);
- return (n >= 0 ||
- (n == -1 &&
- ((a = array) == null ||
- (m = a.length - 1) < 0 ||
- U.getObject
- (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
- }
-
- /**
- * Pushes a task. Call only by owner in unshared queues. (The
- * shared-queue version is embedded in method externalPush.)
- *
- * @param task the task. Caller must ensure non-null.
- * @throws RejectedExecutionException if array cannot be resized
- */
- final void push(ForkJoinTask<?> task) {
- ForkJoinTask<?>[] a; ForkJoinPool p;
- int s = top, n;
- if ((a = array) != null) { // ignore if queue removed
- int m = a.length - 1;
- U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
- if ((n = (top = s + 1) - base) <= 2)
- (p = pool).signalWork(p.workQueues, this);
- else if (n >= m)
- growArray();
- }
- }
-
- /**
- * Initializes or doubles the capacity of array. Call either
- * by owner or with lock held -- it is OK for base, but not
- * top, to move while resizings are in progress.
- */
- final ForkJoinTask<?>[] growArray() {
- ForkJoinTask<?>[] oldA = array;
- int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
- if (size > MAXIMUM_QUEUE_CAPACITY)
- throw new RejectedExecutionException("Queue capacity exceeded");
- int oldMask, t, b;
- ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
- if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
- (t = top) - (b = base) > 0) {
- int mask = size - 1;
- do {
- ForkJoinTask<?> x;
- int oldj = ((b & oldMask) << ASHIFT) + ABASE;
- int j = ((b & mask) << ASHIFT) + ABASE;
- x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
- if (x != null &&
- U.compareAndSwapObject(oldA, oldj, x, null))
- U.putObjectVolatile(a, j, x);
- } while (++b != t);
- }
- return a;
- }
-
- /**
- * Takes next task, if one exists, in LIFO order. Call only
- * by owner in unshared queues.
- */
- final ForkJoinTask<?> pop() {
- ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
- if ((a = array) != null && (m = a.length - 1) >= 0) {
- for (int s; (s = top - 1) - base >= 0;) {
- long j = ((m & s) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
- break;
- if (U.compareAndSwapObject(a, j, t, null)) {
- top = s;
- return t;
- }
- }
- }
- return null;
- }
-
- /**
- * Takes a task in FIFO order if b is base of queue and a task
- * can be claimed without contention. Specialized versions
- * appear in ForkJoinPool methods scan and tryHelpStealer.
- */
- final ForkJoinTask<?> pollAt(int b) {
- ForkJoinTask<?> t; ForkJoinTask<?>[] a;
- if ((a = array) != null) {
- int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
- base == b && U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- return t;
- }
- }
- return null;
- }
-
- /**
- * Takes next task, if one exists, in FIFO order.
- */
- final ForkJoinTask<?> poll() {
- ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
- while ((b = base) - top < 0 && (a = array) != null) {
- int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- if (t != null) {
- if (U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- return t;
- }
- }
- else if (base == b) {
- if (b + 1 == top)
- break;
- Thread.yield(); // wait for lagging update (very rare)
- }
- }
- return null;
- }
-
- /**
- * Takes next task, if one exists, in order specified by mode.
- */
- final ForkJoinTask<?> nextLocalTask() {
- return mode == 0 ? pop() : poll();
- }
-
- /**
- * Returns next task, if one exists, in order specified by mode.
- */
- final ForkJoinTask<?> peek() {
- ForkJoinTask<?>[] a = array; int m;
- if (a == null || (m = a.length - 1) < 0)
- return null;
- int i = mode == 0 ? top - 1 : base;
- int j = ((i & m) << ASHIFT) + ABASE;
- return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- }
-
- /**
- * Pops the given task only if it is at the current top.
- * (A shared version is available only via FJP.tryExternalUnpush)
- */
- final boolean tryUnpush(ForkJoinTask<?> t) {
- ForkJoinTask<?>[] a; int s;
- if ((a = array) != null && (s = top) != base &&
- U.compareAndSwapObject
- (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
- top = s;
- return true;
- }
- return false;
- }
-
- /**
- * Removes and cancels all known tasks, ignoring any exceptions.
- */
- final void cancelAll() {
- ForkJoinTask.cancelIgnoringExceptions(currentJoin);
- ForkJoinTask.cancelIgnoringExceptions(currentSteal);
- for (ForkJoinTask<?> t; (t = poll()) != null; )
- ForkJoinTask.cancelIgnoringExceptions(t);
- }
-
- // Specialized execution methods
-
- /**
- * Polls and runs tasks until empty.
- */
- final void pollAndExecAll() {
- for (ForkJoinTask<?> t; (t = poll()) != null;)
- t.doExec();
- }
-
- /**
- * Executes a top-level task and any local tasks remaining
- * after execution.
- */
- final void runTask(ForkJoinTask<?> task) {
- if ((currentSteal = task) != null) {
- ForkJoinWorkerThread thread;
- task.doExec();
- ForkJoinTask<?>[] a = array;
- int md = mode;
- ++nsteals;
- currentSteal = null;
- if (md != 0)
- pollAndExecAll();
- else if (a != null) {
- int s, m = a.length - 1;
- ForkJoinTask<?> t;
- while ((s = top - 1) - base >= 0 &&
- (t = (ForkJoinTask<?>)U.getAndSetObject
- (a, ((m & s) << ASHIFT) + ABASE, null)) != null) {
- top = s;
- t.doExec();
- }
- }
- if ((thread = owner) != null) // no need to do in finally clause
- thread.afterTopLevelExec();
- }
- }
-
- /**
- * If present, removes from queue and executes the given task,
- * or any other cancelled task. Returns (true) on any CAS
- * or consistency check failure so caller can retry.
- *
- * @return false if no progress can be made, else true
- */
- final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
- boolean stat;
- ForkJoinTask<?>[] a; int m, s, b, n;
- if (task != null && (a = array) != null && (m = a.length - 1) >= 0 &&
- (n = (s = top) - (b = base)) > 0) {
- boolean removed = false, empty = true;
- stat = true;
- for (ForkJoinTask<?> t;;) { // traverse from s to b
- long j = ((--s & m) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObject(a, j);
- if (t == null) // inconsistent length
- break;
- else if (t == task) {
- if (s + 1 == top) { // pop
- if (!U.compareAndSwapObject(a, j, task, null))
- break;
- top = s;
- removed = true;
- }
- else if (base == b) // replace with proxy
- removed = U.compareAndSwapObject(a, j, task,
- new EmptyTask());
- break;
- }
- else if (t.status >= 0)
- empty = false;
- else if (s + 1 == top) { // pop and throw away
- if (U.compareAndSwapObject(a, j, t, null))
- top = s;
- break;
- }
- if (--n == 0) {
- if (!empty && base == b)
- stat = false;
- break;
- }
- }
- if (removed)
- task.doExec();
- }
- else
- stat = false;
- return stat;
- }
-
- /**
- * Tries to poll for and execute the given task or any other
- * task in its CountedCompleter computation.
- */
- final boolean pollAndExecCC(CountedCompleter<?> root) {
- ForkJoinTask<?>[] a; int b; Object o; CountedCompleter<?> t, r;
- if ((b = base) - top < 0 && (a = array) != null) {
- long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((o = U.getObjectVolatile(a, j)) == null)
- return true; // retry
- if (o instanceof CountedCompleter) {
- for (t = (CountedCompleter<?>)o, r = t;;) {
- if (r == root) {
- if (base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- t.doExec();
- }
- return true;
- }
- else if ((r = r.completer) == null)
- break; // not part of root computation
- }
- }
- }
- return false;
- }
-
- /**
- * Tries to pop and execute the given task or any other task
- * in its CountedCompleter computation.
- */
- final boolean externalPopAndExecCC(CountedCompleter<?> root) {
- ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
- if (base - (s = top) < 0 && (a = array) != null) {
- long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
- for (t = (CountedCompleter<?>)o, r = t;;) {
- if (r == root) {
- if (compareAndSwapIntQlock(0, 1)) {
- if (top == s && array == a &&
- U.compareAndSwapObject(a, j, t, null)) {
- top = s - 1;
- qlock = 0;
- t.doExec();
- }
- else
- qlock = 0;
- }
- return true;
- }
- else if ((r = r.completer) == null)
- break;
- }
- }
- }
- return false;
- }
-
- /**
- * Internal version
- */
- final boolean internalPopAndExecCC(CountedCompleter<?> root) {
- ForkJoinTask<?>[] a; int s; Object o; CountedCompleter<?> t, r;
- if (base - (s = top) < 0 && (a = array) != null) {
- long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if ((o = U.getObject(a, j)) instanceof CountedCompleter) {
- for (t = (CountedCompleter<?>)o, r = t;;) {
- if (r == root) {
- if (U.compareAndSwapObject(a, j, t, null)) {
- top = s - 1;
- t.doExec();
- }
- return true;
- }
- else if ((r = r.completer) == null)
- break;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns true if owned and not known to be blocked.
- */
- final boolean isApparentlyUnblocked() {
- Thread wt; Thread.State s;
- return (eventCount >= 0 &&
- (wt = owner) != null &&
- (s = wt.getState()) != Thread.State.BLOCKED &&
- s != Thread.State.WAITING &&
- s != Thread.State.TIMED_WAITING);
- }
-
- @ikvm.internal.InterlockedCompareAndSet("qlock")
- final native boolean compareAndSwapIntQlock(int expect, int update);
-
- // Unsafe mechanics
- private static final sun.misc.Unsafe U;
- private static final int ABASE;
- private static final int ASHIFT;
- static {
- try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> ak = ForkJoinTask[].class;
- ABASE = U.arrayBaseOffset(ak);
- int scale = U.arrayIndexScale(ak);
- if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
- throw new Error(e);
- }
- }
- }
-
- // static fields (initialized in static initializer below)
-
- /**
- * Creates a new ForkJoinWorkerThread. This factory is used unless
- * overridden in ForkJoinPool constructors.
- */
- public static final ForkJoinWorkerThreadFactory
- defaultForkJoinWorkerThreadFactory;
-
- /**
- * Permission required for callers of methods that may start or
- * kill threads.
- */
- private static final RuntimePermission modifyThreadPermission;
-
- /**
- * Common (static) pool. Non-null for public use unless a static
- * construction exception, but internal usages null-check on use
- * to paranoically avoid potential initialization circularities
- * as well as to simplify generated code.
- */
- static final ForkJoinPool common;
-
- /**
- * Common pool parallelism. To allow simpler use and management
- * when common pool threads are disabled, we allow the underlying
- * common.parallelism field to be zero, but in that case still report
- * parallelism as 1 to reflect resulting caller-runs mechanics.
- */
- static final int commonParallelism;
-
- /**
- * Sequence number for creating workerNamePrefix.
- */
- private static int poolNumberSequence;
-
- /**
- * Returns the next sequence number. We don't expect this to
- * ever contend, so use simple builtin sync.
- */
- private static final synchronized int nextPoolId() {
- return ++poolNumberSequence;
- }
-
- // static constants
-
- /**
- * Initial timeout value (in nanoseconds) for the thread
- * triggering quiescence to park waiting for new work. On timeout,
- * the thread will instead try to shrink the number of
- * workers. The value should be large enough to avoid overly
- * aggressive shrinkage during most transient stalls (long GCs
- * etc).
- */
- private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec
-
- /**
- * Timeout value when there are more threads than parallelism level
- */
- private static final long FAST_IDLE_TIMEOUT = 200L * 1000L * 1000L;
-
- /**
- * Tolerance for idle timeouts, to cope with timer undershoots
- */
- private static final long TIMEOUT_SLOP = 2000000L;
-
- /**
- * The maximum stolen->joining link depth allowed in method
- * tryHelpStealer. Must be a power of two. Depths for legitimate
- * chains are unbounded, but we use a fixed constant to avoid
- * (otherwise unchecked) cycles and to bound staleness of
- * traversal parameters at the expense of sometimes blocking when
- * we could be helping.
- */
- private static final int MAX_HELP = 64;
-
- /**
- * Increment for seed generators. See class ThreadLocal for
- * explanation.
- */
- private static final int SEED_INCREMENT = 0x9e3779b9;
-
- /*
- * Bits and masks for control variables
- *
- * Field ctl is a long packed with:
- * AC: Number of active running workers minus target parallelism (16 bits)
- * TC: Number of total workers minus target parallelism (16 bits)
- * ST: true if pool is terminating (1 bit)
- * EC: the wait count of top waiting thread (15 bits)
- * ID: poolIndex of top of Treiber stack of waiters (16 bits)
- *
- * When convenient, we can extract the upper 32 bits of counts and
- * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
- * (int)ctl. The ec field is never accessed alone, but always
- * together with id and st. The offsets of counts by the target
- * parallelism and the positionings of fields makes it possible to
- * perform the most common checks via sign tests of fields: When
- * ac is negative, there are not enough active workers, when tc is
- * negative, there are not enough total workers, and when e is
- * negative, the pool is terminating. To deal with these possibly
- * negative fields, we use casts in and out of "short" and/or
- * signed shifts to maintain signedness.
- *
- * When a thread is queued (inactivated), its eventCount field is
- * set negative, which is the only way to tell if a worker is
- * prevented from executing tasks, even though it must continue to
- * scan for them to avoid queuing races. Note however that
- * eventCount updates lag releases so usage requires care.
- *
- * Field plock is an int packed with:
- * SHUTDOWN: true if shutdown is enabled (1 bit)
- * SEQ: a sequence lock, with PL_LOCK bit set if locked (30 bits)
- * SIGNAL: set when threads may be waiting on the lock (1 bit)
- *
- * The sequence number enables simple consistency checks:
- * Staleness of read-only operations on the workQueues array can
- * be checked by comparing plock before vs after the reads.
- */
-
- // bit positions/shifts for fields
- private static final int AC_SHIFT = 48;
- private static final int TC_SHIFT = 32;
- private static final int ST_SHIFT = 31;
- private static final int EC_SHIFT = 16;
-
- // bounds
- private static final int SMASK = 0xffff; // short bits
- private static final int MAX_CAP = 0x7fff; // max #workers - 1
- private static final int EVENMASK = 0xfffe; // even short bits
- private static final int SQMASK = 0x007e; // max 64 (even) slots
- private static final int SHORT_SIGN = 1 << 15;
- private static final int INT_SIGN = 1 << 31;
-
- // masks
- private static final long STOP_BIT = 0x0001L << ST_SHIFT;
- private static final long AC_MASK = ((long)SMASK) << AC_SHIFT;
- private static final long TC_MASK = ((long)SMASK) << TC_SHIFT;
-
- // units for incrementing and decrementing
- private static final long TC_UNIT = 1L << TC_SHIFT;
- private static final long AC_UNIT = 1L << AC_SHIFT;
-
- // masks and units for dealing with u = (int)(ctl >>> 32)
- private static final int UAC_SHIFT = AC_SHIFT - 32;
- private static final int UTC_SHIFT = TC_SHIFT - 32;
- private static final int UAC_MASK = SMASK << UAC_SHIFT;
- private static final int UTC_MASK = SMASK << UTC_SHIFT;
- private static final int UAC_UNIT = 1 << UAC_SHIFT;
- private static final int UTC_UNIT = 1 << UTC_SHIFT;
-
- // masks and units for dealing with e = (int)ctl
- private static final int E_MASK = 0x7fffffff; // no STOP_BIT
- private static final int E_SEQ = 1 << EC_SHIFT;
-
- // plock bits
- private static final int SHUTDOWN = 1 << 31;
- private static final int PL_LOCK = 2;
- private static final int PL_SIGNAL = 1;
- private static final int PL_SPINS = 1 << 8;
-
- // access mode for WorkQueue
- static final int LIFO_QUEUE = 0;
- static final int FIFO_QUEUE = 1;
- static final int SHARED_QUEUE = -1;
-
- // Instance fields
- volatile long stealCount; // collects worker counts
- volatile long ctl; // main pool control
- volatile int plock; // shutdown status and seqLock
- volatile int indexSeed; // worker/submitter index seed
- final short parallelism; // parallelism level
- final short mode; // LIFO/FIFO
- WorkQueue[] workQueues; // main registry
- final ForkJoinWorkerThreadFactory factory;
- final UncaughtExceptionHandler ueh; // per-worker UEH
- final String workerNamePrefix; // to create worker name string
-
- /**
- * Acquires the plock lock to protect worker array and related
- * updates. This method is called only if an initial CAS on plock
- * fails. This acts as a spinlock for normal cases, but falls back
- * to builtin monitor to block when (rarely) needed. This would be
- * a terrible idea for a highly contended lock, but works fine as
- * a more conservative alternative to a pure spinlock.
- */
- private int acquirePlock() {
- int spins = PL_SPINS, ps, nps;
- for (;;) {
- if (((ps = plock) & PL_LOCK) == 0 &&
- compareAndSwapIntPlock(ps, nps = ps + PL_LOCK))
- return nps;
- else if (spins >= 0) {
- if (ThreadLocalRandom.nextSecondarySeed() >= 0)
- --spins;
- }
- else if (compareAndSwapIntPlock(ps, ps | PL_SIGNAL)) {
- synchronized (this) {
- if ((plock & PL_SIGNAL) != 0) {
- try {
- wait();
- } catch (InterruptedException ie) {
- try {
- Thread.currentThread().interrupt();
- } catch (SecurityException ignore) {
- }
- }
- }
- else
- notifyAll();
- }
- }
- }
- }
-
- /**
- * Unlocks and signals any thread waiting for plock. Called only
- * when CAS of seq value for unlock fails.
- */
- private void releasePlock(int ps) {
- plock = ps;
- synchronized (this) { notifyAll(); }
- }
-
- /**
- * Tries to create and start one worker if fewer than target
- * parallelism level exist. Adjusts counts etc on failure.
- */
- private void tryAddWorker() {
- long c; int u, e;
- while ((u = (int)((c = ctl) >>> 32)) < 0 &&
- (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) {
- long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) |
- ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e;
- if (compareAndSwapLongCtl(c, nc)) {
- ForkJoinWorkerThreadFactory fac;
- Throwable ex = null;
- ForkJoinWorkerThread wt = null;
- try {
- if ((fac = factory) != null &&
- (wt = fac.newThread(this)) != null) {
- wt.start();
- break;
- }
- } catch (Throwable rex) {
- ex = rex;
- }
- deregisterWorker(wt, ex);
- break;
- }
- }
- }
-
- // Registering and deregistering workers
-
- /**
- * Callback from ForkJoinWorkerThread to establish and record its
- * WorkQueue. To avoid scanning bias due to packing entries in
- * front of the workQueues array, we treat the array as a simple
- * power-of-two hash table using per-thread seed as hash,
- * expanding as needed.
- *
- * @param wt the worker thread
- * @return the worker's queue
- */
- final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
- UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps;
- wt.setDaemon(true);
- if ((handler = ueh) != null)
- wt.setUncaughtExceptionHandler(handler);
- do {} while (!compareAndSwapIntIndexSeed(s = indexSeed,
- s += SEED_INCREMENT) ||
- s == 0); // skip 0
- WorkQueue w = new WorkQueue(this, wt, mode, s);
- if (((ps = plock) & PL_LOCK) != 0 ||
- !compareAndSwapIntPlock(ps, ps += PL_LOCK))
- ps = acquirePlock();
- int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
- try {
- if ((ws = workQueues) != null) { // skip if shutting down
- int n = ws.length, m = n - 1;
- int r = (s << 1) | 1; // use odd-numbered indices
- if (ws[r &= m] != null) { // collision
- int probes = 0; // step by approx half size
- int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
- while (ws[r = (r + step) & m] != null) {
- if (++probes >= n) {
- workQueues = ws = Arrays.copyOf(ws, n <<= 1);
- m = n - 1;
- probes = 0;
- }
- }
- }
- w.poolIndex = (short)r;
- w.eventCount = r; // volatile write orders
- ws[r] = w;
- }
- } finally {
- if (!compareAndSwapIntPlock(ps, nps))
- releasePlock(nps);
- }
- wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1)));
- return w;
- }
-
- /**
- * Final callback from terminating worker, as well as upon failure
- * to construct or start a worker. Removes record of worker from
- * array, and adjusts counts. If pool is shutting down, tries to
- * complete termination.
- *
- * @param wt the worker thread, or null if construction failed
- * @param ex the exception causing failure, or null if none
- */
- final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
- WorkQueue w = null;
- if (wt != null && (w = wt.workQueue) != null) {
- int ps;
- w.qlock = -1; // ensure set
- getAndAddLongStealCount(w.nsteals); // collect steals
- if (((ps = plock) & PL_LOCK) != 0 ||
- !compareAndSwapIntPlock(ps, ps += PL_LOCK))
- ps = acquirePlock();
- int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
- try {
- int idx = w.poolIndex;
- WorkQueue[] ws = workQueues;
- if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w)
- ws[idx] = null;
- } finally {
- if (!compareAndSwapIntPlock(ps, nps))
- releasePlock(nps);
- }
- }
-
- long c; // adjust ctl counts
- do {} while (!compareAndSwapLongCtl
- (c = ctl, (((c - AC_UNIT) & AC_MASK) |
- ((c - TC_UNIT) & TC_MASK) |
- (c & ~(AC_MASK|TC_MASK)))));
-
- if (!tryTerminate(false, false) && w != null && w.array != null) {
- w.cancelAll(); // cancel remaining tasks
- WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e;
- while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) {
- if (e > 0) { // activate or create replacement
- if ((ws = workQueues) == null ||
- (i = e & SMASK) >= ws.length ||
- (v = ws[i]) == null)
- break;
- long nc = (((long)(v.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT) << 32));
- if (v.eventCount != (e | INT_SIGN))
- break;
- if (compareAndSwapLongCtl(c, nc)) {
- v.eventCount = (e + E_SEQ) & E_MASK;
- if ((p = v.parker) != null)
- U.unpark(p);
- break;
- }
- }
- else {
- if ((short)u < 0)
- tryAddWorker();
- break;
- }
- }
- }
- if (ex == null) // help clean refs on way out
- ForkJoinTask.helpExpungeStaleExceptions();
- else // rethrow
- ForkJoinTask.rethrow(ex);
- }
-
- // Submissions
-
- /**
- * Unless shutting down, adds the given task to a submission queue
- * at submitter's current queue index (modulo submission
- * range). Only the most common path is directly handled in this
- * method. All others are relayed to fullExternalPush.
- *
- * @param task the task. Caller must ensure non-null.
- */
- final void externalPush(ForkJoinTask<?> task) {
- WorkQueue q; int m, s, n, am; ForkJoinTask<?>[] a;
- int r = ThreadLocalRandom.getProbe();
- int ps = plock;
- WorkQueue[] ws = workQueues;
- if (ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 &&
- (q = ws[m & r & SQMASK]) != null && r != 0 &&
- q.compareAndSwapIntQlock(0, 1)) { // lock
- if ((a = q.array) != null &&
- (am = a.length - 1) > (n = (s = q.top) - q.base)) {
- int j = ((am & s) << ASHIFT) + ABASE;
- U.putOrderedObject(a, j, task);
- q.top = s + 1; // push on to deque
- q.qlock = 0;
- if (n <= 1)
- signalWork(ws, q);
- return;
- }
- q.qlock = 0;
- }
- fullExternalPush(task);
- }
-
- /**
- * Full version of externalPush. This method is called, among
- * other times, upon the first submission of the first task to the
- * pool, so must perform secondary initialization. It also
- * detects first submission by an external thread by looking up
- * its ThreadLocal, and creates a new shared queue if the one at
- * index if empty or contended. The plock lock body must be
- * exception-free (so no try/finally) so we optimistically
- * allocate new queues outside the lock and throw them away if
- * (very rarely) not needed.
- *
- * Secondary initialization occurs when plock is zero, to create
- * workQueue array and set plock to a valid value. This lock body
- * must also be exception-free. Because the plock seq value can
- * eventually wrap around zero, this method harmlessly fails to
- * reinitialize if workQueues exists, while still advancing plock.
- */
- private void fullExternalPush(ForkJoinTask<?> task) {
- int r;
- if ((r = ThreadLocalRandom.getProbe()) == 0) {
- ThreadLocalRandom.localInit();
- r = ThreadLocalRandom.getProbe();
- }
- for (;;) {
- WorkQueue[] ws; WorkQueue q; int ps, m, k;
- boolean move = false;
- if ((ps = plock) < 0)
- throw new RejectedExecutionException();
- else if (ps == 0 || (ws = workQueues) == null ||
- (m = ws.length - 1) < 0) { // initialize workQueues
- int p = parallelism; // find power of two table size
- int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
- n |= n >>> 1; n |= n >>> 2; n |= n >>> 4;
- n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
- WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ?
- new WorkQueue[n] : null);
- if (((ps = plock) & PL_LOCK) != 0 ||
- !compareAndSwapIntPlock(ps, ps += PL_LOCK))
- ps = acquirePlock();
- if (((ws = workQueues) == null || ws.length == 0) && nws != null)
- workQueues = nws;
- int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
- if (!compareAndSwapIntPlock(ps, nps))
- releasePlock(nps);
- }
- else if ((q = ws[k = r & m & SQMASK]) != null) {
- if (q.qlock == 0 && q.compareAndSwapIntQlock(0, 1)) {
- ForkJoinTask<?>[] a = q.array;
- int s = q.top;
- boolean submitted = false;
- try { // locked version of push
- if ((a != null && a.length > s + 1 - q.base) ||
- (a = q.growArray()) != null) { // must presize
- int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
- U.putOrderedObject(a, j, task);
- q.top = s + 1;
- submitted = true;
- }
- } finally {
- q.qlock = 0; // unlock
- }
- if (submitted) {
- signalWork(ws, q);
- return;
- }
- }
- move = true; // move on failure
- }
- else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
- q = new WorkQueue(this, null, SHARED_QUEUE, r);
- q.poolIndex = (short)k;
- if (((ps = plock) & PL_LOCK) != 0 ||
- !compareAndSwapIntPlock(ps, ps += PL_LOCK))
- ps = acquirePlock();
- if ((ws = workQueues) != null && k < ws.length && ws[k] == null)
- ws[k] = q;
- int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
- if (!compareAndSwapIntPlock(ps, nps))
- releasePlock(nps);
- }
- else
- move = true; // move if busy
- if (move)
- r = ThreadLocalRandom.advanceProbe(r);
- }
- }
-
- // Maintaining ctl counts
-
- /**
- * Increments active count; mainly called upon return from blocking.
- */
- final void incrementActiveCount() {
- long c;
- do {} while (!compareAndSwapLongCtl
- (c = ctl, ((c & ~AC_MASK) |
- ((c & AC_MASK) + AC_UNIT))));
- }
-
- /**
- * Tries to create or activate a worker if too few are active.
- *
- * @param ws the worker array to use to find signallees
- * @param q if non-null, the queue holding tasks to be processed
- */
- final void signalWork(WorkQueue[] ws, WorkQueue q) {
- for (;;) {
- long c; int e, u, i; WorkQueue w; Thread p;
- if ((u = (int)((c = ctl) >>> 32)) >= 0)
- break;
- if ((e = (int)c) <= 0) {
- if ((short)u < 0)
- tryAddWorker();
- break;
- }
- if (ws == null || ws.length <= (i = e & SMASK) ||
- (w = ws[i]) == null)
- break;
- long nc = (((long)(w.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT)) << 32);
- int ne = (e + E_SEQ) & E_MASK;
- if (w.eventCount == (e | INT_SIGN) &&
- compareAndSwapLongCtl(c, nc)) {
- w.eventCount = ne;
- if ((p = w.parker) != null)
- U.unpark(p);
- break;
- }
- if (q != null && q.base >= q.top)
- break;
- }
- }
-
- // Scanning for tasks
-
- /**
- * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
- */
- final void runWorker(WorkQueue w) {
- w.growArray(); // allocate queue
- for (int r = w.hint; scan(w, r) == 0; ) {
- r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
- }
- }
-
- /**
- * Scans for and, if found, runs one task, else possibly
- * inactivates the worker. This method operates on single reads of
- * volatile state and is designed to be re-invoked continuously,
- * in part because it returns upon detecting inconsistencies,
- * contention, or state changes that indicate possible success on
- * re-invocation.
- *
- * The scan searches for tasks across queues starting at a random
- * index, checking each at least twice. The scan terminates upon
- * either finding a non-empty queue, or completing the sweep. If
- * the worker is not inactivated, it takes and runs a task from
- * this queue. Otherwise, if not activated, it tries to activate
- * itself or some other worker by signalling. On failure to find a
- * task, returns (for retry) if pool state may have changed during
- * an empty scan, or tries to inactivate if active, else possibly
- * blocks or terminates via method awaitWork.
- *
- * @param w the worker (via its WorkQueue)
- * @param r a random seed
- * @return worker qlock status if would have waited, else 0
- */
- private final int scan(WorkQueue w, int r) {
- WorkQueue[] ws; int m;
- long c = ctl; // for consistency check
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) {
- for (int j = m + m + 1, ec = w.eventCount;;) {
- WorkQueue q; int b, e; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
- if ((q = ws[(r - j) & m]) != null &&
- (b = q.base) - q.top < 0 && (a = q.array) != null) {
- long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((t = ((ForkJoinTask<?>)
- U.getObjectVolatile(a, i))) != null) {
- if (ec < 0)
- helpRelease(c, ws, w, q, b);
- else if (q.base == b &&
- U.compareAndSwapObject(a, i, t, null)) {
- q.base = b + 1;
- if ((b + 1) - q.top < 0)
- signalWork(ws, q);
- w.runTask(t);
- }
- }
- break;
- }
- else if (--j < 0) {
- if ((ec | (e = (int)c)) < 0) // inactive or terminating
- return awaitWork(w, c, ec);
- else if (ctl == c) { // try to inactivate and enqueue
- long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
- w.nextWait = e;
- w.eventCount = ec | INT_SIGN;
- if (!compareAndSwapLongCtl(c, nc))
- w.eventCount = ec; // back out
- }
- break;
- }
- }
- }
- return 0;
- }
-
- /**
- * A continuation of scan(), possibly blocking or terminating
- * worker w. Returns without blocking if pool state has apparently
- * changed since last invocation. Also, if inactivating w has
- * caused the pool to become quiescent, checks for pool
- * termination, and, so long as this is not the only worker, waits
- * for event for up to a given duration. On timeout, if ctl has
- * not changed, terminates the worker, which will in turn wake up
- * another worker to possibly repeat this process.
- *
- * @param w the calling worker
- * @param c the ctl value on entry to scan
- * @param ec the worker's eventCount on entry to scan
- */
- private final int awaitWork(WorkQueue w, long c, int ec) {
- int stat, ns; long parkTime, deadline;
- if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c &&
- !Thread.interrupted()) {
- int e = (int)c;
- int u = (int)(c >>> 32);
- int d = (u >> UAC_SHIFT) + parallelism; // active count
-
- if (e < 0 || (d <= 0 && tryTerminate(false, false)))
- stat = w.qlock = -1; // pool is terminating
- else if ((ns = w.nsteals) != 0) { // collect steals and retry
- w.nsteals = 0;
- getAndAddLongStealCount((long)ns);
- }
- else {
- long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L :
- ((long)(w.nextWait & E_MASK)) | // ctl to restore
- ((long)(u + UAC_UNIT)) << 32);
- if (pc != 0L) { // timed wait if last waiter
- int dc = -(short)(c >>> TC_SHIFT);
- parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT:
- (dc + 1) * IDLE_TIMEOUT);
- deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
- }
- else
- parkTime = deadline = 0L;
- if (w.eventCount == ec && ctl == c) {
- Thread wt = Thread.currentThread();
- wt.parkBlocker = this;
- w.parker = wt; // emulate LockSupport.park
- if (w.eventCount == ec && ctl == c)
- U.park(false, parkTime); // must recheck before park
- w.parker = null;
- wt.parkBlocker = null;
- if (parkTime != 0L && ctl == c &&
- deadline - System.nanoTime() <= 0L &&
- compareAndSwapLongCtl(c, pc))
- stat = w.qlock = -1; // shrink pool
- }
- }
- }
- return stat;
- }
-
- /**
- * Possibly releases (signals) a worker. Called only from scan()
- * when a worker with apparently inactive status finds a non-empty
- * queue. This requires revalidating all of the associated state
- * from caller.
- */
- private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w,
- WorkQueue q, int b) {
- WorkQueue v; int e, i; Thread p;
- if (w != null && w.eventCount < 0 && (e = (int)c) > 0 &&
- ws != null && ws.length > (i = e & SMASK) &&
- (v = ws[i]) != null && ctl == c) {
- long nc = (((long)(v.nextWait & E_MASK)) |
- ((long)((int)(c >>> 32) + UAC_UNIT)) << 32);
- int ne = (e + E_SEQ) & E_MASK;
- if (q != null && q.base == b && w.eventCount < 0 &&
- v.eventCount == (e | INT_SIGN) &&
- compareAndSwapLongCtl(c, nc)) {
- v.eventCount = ne;
- if ((p = v.parker) != null)
- U.unpark(p);
- }
- }
- }
-
- /**
- * Tries to locate and execute tasks for a stealer of the given
- * task, or in turn one of its stealers, Traces currentSteal ->
- * currentJoin links looking for a thread working on a descendant
- * of the given task and with a non-empty queue to steal back and
- * execute tasks from. The first call to this method upon a
- * waiting join will often entail scanning/search, (which is OK
- * because the joiner has nothing better to do), but this method
- * leaves hints in workers to speed up subsequent calls. The
- * implementation is very branchy to cope with potential
- * inconsistencies or loops encountering chains that are stale,
- * unknown, or so long that they are likely cyclic.
- *
- * @param joiner the joining worker
- * @param task the task to join
- * @return 0 if no progress can be made, negative if task
- * known complete, else positive
- */
- private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
- int stat = 0, steps = 0; // bound to avoid cycles
- if (task != null && joiner != null &&
- joiner.base - joiner.top >= 0) { // hoist checks
- restart: for (;;) {
- ForkJoinTask<?> subtask = task; // current target
- for (WorkQueue j = joiner, v;;) { // v is stealer of subtask
- WorkQueue[] ws; int m, s, h;
- if ((s = task.status) < 0) {
- stat = s;
- break restart;
- }
- if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
- break restart; // shutting down
- if ((v = ws[h = (j.hint | 1) & m]) == null ||
- v.currentSteal != subtask) {
- for (int origin = h;;) { // find stealer
- if (((h = (h + 2) & m) & 15) == 1 &&
- (subtask.status < 0 || j.currentJoin != subtask))
- continue restart; // occasional staleness check
- if ((v = ws[h]) != null &&
- v.currentSteal == subtask) {
- j.hint = h; // save hint
- break;
- }
- if (h == origin)
- break restart; // cannot find stealer
- }
- }
- for (;;) { // help stealer or descend to its stealer
- ForkJoinTask<?>[] a; int b;
- if (subtask.status < 0) // surround probes with
- continue restart; // consistency checks
- if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
- int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- ForkJoinTask<?> t =
- (ForkJoinTask<?>)U.getObjectVolatile(a, i);
- if (subtask.status < 0 || j.currentJoin != subtask ||
- v.currentSteal != subtask)
- continue restart; // stale
- stat = 1; // apparent progress
- if (v.base == b) {
- if (t == null)
- break restart;
- if (U.compareAndSwapObject(a, i, t, null)) {
- v.base = b + 1;
- ForkJoinTask<?> ps = joiner.currentSteal;
- int jt = joiner.top;
- do {
- joiner.currentSteal = t;
- t.doExec(); // clear local tasks too
- } while (task.status >= 0 &&
- joiner.top != jt &&
- (t = joiner.pop()) != null);
- joiner.currentSteal = ps;
- break restart;
- }
- }
- }
- else { // empty -- try to descend
- ForkJoinTask<?> next = v.currentJoin;
- if (subtask.status < 0 || j.currentJoin != subtask ||
- v.currentSteal != subtask)
- continue restart; // stale
- else if (next == null || ++steps == MAX_HELP)
- break restart; // dead-end or maybe cyclic
- else {
- subtask = next;
- j = v;
- break;
- }
- }
- }
- }
- }
- }
- return stat;
- }
-
- /**
- * Analog of tryHelpStealer for CountedCompleters. Tries to steal
- * and run tasks within the target's computation.
- *
- * @param task the task to join
- * @param maxTasks the maximum number of other tasks to run
- */
- final int helpComplete(WorkQueue joiner, CountedCompleter<?> task,
- int maxTasks) {
- WorkQueue[] ws; int m;
- int s = 0;
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
- joiner != null && task != null) {
- int j = joiner.poolIndex;
- int scans = m + m + 1;
- long c = 0L; // for stability check
- for (int k = scans; ; j += 2) {
- WorkQueue q;
- if ((s = task.status) < 0)
- break;
- else if (joiner.internalPopAndExecCC(task)) {
- if (--maxTasks <= 0) {
- s = task.status;
- break;
- }
- k = scans;
- }
- else if ((s = task.status) < 0)
- break;
- else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
- if (--maxTasks <= 0) {
- s = task.status;
- break;
- }
- k = scans;
- }
- else if (--k < 0) {
- if (c == (c = ctl))
- break;
- k = scans;
- }
- }
- }
- return s;
- }
-
- /**
- * Tries to decrement active count (sometimes implicitly) and
- * possibly release or create a compensating worker in preparation
- * for blocking. Fails on contention or termination. Otherwise,
- * adds a new thread if no idle workers are available and pool
- * may become starved.
- *
- * @param c the assumed ctl value
- */
- final boolean tryCompensate(long c) {
- WorkQueue[] ws = workQueues;
- int pc = parallelism, e = (int)c, m, tc;
- if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) {
- WorkQueue w = ws[e & m];
- if (e != 0 && w != null) {
- Thread p;
- long nc = ((long)(w.nextWait & E_MASK) |
- (c & (AC_MASK|TC_MASK)));
- int ne = (e + E_SEQ) & E_MASK;
- if (w.eventCount == (e | INT_SIGN) &&
- compareAndSwapLongCtl(c, nc)) {
- w.eventCount = ne;
- if ((p = w.parker) != null)
- U.unpark(p);
- return true; // replace with idle worker
- }
- }
- else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 &&
- (int)(c >> AC_SHIFT) + pc > 1) {
- long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
- if (compareAndSwapLongCtl(c, nc))
- return true; // no compensation
- }
- else if (tc + pc < MAX_CAP) {
- long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
- if (compareAndSwapLongCtl(c, nc)) {
- ForkJoinWorkerThreadFactory fac;
- Throwable ex = null;
- ForkJoinWorkerThread wt = null;
- try {
- if ((fac = factory) != null &&
- (wt = fac.newThread(this)) != null) {
- wt.start();
- return true;
- }
- } catch (Throwable rex) {
- ex = rex;
- }
- deregisterWorker(wt, ex); // clean up and return false
- }
- }
- }
- return false;
- }
-
- /**
- * Helps and/or blocks until the given task is done.
- *
- * @param joiner the joining worker
- * @param task the task
- * @return task status on exit
- */
- final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
- int s = 0;
- if (task != null && (s = task.status) >= 0 && joiner != null) {
- ForkJoinTask<?> prevJoin = joiner.currentJoin;
- joiner.currentJoin = task;
- do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
- (s = task.status) >= 0);
- if (s >= 0 && (task instanceof CountedCompleter))
- s = helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
- long cc = 0; // for stability checks
- while (s >= 0 && (s = task.status) >= 0) {
- if ((s = tryHelpStealer(joiner, task)) == 0 &&
- (s = task.status) >= 0) {
- if (!tryCompensate(cc))
- cc = ctl;
- else {
- if (task.trySetSignal() && (s = task.status) >= 0) {
- synchronized (task) {
- if (task.status >= 0) {
- try { // see ForkJoinTask
- task.wait(); // for explanation
- } catch (InterruptedException ie) {
- }
- }
- else
- task.notifyAll();
- }
- }
- long c; // reactivate
- do {} while (!compareAndSwapLongCtl
- (c = ctl,
- ((c & ~AC_MASK) |
- ((c & AC_MASK) + AC_UNIT))));
- }
- }
- }
- joiner.currentJoin = prevJoin;
- }
- return s;
- }
-
- /**
- * Stripped-down variant of awaitJoin used by timed joins. Tries
- * to help join only while there is continuous progress. (Caller
- * will then enter a timed wait.)
- *
- * @param joiner the joining worker
- * @param task the task
- */
- final void helpJoinOnce(WorkQueue joiner, ForkJoinTask<?> task) {
- int s;
- if (joiner != null && task != null && (s = task.status) >= 0) {
- ForkJoinTask<?> prevJoin = joiner.currentJoin;
- joiner.currentJoin = task;
- do {} while (joiner.tryRemoveAndExec(task) && // process local tasks
- (s = task.status) >= 0);
- if (s >= 0) {
- if (task instanceof CountedCompleter)
- helpComplete(joiner, (CountedCompleter<?>)task, Integer.MAX_VALUE);
- do {} while (task.status >= 0 &&
- tryHelpStealer(joiner, task) > 0);
- }
- joiner.currentJoin = prevJoin;
- }
- }
-
- /**
- * Returns a (probably) non-empty steal queue, if one is found
- * during a scan, else null. This method must be retried by
- * caller if, by the time it tries to use the queue, it is empty.
- */
- private WorkQueue findNonEmptyStealQueue() {
- int r = ThreadLocalRandom.nextSecondarySeed();
- for (;;) {
- int ps = plock, m; WorkQueue[] ws; WorkQueue q;
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
- for (int j = (m + 1) << 2; j >= 0; --j) {
- if ((q = ws[(((r - j) << 1) | 1) & m]) != null &&
- q.base - q.top < 0)
- return q;
- }
- }
- if (plock == ps)
- return null;
- }
- }
-
- /**
- * Runs tasks until {@code isQuiescent()}. We piggyback on
- * active count ctl maintenance, but rather than blocking
- * when tasks cannot be found, we rescan until all others cannot
- * find tasks either.
- */
- final void helpQuiescePool(WorkQueue w) {
- ForkJoinTask<?> ps = w.currentSteal;
- for (boolean active = true;;) {
- long c; WorkQueue q; ForkJoinTask<?> t; int b;
- while ((t = w.nextLocalTask()) != null)
- t.doExec();
- if ((q = findNonEmptyStealQueue()) != null) {
- if (!active) { // re-establish active count
- active = true;
- do {} while (!compareAndSwapLongCtl
- (c = ctl,
- ((c & ~AC_MASK) |
- ((c & AC_MASK) + AC_UNIT))));
- }
- if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
- w.runTask(t);
- }
- else if (active) { // decrement active count without queuing
- long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT);
- if ((int)(nc >> AC_SHIFT) + parallelism == 0)
- break; // bypass decrement-then-increment
- if (compareAndSwapLongCtl(c, nc))
- active = false;
- }
- else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 &&
- compareAndSwapLongCtl
- (c, ((c & ~AC_MASK) |
- ((c & AC_MASK) + AC_UNIT))))
- break;
- }
- }
-
- /**
- * Gets and removes a local or stolen task for the given worker.
- *
- * @return a task, if available
- */
- final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
- for (ForkJoinTask<?> t;;) {
- WorkQueue q; int b;
- if ((t = w.nextLocalTask()) != null)
- return t;
- if ((q = findNonEmptyStealQueue()) == null)
- return null;
- if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
- return t;
- }
- }
-
- /**
- * Returns a cheap heuristic guide for task partitioning when
- * programmers, frameworks, tools, or languages have little or no
- * idea about task granularity. In essence by offering this
- * method, we ask users only about tradeoffs in overhead vs
- * expected throughput and its variance, rather than how finely to
- * partition tasks.
- *
- * In a steady state strict (tree-structured) computation, each
- * thread makes available for stealing enough tasks for other
- * threads to remain active. Inductively, if all threads play by
- * the same rules, each thread should make available only a
- * constant number of tasks.
- *
- * The minimum useful constant is just 1. But using a value of 1
- * would require immediate replenishment upon each steal to
- * maintain enough tasks, which is infeasible. Further,
- * partitionings/granularities of offered tasks should minimize
- * steal rates, which in general means that threads nearer the top
- * of computation tree should generate more than those nearer the
- * bottom. In perfect steady state, each thread is at
- * approximately the same level of computation tree. However,
- * producing extra tasks amortizes the uncertainty of progress and
- * diffusion assumptions.
- *
- * So, users will want to use values larger (but not much larger)
- * than 1 to both smooth over transient shortages and hedge
- * against uneven progress; as traded off against the cost of
- * extra task overhead. We leave the user to pick a threshold
- * value to compare with the results of this call to guide
- * decisions, but recommend values such as 3.
- *
- * When all threads are active, it is on average OK to estimate
- * surplus strictly locally. In steady-state, if one thread is
- * maintaining say 2 surplus tasks, then so are others. So we can
- * just use estimated queue length. However, this strategy alone
- * leads to serious mis-estimates in some non-steady-state
- * conditions (ramp-up, ramp-down, other stalls). We can detect
- * many of these by further considering the number of "idle"
- * threads, that are known to have zero queued tasks, so
- * compensate by a factor of (#idle/#active) threads.
- *
- * Note: The approximation of #busy workers as #active workers is
- * not very good under current signalling scheme, and should be
- * improved.
- */
- static int getSurplusQueuedTaskCount() {
- Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
- if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
- int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).parallelism;
- int n = (q = wt.workQueue).top - q.base;
- int a = (int)(pool.ctl >> AC_SHIFT) + p;
- return n - (a > (p >>>= 1) ? 0 :
- a > (p >>>= 1) ? 1 :
- a > (p >>>= 1) ? 2 :
- a > (p >>>= 1) ? 4 :
- 8);
- }
- return 0;
- }
-
- // Termination
-
- /**
- * Possibly initiates and/or completes termination. The caller
- * triggering termination runs three passes through workQueues:
- * (0) Setting termination status, followed by wakeups of queued
- * workers; (1) cancelling all tasks; (2) interrupting lagging
- * threads (likely in external tasks, but possibly also blocked in
- * joins). Each pass repeats previous steps because of potential
- * lagging thread creation.
- *
- * @param now if true, unconditionally terminate, else only
- * if no work and no active workers
- * @param enable if true, enable shutdown when next possible
- * @return true if now terminating or terminated
- */
- private boolean tryTerminate(boolean now, boolean enable) {
- int ps;
- if (this == common) // cannot shut down
- return false;
- if ((ps = plock) >= 0) { // enable by setting plock
- if (!enable)
- return false;
- if ((ps & PL_LOCK) != 0 ||
- !compareAndSwapIntPlock(ps, ps += PL_LOCK))
- ps = acquirePlock();
- int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN;
- if (!compareAndSwapIntPlock(ps, nps))
- releasePlock(nps);
- }
- for (long c;;) {
- if (((c = ctl) & STOP_BIT) != 0) { // already terminating
- if ((short)(c >>> TC_SHIFT) + parallelism <= 0) {
- synchronized (this) {
- notifyAll(); // signal when 0 workers
- }
- }
- return true;
- }
- if (!now) { // check if idle & no tasks
- WorkQueue[] ws; WorkQueue w;
- if ((int)(c >> AC_SHIFT) + parallelism > 0)
- return false;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; ++i) {
- if ((w = ws[i]) != null &&
- (!w.isEmpty() ||
- ((i & 1) != 0 && w.eventCount >= 0))) {
- signalWork(ws, w);
- return false;
- }
- }
- }
- }
- if (compareAndSwapLongCtl(c, c | STOP_BIT)) {
- for (int pass = 0; pass < 3; ++pass) {
- WorkQueue[] ws; WorkQueue w; Thread wt;
- if ((ws = workQueues) != null) {
- int n = ws.length;
- for (int i = 0; i < n; ++i) {
- if ((w = ws[i]) != null) {
- w.qlock = -1;
- if (pass > 0) {
- w.cancelAll();
- if (pass > 1 && (wt = w.owner) != null) {
- if (!wt.isInterrupted()) {
- try {
- wt.interrupt();
- } catch (Throwable ignore) {
- }
- }
- U.unpark(wt);
- }
- }
- }
- }
- // Wake up workers parked on event queue
- int i, e; long cc; Thread p;
- while ((e = (int)(cc = ctl) & E_MASK) != 0 &&
- (i = e & SMASK) < n && i >= 0 &&
- (w = ws[i]) != null) {
- long nc = ((long)(w.nextWait & E_MASK) |
- ((cc + AC_UNIT) & AC_MASK) |
- (cc & (TC_MASK|STOP_BIT)));
- if (w.eventCount == (e | INT_SIGN) &&
- compareAndSwapLongCtl(cc, nc)) {
- w.eventCount = (e + E_SEQ) & E_MASK;
- w.qlock = -1;
- if ((p = w.parker) != null)
- U.unpark(p);
- }
- }
- }
- }
- }
- }
- }
-
- // external operations on common pool
-
- /**
- * Returns common pool queue for a thread that has submitted at
- * least one task.
- */
- static WorkQueue commonSubmitterQueue() {
- ForkJoinPool p; WorkQueue[] ws; int m, z;
- return ((z = ThreadLocalRandom.getProbe()) != 0 &&
- (p = common) != null &&
- (ws = p.workQueues) != null &&
- (m = ws.length - 1) >= 0) ?
- ws[m & z & SQMASK] : null;
- }
-
- /**
- * Tries to pop the given task from submitter's queue in common pool.
- */
- final boolean tryExternalUnpush(ForkJoinTask<?> task) {
- WorkQueue joiner; ForkJoinTask<?>[] a; int m, s;
- WorkQueue[] ws = workQueues;
- int z = ThreadLocalRandom.getProbe();
- boolean popped = false;
- if (ws != null && (m = ws.length - 1) >= 0 &&
- (joiner = ws[z & m & SQMASK]) != null &&
- joiner.base != (s = joiner.top) &&
- (a = joiner.array) != null) {
- long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if (U.getObject(a, j) == task &&
- joiner.compareAndSwapIntQlock(0, 1)) {
- if (joiner.top == s && joiner.array == a &&
- U.compareAndSwapObject(a, j, task, null)) {
- joiner.top = s - 1;
- popped = true;
- }
- joiner.qlock = 0;
- }
- }
- return popped;
- }
-
- final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
- WorkQueue joiner; int m;
- WorkQueue[] ws = workQueues;
- int j = ThreadLocalRandom.getProbe();
- int s = 0;
- if (ws != null && (m = ws.length - 1) >= 0 &&
- (joiner = ws[j & m & SQMASK]) != null && task != null) {
- int scans = m + m + 1;
- long c = 0L; // for stability check
- j |= 1; // poll odd queues
- for (int k = scans; ; j += 2) {
- WorkQueue q;
- if ((s = task.status) < 0)
- break;
- else if (joiner.externalPopAndExecCC(task)) {
- if (--maxTasks <= 0) {
- s = task.status;
- break;
- }
- k = scans;
- }
- else if ((s = task.status) < 0)
- break;
- else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
- if (--maxTasks <= 0) {
- s = task.status;
- break;
- }
- k = scans;
- }
- else if (--k < 0) {
- if (c == (c = ctl))
- break;
- k = scans;
- }
- }
- }
- return s;
- }
-
- // Exported methods
-
- // Constructors
-
- /**
- * Creates a {@code ForkJoinPool} with parallelism equal to {@link
- * java.lang.Runtime#availableProcessors}, using the {@linkplain
- * #defaultForkJoinWorkerThreadFactory default thread factory},
- * no UncaughtExceptionHandler, and non-async LIFO processing mode.
- *
- * @throws SecurityException if a security manager exists and
- * the caller is not permitted to modify threads
- * because it does not hold {@link
- * java.lang.RuntimePermission}{@code ("modifyThread")}
- */
- public ForkJoinPool() {
- this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
- defaultForkJoinWorkerThreadFactory, null, false);
- }
-
- /**
- * Creates a {@code ForkJoinPool} with the indicated parallelism
- * level, the {@linkplain
- * #defaultForkJoinWorkerThreadFactory default thread factory},
- * no UncaughtExceptionHandler, and non-async LIFO processing mode.
- *
- * @param parallelism the parallelism level
- * @throws IllegalArgumentException if parallelism less than or
- * equal to zero, or greater than implementation limit
- * @throws SecurityException if a security manager exists and
- * the caller is not permitted to modify threads
- * because it does not hold {@link
- * java.lang.RuntimePermission}{@code ("modifyThread")}
- */
- public ForkJoinPool(int parallelism) {
- this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
- }
-
- /**
- * Creates a {@code ForkJoinPool} with the given parameters.
- *
- * @param parallelism the parallelism level. For default value,
- * use {@link java.lang.Runtime#availableProcessors}.
- * @param factory the factory for creating new threads. For default value,
- * use {@link #defaultForkJoinWorkerThreadFactory}.
- * @param handler the handler for internal worker threads that
- * terminate due to unrecoverable errors encountered while executing
- * tasks. For default value, use {@code null}.
- * @param asyncMode if true,
- * establishes local first-in-first-out scheduling mode for forked
- * tasks that are never joined. This mode may be more appropriate
- * than default locally stack-based mode in applications in which
- * worker threads only process event-style asynchronous tasks.
- * For default value, use {@code false}.
- * @throws IllegalArgumentException if parallelism less than or
- * equal to zero, or greater than implementation limit
- * @throws NullPointerException if the factory is null
- * @throws SecurityException if a security manager exists and
- * the caller is not permitted to modify threads
- * because it does not hold {@link
- * java.lang.RuntimePermission}{@code ("modifyThread")}
- */
- public ForkJoinPool(int parallelism,
- ForkJoinWorkerThreadFactory factory,
- UncaughtExceptionHandler handler,
- boolean asyncMode) {
- this(checkParallelism(parallelism),
- checkFactory(factory),
- handler,
- (asyncMode ? FIFO_QUEUE : LIFO_QUEUE),
- "ForkJoinPool-" + nextPoolId() + "-worker-");
- checkPermission();
- }
-
- private static int checkParallelism(int parallelism) {
- if (parallelism <= 0 || parallelism > MAX_CAP)
- throw new IllegalArgumentException();
- return parallelism;
- }
-
- private static ForkJoinWorkerThreadFactory checkFactory
- (ForkJoinWorkerThreadFactory factory) {
- if (factory == null)
- throw new NullPointerException();
- return factory;
- }
-
- /**
- * Creates a {@code ForkJoinPool} with the given parameters, without
- * any security checks or parameter validation. Invoked directly by
- * makeCommonPool.
- */
- private ForkJoinPool(int parallelism,
- ForkJoinWorkerThreadFactory factory,
- UncaughtExceptionHandler handler,
- int mode,
- String workerNamePrefix) {
- this.workerNamePrefix = workerNamePrefix;
- this.factory = factory;
- this.ueh = handler;
- this.mode = (short)mode;
- this.parallelism = (short)parallelism;
- long np = (long)(-parallelism); // offset ctl counts
- this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
- }
-
- /**
- * Returns the common pool instance. This pool is statically
- * constructed; its run state is unaffected by attempts to {@link
- * #shutdown} or {@link #shutdownNow}. However this pool and any
- * ongoing processing are automatically terminated upon program
- * {@link System#exit}. Any program that relies on asynchronous
- * task processing to complete before program termination should
- * invoke {@code commonPool().}{@link #awaitQuiescence awaitQuiescence},
- * before exit.
- *
- * @return the common pool instance
- * @since 1.8
- */
- public static ForkJoinPool commonPool() {
- // assert common != null : "static init error";
- return common;
- }
-
- // Execution methods
-
- /**
- * Performs the given task, returning its result upon completion.
- * If the computation encounters an unchecked Exception or Error,
- * it is rethrown as the outcome of this invocation. Rethrown
- * exceptions behave in the same way as regular exceptions, but,
- * when possible, contain stack traces (as displayed for example
- * using {@code ex.printStackTrace()}) of both the current thread
- * as well as the thread actually encountering the exception;
- * minimally only the latter.
- *
- * @param task the task
- * @param <T> the type of the task's result
- * @return the task's result
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public <T> T invoke(ForkJoinTask<T> task) {
- if (task == null)
- throw new NullPointerException();
- externalPush(task);
- return task.join();
- }
-
- /**
- * Arranges for (asynchronous) execution of the given task.
- *
- * @param task the task
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public void execute(ForkJoinTask<?> task) {
- if (task == null)
- throw new NullPointerException();
- externalPush(task);
- }
-
- // AbstractExecutorService methods
-
- /**
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public void execute(Runnable task) {
- if (task == null)
- throw new NullPointerException();
- ForkJoinTask<?> job;
- if (task instanceof ForkJoinTask<?>) // avoid re-wrap
- job = (ForkJoinTask<?>) task;
- else
- job = new ForkJoinTask.RunnableExecuteAction(task);
- externalPush(job);
- }
-
- /**
- * Submits a ForkJoinTask for execution.
- *
- * @param task the task to submit
- * @param <T> the type of the task's result
- * @return the task
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
- if (task == null)
- throw new NullPointerException();
- externalPush(task);
- return task;
- }
-
- /**
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public <T> ForkJoinTask<T> submit(Callable<T> task) {
- ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
- externalPush(job);
- return job;
- }
-
- /**
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public <T> ForkJoinTask<T> submit(Runnable task, T result) {
- ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
- externalPush(job);
- return job;
- }
-
- /**
- * @throws NullPointerException if the task is null
- * @throws RejectedExecutionException if the task cannot be
- * scheduled for execution
- */
- public ForkJoinTask<?> submit(Runnable task) {
- if (task == null)
- throw new NullPointerException();
- ForkJoinTask<?> job;
- if (task instanceof ForkJoinTask<?>) // avoid re-wrap
- job = (ForkJoinTask<?>) task;
- else
- job = new ForkJoinTask.AdaptedRunnableAction(task);
- externalPush(job);
- return job;
- }
-
- /**
- * @throws NullPointerException {@inheritDoc}
- * @throws RejectedExecutionException {@inheritDoc}
- */
- public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
- // In previous versions of this class, this method constructed
- // a task to run ForkJoinTask.invokeAll, but now external
- // invocation of multiple tasks is at least as efficient.
- ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
-
- boolean done = false;
- try {
- for (Callable<T> t : tasks) {
- ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
- futures.add(f);
- externalPush(f);
- }
- for (int i = 0, size = futures.size(); i < size; i++)
- ((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
- done = true;
- return futures;
- } finally {
- if (!done)
- for (int i = 0, size = futures.size(); i < size; i++)
- futures.get(i).cancel(false);
- }
- }
-
- /**
- * Returns the factory used for constructing new workers.
- *
- * @return the factory used for constructing new workers
- */
- public ForkJoinWorkerThreadFactory getFactory() {
- return factory;
- }
-
- /**
- * Returns the handler for internal worker threads that terminate
- * due to unrecoverable errors encountered while executing tasks.
- *
- * @return the handler, or {@code null} if none
- */
- public UncaughtExceptionHandler getUncaughtExceptionHandler() {
- return ueh;
- }
-
- /**
- * Returns the targeted parallelism level of this pool.
- *
- * @return the targeted parallelism level of this pool
- */
- public int getParallelism() {
- int par;
- return ((par = parallelism) > 0) ? par : 1;
- }
-
- /**
- * Returns the targeted parallelism level of the common pool.
- *
- * @return the targeted parallelism level of the common pool
- * @since 1.8
- */
- public static int getCommonPoolParallelism() {
- return commonParallelism;
- }
-
- /**
- * Returns the number of worker threads that have started but not
- * yet terminated. The result returned by this method may differ
- * from {@link #getParallelism} when threads are created to
- * maintain parallelism when others are cooperatively blocked.
- *
- * @return the number of worker threads
- */
- public int getPoolSize() {
- return parallelism + (short)(ctl >>> TC_SHIFT);
- }
-
- /**
- * Returns {@code true} if this pool uses local first-in-first-out
- * scheduling mode for forked tasks that are never joined.
- *
- * @return {@code true} if this pool uses async mode
- */
- public boolean getAsyncMode() {
- return mode == FIFO_QUEUE;
- }
-
- /**
- * Returns an estimate of the number of worker threads that are
- * not blocked waiting to join tasks or for other managed
- * synchronization. This method may overestimate the
- * number of running threads.
- *
- * @return the number of worker threads
- */
- public int getRunningThreadCount() {
- int rc = 0;
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 1; i < ws.length; i += 2) {
- if ((w = ws[i]) != null && w.isApparentlyUnblocked())
- ++rc;
- }
- }
- return rc;
- }
-
- /**
- * Returns an estimate of the number of threads that are currently
- * stealing or executing tasks. This method may overestimate the
- * number of active threads.
- *
- * @return the number of active threads
- */
- public int getActiveThreadCount() {
- int r = parallelism + (int)(ctl >> AC_SHIFT);
- return (r <= 0) ? 0 : r; // suppress momentarily negative values
- }
-
- /**
- * Returns {@code true} if all worker threads are currently idle.
- * An idle worker is one that cannot obtain a task to execute
- * because none are available to steal from other threads, and
- * there are no pending submissions to the pool. This method is
- * conservative; it might not return {@code true} immediately upon
- * idleness of all threads, but will eventually become true if
- * threads remain inactive.
- *
- * @return {@code true} if all threads are currently idle
- */
- public boolean isQuiescent() {
- return parallelism + (int)(ctl >> AC_SHIFT) <= 0;
- }
-
- /**
- * Returns an estimate of the total number of tasks stolen from
- * one thread's work queue by another. The reported value
- * underestimates the actual total number of steals when the pool
- * is not quiescent. This value may be useful for monitoring and
- * tuning fork/join programs: in general, steal counts should be
- * high enough to keep threads busy, but low enough to avoid
- * overhead and contention across threads.
- *
- * @return the number of steals
- */
- public long getStealCount() {
- long count = stealCount;
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 1; i < ws.length; i += 2) {
- if ((w = ws[i]) != null)
- count += w.nsteals;
- }
- }
- return count;
- }
-
- /**
- * Returns an estimate of the total number of tasks currently held
- * in queues by worker threads (but not including tasks submitted
- * to the pool that have not begun executing). This value is only
- * an approximation, obtained by iterating across all threads in
- * the pool. This method may be useful for tuning task
- * granularities.
- *
- * @return the number of queued tasks
- */
- public long getQueuedTaskCount() {
- long count = 0;
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 1; i < ws.length; i += 2) {
- if ((w = ws[i]) != null)
- count += w.queueSize();
- }
- }
- return count;
- }
-
- /**
- * Returns an estimate of the number of tasks submitted to this
- * pool that have not yet begun executing. This method may take
- * time proportional to the number of submissions.
- *
- * @return the number of queued submissions
- */
- public int getQueuedSubmissionCount() {
- int count = 0;
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; i += 2) {
- if ((w = ws[i]) != null)
- count += w.queueSize();
- }
- }
- return count;
- }
-
- /**
- * Returns {@code true} if there are any tasks submitted to this
- * pool that have not yet begun executing.
- *
- * @return {@code true} if there are any queued submissions
- */
- public boolean hasQueuedSubmissions() {
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; i += 2) {
- if ((w = ws[i]) != null && !w.isEmpty())
- return true;
- }
- }
- return false;
- }
-
- /**
- * Removes and returns the next unexecuted submission if one is
- * available. This method may be useful in extensions to this
- * class that re-assign work in systems with multiple pools.
- *
- * @return the next submission, or {@code null} if none
- */
- protected ForkJoinTask<?> pollSubmission() {
- WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; i += 2) {
- if ((w = ws[i]) != null && (t = w.poll()) != null)
- return t;
- }
- }
- return null;
- }
-
- /**
- * Removes all available unexecuted submitted and forked tasks
- * from scheduling queues and adds them to the given collection,
- * without altering their execution status. These may include
- * artificially generated or wrapped tasks. This method is
- * designed to be invoked only when the pool is known to be
- * quiescent. Invocations at other times may not remove all
- * tasks. A failure encountered while attempting to add elements
- * to collection {@code c} may result in elements being in
- * neither, either or both collections when the associated
- * exception is thrown. The behavior of this operation is
- * undefined if the specified collection is modified while the
- * operation is in progress.
- *
- * @param c the collection to transfer elements into
- * @return the number of elements transferred
- */
- protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
- int count = 0;
- WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; ++i) {
- if ((w = ws[i]) != null) {
- while ((t = w.poll()) != null) {
- c.add(t);
- ++count;
- }
- }
- }
- }
- return count;
- }
-
- /**
- * Returns a string identifying this pool, as well as its state,
- * including indications of run state, parallelism level, and
- * worker and task counts.
- *
- * @return a string identifying this pool, as well as its state
- */
- public String toString() {
- // Use a single pass through workQueues to collect counts
- long qt = 0L, qs = 0L; int rc = 0;
- long st = stealCount;
- long c = ctl;
- WorkQueue[] ws; WorkQueue w;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; ++i) {
- if ((w = ws[i]) != null) {
- int size = w.queueSize();
- if ((i & 1) == 0)
- qs += size;
- else {
- qt += size;
- st += w.nsteals;
- if (w.isApparentlyUnblocked())
- ++rc;
- }
- }
- }
- }
- int pc = parallelism;
- int tc = pc + (short)(c >>> TC_SHIFT);
- int ac = pc + (int)(c >> AC_SHIFT);
- if (ac < 0) // ignore transient negative
- ac = 0;
- String level;
- if ((c & STOP_BIT) != 0)
- level = (tc == 0) ? "Terminated" : "Terminating";
- else
- level = plock < 0 ? "Shutting down" : "Running";
- return super.toString() +
- "[" + level +
- ", parallelism = " + pc +
- ", size = " + tc +
- ", active = " + ac +
- ", running = " + rc +
- ", steals = " + st +
- ", tasks = " + qt +
- ", submissions = " + qs +
- "]";
- }
-
- /**
- * Possibly initiates an orderly shutdown in which previously
- * submitted tasks are executed, but no new tasks will be
- * accepted. Invocation has no effect on execution state if this
- * is the {@link #commonPool()}, and no additional effect if
- * already shut down. Tasks that are in the process of being
- * submitted concurrently during the course of this method may or
- * may not be rejected.
- *
- * @throws SecurityException if a security manager exists and
- * the caller is not permitted to modify threads
- * because it does not hold {@link
- * java.lang.RuntimePermission}{@code ("modifyThread")}
- */
- public void shutdown() {
- checkPermission();
- tryTerminate(false, true);
- }
-
- /**
- * Possibly attempts to cancel and/or stop all tasks, and reject
- * all subsequently submitted tasks. Invocation has no effect on
- * execution state if this is the {@link #commonPool()}, and no
- * additional effect if already shut down. Otherwise, tasks that
- * are in the process of being submitted or executed concurrently
- * during the course of this method may or may not be
- * rejected. This method cancels both existing and unexecuted
- * tasks, in order to permit termination in the presence of task
- * dependencies. So the method always returns an empty list
- * (unlike the case for some other Executors).
- *
- * @return an empty list
- * @throws SecurityException if a security manager exists and
- * the caller is not permitted to modify threads
- * because it does not hold {@link
- * java.lang.RuntimePermission}{@code ("modifyThread")}
- */
- public List<Runnable> shutdownNow() {
- checkPermission();
- tryTerminate(true, true);
- return Collections.emptyList();
- }
-
- /**
- * Returns {@code true} if all tasks have completed following shut down.
- *
- * @return {@code true} if all tasks have completed following shut down
- */
- public boolean isTerminated() {
- long c = ctl;
- return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) + parallelism <= 0);
- }
-
- /**
- * Returns {@code true} if the process of termination has
- * commenced but not yet completed. This method may be useful for
- * debugging. A return of {@code true} reported a sufficient
- * period after shutdown may indicate that submitted tasks have
- * ignored or suppressed interruption, or are waiting for I/O,
- * causing this executor not to properly terminate. (See the
- * advisory notes for class {@link ForkJoinTask} stating that
- * tasks should not normally entail blocking operations. But if
- * they do, they must abort them on interrupt.)
- *
- * @return {@code true} if terminating but not yet terminated
- */
- public boolean isTerminating() {
- long c = ctl;
- return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) + parallelism > 0);
- }
-
- /**
- * Returns {@code true} if this pool has been shut down.
- *
- * @return {@code true} if this pool has been shut down
- */
- public boolean isShutdown() {
- return plock < 0;
- }
-
- /**
- * Blocks until all tasks have completed execution after a
- * shutdown request, or the timeout occurs, or the current thread
- * is interrupted, whichever happens first. Because the {@link
- * #commonPool()} never terminates until program shutdown, when
- * applied to the common pool, this method is equivalent to {@link
- * #awaitQuiescence(long, TimeUnit)} but always returns {@code false}.
- *
- * @param timeout the maximum time to wait
- * @param unit the time unit of the timeout argument
- * @return {@code true} if this executor terminated and
- * {@code false} if the timeout elapsed before termination
- * @throws InterruptedException if interrupted while waiting
- */
- public boolean awaitTermination(long timeout, TimeUnit unit)
- throws InterruptedException {
- if (Thread.interrupted())
- throw new InterruptedException();
- if (this == common) {
- awaitQuiescence(timeout, unit);
- return false;
- }
- long nanos = unit.toNanos(timeout);
- if (isTerminated())
- return true;
- if (nanos <= 0L)
- return false;
- long deadline = System.nanoTime() + nanos;
- synchronized (this) {
- for (;;) {
- if (isTerminated())
- return true;
- if (nanos <= 0L)
- return false;
- long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
- wait(millis > 0L ? millis : 1L);
- nanos = deadline - System.nanoTime();
- }
- }
- }
-
- /**
- * If called by a ForkJoinTask operating in this pool, equivalent
- * in effect to {@link ForkJoinTask#helpQuiesce}. Otherwise,
- * waits and/or attempts to assist performing tasks until this
- * pool {@link #isQuiescent} or the indicated timeout elapses.
- *
- * @param timeout the maximum time to wait
- * @param unit the time unit of the timeout argument
- * @return {@code true} if quiescent; {@code false} if the
- * timeout elapsed.
- */
- public boolean awaitQuiescence(long timeout, TimeUnit unit) {
- long nanos = unit.toNanos(timeout);
- ForkJoinWorkerThread wt;
- Thread thread = Thread.currentThread();
- if ((thread instanceof ForkJoinWorkerThread) &&
- (wt = (ForkJoinWorkerThread)thread).pool == this) {
- helpQuiescePool(wt.workQueue);
- return true;
- }
- long startTime = System.nanoTime();
- WorkQueue[] ws;
- int r = 0, m;
- boolean found = true;
- while (!isQuiescent() && (ws = workQueues) != null &&
- (m = ws.length - 1) >= 0) {
- if (!found) {
- if ((System.nanoTime() - startTime) > nanos)
- return false;
- Thread.yield(); // cannot block
- }
- found = false;
- for (int j = (m + 1) << 2; j >= 0; --j) {
- ForkJoinTask<?> t; WorkQueue q; int b;
- if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) {
- found = true;
- if ((t = q.pollAt(b)) != null)
- t.doExec();
- break;
- }
- }
- }
- return true;
- }
-
- /**
- * Waits and/or attempts to assist performing tasks indefinitely
- * until the {@link #commonPool()} {@link #isQuiescent}.
- */
- static void quiesceCommonPool() {
- common.awaitQuiescence(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
- }
-
- /**
- * Interface for extending managed parallelism for tasks running
- * in {@link ForkJoinPool}s.
- *
- * <p>A {@code ManagedBlocker} provides two methods. Method
- * {@code isReleasable} must return {@code true} if blocking is
- * not necessary. Method {@code block} blocks the current thread
- * if necessary (perhaps internally invoking {@code isReleasable}
- * before actually blocking). These actions are performed by any
- * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}.
- * The unusual methods in this API accommodate synchronizers that
- * may, but don't usually, block for long periods. Similarly, they
- * allow more efficient internal handling of cases in which
- * additional workers may be, but usually are not, needed to
- * ensure sufficient parallelism. Toward this end,
- * implementations of method {@code isReleasable} must be amenable
- * to repeated invocation.
- *
- * <p>For example, here is a ManagedBlocker based on a
- * ReentrantLock:
- * <pre> {@code
- * class ManagedLocker implements ManagedBlocker {
- * final ReentrantLock lock;
- * boolean hasLock = false;
- * ManagedLocker(ReentrantLock lock) { this.lock = lock; }
- * public boolean block() {
- * if (!hasLock)
- * lock.lock();
- * return true;
- * }
- * public boolean isReleasable() {
- * return hasLock || (hasLock = lock.tryLock());
- * }
- * }}</pre>
- *
- * <p>Here is a class that possibly blocks waiting for an
- * item on a given queue:
- * <pre> {@code
- * class QueueTaker<E> implements ManagedBlocker {
- * final BlockingQueue<E> queue;
- * volatile E item = null;
- * QueueTaker(BlockingQueue<E> q) { this.queue = q; }
- * public boolean block() throws InterruptedException {
- * if (item == null)
- * item = queue.take();
- * return true;
- * }
- * public boolean isReleasable() {
- * return item != null || (item = queue.poll()) != null;
- * }
- * public E getItem() { // call after pool.managedBlock completes
- * return item;
- * }
- * }}</pre>
- */
- public static interface ManagedBlocker {
- /**
- * Possibly blocks the current thread, for example waiting for
- * a lock or condition.
- *
- * @return {@code true} if no additional blocking is necessary
- * (i.e., if isReleasable would return true)
- * @throws InterruptedException if interrupted while waiting
- * (the method is not required to do so, but is allowed to)
- */
- boolean block() throws InterruptedException;
-
- /**
- * Returns {@code true} if blocking is unnecessary.
- * @return {@code true} if blocking is unnecessary
- */
- boolean isReleasable();
- }
-
- /**
- * Blocks in accord with the given blocker. If the current thread
- * is a {@link ForkJoinWorkerThread}, this method possibly
- * arranges for a spare thread to be activated if necessary to
- * ensure sufficient parallelism while the current thread is blocked.
- *
- * <p>If the caller is not a {@link ForkJoinTask}, this method is
- * behaviorally equivalent to
- * <pre> {@code
- * while (!blocker.isReleasable())
- * if (blocker.block())
- * return;
- * }</pre>
- *
- * If the caller is a {@code ForkJoinTask}, then the pool may
- * first be expanded to ensure parallelism, and later adjusted.
- *
- * @param blocker the blocker
- * @throws InterruptedException if blocker.block did so
- */
- public static void managedBlock(ManagedBlocker blocker)
- throws InterruptedException {
- Thread t = Thread.currentThread();
- if (t instanceof ForkJoinWorkerThread) {
- ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
- while (!blocker.isReleasable()) {
- if (p.tryCompensate(p.ctl)) {
- try {
- do {} while (!blocker.isReleasable() &&
- !blocker.block());
- } finally {
- p.incrementActiveCount();
- }
- break;
- }
- }
- }
- else {
- do {} while (!blocker.isReleasable() &&
- !blocker.block());
- }
- }
-
- // AbstractExecutorService overrides. These rely on undocumented
- // fact that ForkJoinTask.adapt returns ForkJoinTasks that also
- // implement RunnableFuture.
-
- protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
- return new ForkJoinTask.AdaptedRunnable<T>(runnable, value);
- }
-
- protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
- return new ForkJoinTask.AdaptedCallable<T>(callable);
- }
-
- @ikvm.internal.InterlockedCompareAndSet("ctl")
- private native boolean compareAndSwapLongCtl(long expect, long update);
-
- @ikvm.internal.InterlockedCompareAndSet("plock")
- private native boolean compareAndSwapIntPlock(int expect, int update);
-
- @ikvm.internal.InterlockedCompareAndSet("indexSeed")
- private native boolean compareAndSwapIntIndexSeed(int expect, int update);
-
- @ikvm.internal.InterlockedCompareAndSet("stealCount")
- private native boolean compareAndSwapLongStealCount(long expect, long update);
-
- private long getAndAddLongStealCount(long delta) {
- for (;;) {
- long value = stealCount;
- if (compareAndSwapLongStealCount(value, value + delta)) {
- return value;
- }
- }
- }
-
- // Unsafe mechanics
- private static final sun.misc.Unsafe U;
- private static final int ABASE;
- private static final int ASHIFT;
-
- static {
- // initialize field offsets for CAS etc
- try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> ak = ForkJoinTask[].class;
- ABASE = U.arrayBaseOffset(ak);
- int scale = U.arrayIndexScale(ak);
- if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
- throw new Error(e);
- }
-
- defaultForkJoinWorkerThreadFactory =
- new DefaultForkJoinWorkerThreadFactory();
- modifyThreadPermission = new RuntimePermission("modifyThread");
-
- common = java.security.AccessController.doPrivileged
- (new java.security.PrivilegedAction<ForkJoinPool>() {
- public ForkJoinPool run() { return makeCommonPool(); }});
- int par = common.parallelism; // report 1 even if threads disabled
- commonParallelism = par > 0 ? par : 1;
- }
-
- /**
- * Creates and returns the common pool, respecting user settings
- * specified via system properties.
- */
- private static ForkJoinPool makeCommonPool() {
- int parallelism = -1;
- ForkJoinWorkerThreadFactory factory = null;
- UncaughtExceptionHandler handler = null;
- try { // ignore exceptions in accessing/parsing properties
- String pp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.parallelism");
- String fp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.threadFactory");
- String hp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
- if (pp != null)
- parallelism = Integer.parseInt(pp);
- if (fp != null)
- factory = ((ForkJoinWorkerThreadFactory)ClassLoader.
- getSystemClassLoader().loadClass(fp).newInstance());
- if (hp != null)
- handler = ((UncaughtExceptionHandler)ClassLoader.
- getSystemClassLoader().loadClass(hp).newInstance());
- } catch (Exception ignore) {
- }
- if (factory == null) {
- if (System.getSecurityManager() == null)
- factory = defaultForkJoinWorkerThreadFactory;
- else // use security-managed default
- factory = new InnocuousForkJoinWorkerThreadFactory();
- }
- if (parallelism < 0 && // default 1 less than #cores
- (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
- parallelism = 1;
- if (parallelism > MAX_CAP)
- parallelism = MAX_CAP;
- return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
- "ForkJoinPool.commonPool-worker-");
- }
-
- /**
- * Factory for innocuous worker threads
- */
- static final class InnocuousForkJoinWorkerThreadFactory
- implements ForkJoinWorkerThreadFactory {
-
- /**
- * An ACC to restrict permissions for the factory itself.
- * The constructed workers have no permissions set.
- */
- private static final AccessControlContext innocuousAcc;
- static {
- Permissions innocuousPerms = new Permissions();
- innocuousPerms.add(modifyThreadPermission);
- innocuousPerms.add(new RuntimePermission(
- "enableContextClassLoaderOverride"));
- innocuousPerms.add(new RuntimePermission(
- "modifyThreadGroup"));
- innocuousAcc = new AccessControlContext(new ProtectionDomain[] {
- new ProtectionDomain(null, innocuousPerms)
- });
- }
-
- public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return (ForkJoinWorkerThread.InnocuousForkJoinWorkerThread)
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
- public ForkJoinWorkerThread run() {
- return new ForkJoinWorkerThread.
- InnocuousForkJoinWorkerThread(pool);
- }}, innocuousAcc);
- }
- }
-
-}
diff --git a/openjdk/map.xml b/openjdk/map.xml
index 21beaab3..5b6c2189 100644
--- a/openjdk/map.xml
+++ b/openjdk/map.xml
@@ -1830,15 +1830,6 @@
</body>
</method>
</class>
- <class name="sun.invoke.util.ValueConversions">
- <method name="castReference" sig="(Ljava.lang.Class;Ljava.lang.Object;)Ljava.lang.Object;">
- <replace-method-call class="java.lang.Class" name="isInstance" sig="(Ljava.lang.Object;)Z">
- <code>
- <call type="Java_sun_invoke_util_ValueConversions" name="Class_isInstance" sig="(Ljava.lang.Class;Ljava.lang.Object;)Z" />
- </code>
- </replace-method-call>
- </method>
- </class>
<class name="sun.invoke.util.VerifyAccess">
<method name="isTypeVisible" sig="(Ljava.lang.Class;Ljava.lang.Class;)Z">
<replace-method-call class="java.lang.Class" name="getClassLoader" sig="()Ljava.lang.ClassLoader;">
@@ -2964,6 +2955,15 @@
</body>
</method>
</class>
+ <class name="java.lang.invoke.MethodHandleImpl">
+ <method name="castReference" sig="(Ljava.lang.Class;Ljava.lang.Object;)Ljava.lang.Object;">
+ <replace-method-call class="java.lang.Class" name="isInstance" sig="(Ljava.lang.Object;)Z">
+ <code>
+ <call type="Java_java_lang_invoke_MethodHandleNatives" name="Class_isInstance" sig="(Ljava.lang.Class;Ljava.lang.Object;)Z" />
+ </code>
+ </replace-method-call>
+ </method>
+ </class>
<class name="java.lang.invoke.MethodHandles$Lookup">
<!-- We hook this to undo the fiddling we do to support string constructors -->
<method name="revealDirect" sig="(Ljava.lang.invoke.MethodHandle;)Ljava.lang.invoke.MethodHandleInfo;">
diff --git a/openjdk/openjdk.build b/openjdk/openjdk.build
index 2b3dd1af..3d7e1892 100644
--- a/openjdk/openjdk.build
+++ b/openjdk/openjdk.build
@@ -27,11 +27,11 @@
<property name="pathsep" value=":" />
<property overwrite="false" name="signoption" value="" />
<property overwrite="false" name="SkipSystemCoreDependency" value="false" />
- <property name="OPENJDK_VERSION" value="OpenJDK 8 b132" />
+ <property name="OPENJDK_VERSION" value="OpenJDK 8u45 b14" />
<property name="IMPLEMENTATION_VERSION" value="1.8.0" />
<property name="SPECIFICATION_VERSION" value="1.8" />
- <property name="FULL_VERSION" value="1.8.0-b132" />
- <property name="OpenJDK.dir" value="${project::get-base-directory()}/../../openjdk-8-b132" />
+ <property name="FULL_VERSION" value="1.8.0_45-b14" />
+ <property name="OpenJDK.dir" value="${project::get-base-directory()}/../../openjdk-8u45-b14" />
<if test="${platform::is-win32()}">
<property name="pathsep" value=";" />
</if>
@@ -192,7 +192,7 @@
</target>
<target name="classpath">
- <property name="CLASSPATH" value="mscorlib.jar${pathsep}System.Xml.jar${pathsep}${OpenJDK.dir}/jdk/src/share/classes/${pathsep}${OpenJDK.dir}/corba/src/share/classes" />
+ <property name="CLASSPATH" value="mscorlib.jar${pathsep}System.Xml.jar${pathsep}${OpenJDK.dir}/jdk/src/share/classes/${pathsep}${OpenJDK.dir}/corba/src/share/classes${pathsep}${OpenJDK.dir}/build/linux-x86_64-normal-server-release/jdk/gensrc" />
</target>
<target name="rmi" depends="classpath">
diff --git a/openjdk/response.txt b/openjdk/response.txt
index 409d55c9..f6b919d8 100644
--- a/openjdk/response.txt
+++ b/openjdk/response.txt
@@ -42,7 +42,6 @@
java/net/*.class
java/nio/*.class
java/security/*.class
- java/util/concurrent/*.class
java/util/concurrent/locks/*.class
gnu/java/util/*.class
sun/misc/*.class
@@ -123,6 +122,7 @@
@OPENJDK@/jdk/src/share/classes/jdk/internal/org/xml/sax/helpers/*.class
@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/*.class
@OPENJDK@/jdk/src/share/classes/jdk/internal/util/xml/impl/*.class
+ @OPENJDK@/jdk/src/share/classes/jdk/net/*.class
@OPENJDK@/jdk/src/share/classes/sun/invoke/*.class
@OPENJDK@/jdk/src/share/classes/sun/invoke/anon/*.class
@OPENJDK@/jdk/src/share/classes/sun/invoke/empty/*.class
@@ -192,7 +192,7 @@
}
{
-out:IKVM.OpenJDK.Corba.dll
- -baseaddress:0x57320000
+ -baseaddress:0x57350000
-recurse:resources.zip/com/sun/corba/*
-recurse:resources.zip/com/sun/jndi/cosnaming/jndiprovider.properties
-resource:com/sun/corba/se/impl/logging/LogStrings.properties=@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/classes/com/sun/corba/se/impl/logging/LogStrings.properties
@@ -313,7 +313,7 @@
}
{
-out:IKVM.OpenJDK.XML.API.dll
- -baseaddress:0x57950000
+ -baseaddress:0x57980000
-resource:META-INF/services/sun.util.spi.XmlPropertiesProvider=@OPENJDK@/jdk/src/share/classes/sun/util/xml/META-INF/services/sun.util.spi.XmlPropertiesProvider
@OPENJDK@/jaxp/src/javax/xml/*.class
@OPENJDK@/jaxp/src/javax/xml/datatype/*.class
@@ -348,7 +348,7 @@
}
{
-out:IKVM.OpenJDK.XML.XPath.dll
- -baseaddress:0x57A10000
+ -baseaddress:0x57A40000
-recurse:resources.zip/com/sun/org/apache/xalan/internal/res/*
@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/extensions/*.class
@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/res/*.class
@@ -373,9 +373,10 @@
}
{
-out:IKVM.OpenJDK.XML.Parse.dll
- -baseaddress:0x57D70000
+ -baseaddress:0x57DA0000
-recurse:resources.zip/com/sun/org/apache/xerces/*
-recurse:resources.zip/com/sun/org/apache/xml/internal/*
+ -recurse:resources.zip/com/sun/xml/internal/stream/*
@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SecuritySupport.class
@OPENJDK@/jaxp/src/com/sun/org/apache/bcel/internal/util/SecuritySupport$*.class
@OPENJDK@/jaxp/src/com/sun/org/apache/xalan/internal/utils/*.class
@@ -1048,7 +1049,7 @@
}
{
-out:IKVM.OpenJDK.Beans.dll
- -baseaddress:0x5C3F0000
+ -baseaddress:0x5C420000
-resource:META-INF/mailcap.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mailcap.default
-resource:META-INF/mimetypes.default=@OPENJDK@/jaxws/src/share/jaf_classes/META-INF/mimetypes.default
@OPENJDK@/jaxws/src/share/jaf_classes/com/sun/activation/registries/*.class
@@ -1064,7 +1065,7 @@
}
{
-out:IKVM.OpenJDK.Media.dll
- -baseaddress:0x5C4E0000
+ -baseaddress:0x5C510000
-resource:META-INF/services/javax.print.PrintServiceLookup=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup
-resource:META-INF/services/javax.print.StreamPrintServiceFactory=@OPENJDK@/jdk/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory
-resource:META-INF/services/javax.sound.midi.spi.MidiDeviceProvider=@OPENJDK@/jdk/src/share/classes/com/sun/media/sound/services/javax.sound.midi.spi.MidiDeviceProvider
@@ -1111,7 +1112,7 @@
}
{
-out:IKVM.OpenJDK.Nashorn.dll
- -baseaddress:0x5C750000
+ -baseaddress:0x5C780000
-resource:META-INF/services/javax.script.ScriptEngineFactory=@OPENJDK@/nashorn/src/META-INF/services/javax.script.ScriptEngineFactory
-resource:jdk/nashorn/internal/runtime/resources/version.properties=resources/nashorn/version.properties
-recurse:@OPENJDK@/nashorn/src/*.js
@@ -1121,6 +1122,7 @@
@OPENJDK@/nashorn/src/jdk/internal/dynalink/linker/*.class
@OPENJDK@/nashorn/src/jdk/internal/dynalink/support/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/api/scripting/*.class
+ @OPENJDK@/nashorn/src/jdk/nashorn/internal/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/codegen/types/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/ir/*.class
@@ -1133,7 +1135,9 @@
@OPENJDK@/nashorn/src/jdk/nashorn/internal/parser/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/arrays/*.class
+ @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/events/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/linker/*.class
+ @OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/logging/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/options/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/*.class
@OPENJDK@/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/*.class
@@ -1146,7 +1150,7 @@
}
{
-out:IKVM.OpenJDK.Localedata.dll
- -baseaddress:0x5CBA0000
+ -baseaddress:0x5CCF0000
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/ar/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/util/resources/be/*.class
@@ -1247,7 +1251,7 @@
}
{
-out:IKVM.OpenJDK.Cldrdata.dll
- -baseaddress:0x5D080000
+ -baseaddress:0x5D1D0000
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/aa/*.class
@OPENJDK@/build/linux-x86_64-normal-server-release/jdk/gensrc/sun/text/resources/cldr/af/*.class
diff --git a/openjdk/sun/awt/SunToolkit.java b/openjdk/sun/awt/SunToolkit.java
index 11612ec1..c20f288c 100644
--- a/openjdk/sun/awt/SunToolkit.java
+++ b/openjdk/sun/awt/SunToolkit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -36,6 +36,9 @@ import java.awt.image.*;
import java.awt.TrayIcon;
import java.awt.SystemTray;
import java.awt.event.InputEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -43,28 +46,24 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import sun.awt.datatransfer.DataTransferer;
import sun.security.util.SecurityConstants;
import sun.util.logging.PlatformLogger;
import sun.misc.SoftCache;
import sun.font.FontDesignMetrics;
import sun.awt.im.InputContext;
import sun.awt.image.*;
+import sun.net.util.URLUtil;
import sun.security.action.GetPropertyAction;
import sun.security.action.GetBooleanAction;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
public abstract class SunToolkit extends Toolkit
implements WindowClosingSupport, WindowClosingListener,
ComponentFactory, InputMethodSupport, KeyboardFocusManagerPeerProvider {
- // 8014736: logging has been removed from SunToolkit
+ // 8014718: logging has been removed from SunToolkit
/**
* Special mask for the UngrabEvent events, in addition to the
@@ -73,7 +72,6 @@ public abstract class SunToolkit extends Toolkit
*/
public static final int GRAB_EVENT_MASK = 0x80000000;
- private static Method wakeupMethod;
/* The key to put()/get() the PostEventQueue into/from the AppContext.
*/
private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
@@ -137,6 +135,9 @@ public abstract class SunToolkit extends Toolkit
public abstract FramePeer createFrame(Frame target)
throws HeadlessException;
+ public abstract FramePeer createLightweightFrame(LightweightFrame target)
+ throws HeadlessException;
+
public abstract DialogPeer createDialog(Dialog target)
throws HeadlessException;
@@ -197,12 +198,13 @@ public abstract class SunToolkit extends Toolkit
public abstract boolean isTraySupported();
+ @SuppressWarnings("deprecation")
public abstract FontPeer getFontPeer(String name, int style);
public abstract RobotPeer createRobot(Robot target, GraphicsDevice screen)
throws AWTException;
- public abstract KeyboardFocusManagerPeer createKeyboardFocusManagerPeer(KeyboardFocusManager manager)
+ public abstract KeyboardFocusManagerPeer getKeyboardFocusManagerPeer()
throws HeadlessException;
/**
@@ -296,52 +298,8 @@ public abstract class SunToolkit extends Toolkit
return appContext;
}
- public static Field getField(final Class klass, final String fieldName) {
- return AccessController.doPrivileged(new PrivilegedAction<Field>() {
- public Field run() {
- try {
- Field field = klass.getDeclaredField(fieldName);
- assert (field != null);
- field.setAccessible(true);
- return field;
- } catch (SecurityException e) {
- assert false;
- } catch (NoSuchFieldException e) {
- assert false;
- }
- return null;
- }//run
- });
- }
-
static void wakeupEventQueue(EventQueue q, boolean isShutdown){
- if (wakeupMethod == null){
- wakeupMethod = (Method)AccessController.doPrivileged(new PrivilegedAction(){
- public Object run(){
- try {
- Method method = EventQueue.class.getDeclaredMethod("wakeup",new Class [] {Boolean.TYPE} );
- if (method != null) {
- method.setAccessible(true);
- }
- return method;
- } catch (NoSuchMethodException e) {
- assert false;
- } catch (SecurityException e) {
- assert false;
- }
- return null;
- }//run
- });
- }
- try{
- if (wakeupMethod != null){
- wakeupMethod.invoke(q, new Object[]{Boolean.valueOf(isShutdown)});
- }
- } catch (InvocationTargetException e){
- assert false;
- } catch (IllegalAccessException e) {
- assert false;
- }
+ AWTAccessor.getEventQueueAccessor().wakeup(q, isShutdown);
}
/*
@@ -377,8 +335,8 @@ public abstract class SunToolkit extends Toolkit
// Maps from non-Component/MenuComponent to AppContext.
// WeakHashMap<Component,AppContext>
- private static final Map appContextMap =
- Collections.synchronizedMap(new WeakHashMap());
+ private static final Map<Object, AppContext> appContextMap =
+ Collections.synchronizedMap(new WeakHashMap<Object, AppContext>());
/**
* Sets the appContext field of target. If target is not a Component or
@@ -421,14 +379,14 @@ public abstract class SunToolkit extends Toolkit
* null or the target can't be found, a null with be returned.
*/
public static AppContext targetToAppContext(Object target) {
- if (target == null || GraphicsEnvironment.isHeadless()) {
+ if (target == null) {
return null;
}
AppContext context = getAppContext(target);
if (context == null) {
// target is not a Component/MenuComponent, try the
// appContextMap.
- context = (AppContext)appContextMap.get(target);
+ context = appContextMap.get(target);
}
return context;
}
@@ -473,9 +431,9 @@ public abstract class SunToolkit extends Toolkit
private static FocusTraversalPolicy createLayoutPolicy() {
FocusTraversalPolicy policy = null;
try {
- Class layoutPolicyClass =
+ Class<?> layoutPolicyClass =
Class.forName("javax.swing.LayoutFocusTraversalPolicy");
- policy = (FocusTraversalPolicy) layoutPolicyClass.newInstance();
+ policy = (FocusTraversalPolicy)layoutPolicyClass.newInstance();
}
catch (ClassNotFoundException e) {
assert false;
@@ -495,12 +453,10 @@ public abstract class SunToolkit extends Toolkit
* via targetToAppContext() above.
*/
public static void insertTargetMapping(Object target, AppContext appContext) {
- if (!GraphicsEnvironment.isHeadless()) {
- if (!setAppContext(target, appContext)) {
- // Target is not a Component/MenuComponent, use the private Map
- // instead.
- appContextMap.put(target, appContext);
- }
+ if (!setAppContext(target, appContext)) {
+ // Target is not a Component/MenuComponent, use the private Map
+ // instead.
+ appContextMap.put(target, appContext);
}
}
@@ -515,12 +471,29 @@ public abstract class SunToolkit extends Toolkit
if (event == null) {
throw new NullPointerException();
}
+
+ AWTAccessor.SequencedEventAccessor sea = AWTAccessor.getSequencedEventAccessor();
+ if (sea != null && sea.isSequencedEvent(event)) {
+ AWTEvent nested = sea.getNested(event);
+ if (nested.getID() == WindowEvent.WINDOW_LOST_FOCUS &&
+ nested instanceof TimedWindowEvent)
+ {
+ TimedWindowEvent twe = (TimedWindowEvent)nested;
+ ((SunToolkit)Toolkit.getDefaultToolkit()).
+ setWindowDeactivationTime((Window)twe.getSource(), twe.getWhen());
+ }
+ }
+
// All events posted via this method are system-generated.
// Placing the following call here reduces considerably the
// number of places throughout the toolkit that would
// otherwise have to be modified to precisely identify
// system-generated events.
setSystemGenerated(event);
+ AppContext eventContext = targetToAppContext(event.getSource());
+ if (eventContext != null && !eventContext.equals(appContext)) {
+ throw new RuntimeException("Event posted on wrong app context : " + event);
+ }
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if (postEventQueue != null) {
@@ -541,9 +514,6 @@ public abstract class SunToolkit extends Toolkit
postEvent(targetToAppContext(e.getSource()), pe);
}
- protected static final Lock flushLock = new ReentrantLock();
- private static boolean isFlushingPendingEvents = false;
-
/*
* Flush any pending events which haven't been posted to the AWT
* EventQueue yet.
@@ -553,36 +523,16 @@ public abstract class SunToolkit extends Toolkit
flushPendingEvents(appContext);
}
- public static void flushPendingEvents(AppContext appContext) {
- flushLock.lock();
- try {
- // Don't call flushPendingEvents() recursively
- if (!isFlushingPendingEvents) {
- isFlushingPendingEvents = true;
- try {
- PostEventQueue postEventQueue =
- (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
- if (postEventQueue != null) {
- postEventQueue.flush();
- }
- }
- finally {
- isFlushingPendingEvents = false;
- }
- }
- } finally {
- flushLock.unlock();
- }
- }
-
- public static boolean isPostEventQueueEmpty() {
- AppContext appContext = AppContext.getAppContext();
+ /*
+ * Flush the PostEventQueue for the right AppContext.
+ * The default flushPendingEvents only flushes the thread-local context,
+ * which is not always correct, c.f. 3746956
+ */
+ public static void flushPendingEvents(AppContext appContext) {
PostEventQueue postEventQueue =
- (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
+ (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if (postEventQueue != null) {
- return postEventQueue.noEvents();
- } else {
- return true;
+ postEventQueue.flush();
}
}
@@ -600,11 +550,13 @@ public abstract class SunToolkit extends Toolkit
* Fixed 5064013: the InvocationEvent time should be equals
* the time of the ActionEvent
*/
+ @SuppressWarnings("serial")
public static void executeOnEventHandlerThread(Object target,
Runnable runnable,
final long when) {
- executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT){
- public long getWhen(){
+ executeOnEventHandlerThread(
+ new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT) {
+ public long getWhen() {
return when;
}
});
@@ -685,6 +637,12 @@ public abstract class SunToolkit extends Toolkit
protected abstract int getScreenWidth();
protected abstract int getScreenHeight();
+ @SuppressWarnings("deprecation")
+ public FontMetrics getFontMetrics(Font font) {
+ return FontDesignMetrics.getMetrics(font);
+ }
+
+ @SuppressWarnings("deprecation")
public String[] getFontList() {
String[] hardwiredFontList = {
Font.DIALOG, Font.SANS_SERIF, Font.SERIF, Font.MONOSPACED,
@@ -749,10 +707,100 @@ public abstract class SunToolkit extends Toolkit
return AccessController.doPrivileged(new GetBooleanAction("sun.awt.erasebackgroundonresize"));
}
+
+ static final SoftCache imgCache = new SoftCache();
+
+ static Image getImageFromHash(Toolkit tk, URL url) {
+ checkPermissions(url);
+ synchronized (imgCache) {
+ Image img = (Image)imgCache.get(url);
+ if (img == null) {
+ try {
+ img = tk.createImage(new URLImageSource(url));
+ imgCache.put(url, img);
+ } catch (Exception e) {
+ }
+ }
+ return img;
+ }
+ }
+
+ static Image getImageFromHash(Toolkit tk,
+ String filename) {
+ checkPermissions(filename);
+ synchronized (imgCache) {
+ Image img = (Image)imgCache.get(filename);
+ if (img == null) {
+ try {
+ img = tk.createImage(new FileImageSource(filename));
+ imgCache.put(filename, img);
+ } catch (Exception e) {
+ }
+ }
+ return img;
+ }
+ }
+
+ public Image getImage(String filename) {
+ return getImageFromHash(this, filename);
+ }
+
+ public Image getImage(URL url) {
+ return getImageFromHash(this, url);
+ }
+
+ protected Image getImageWithResolutionVariant(String fileName,
+ String resolutionVariantName) {
+ synchronized (imgCache) {
+ Image image = getImageFromHash(this, fileName);
+ if (image instanceof MultiResolutionImage) {
+ return image;
+ }
+ Image resolutionVariant = getImageFromHash(this, resolutionVariantName);
+ image = createImageWithResolutionVariant(image, resolutionVariant);
+ imgCache.put(fileName, image);
+ return image;
+ }
+ }
+
+ protected Image getImageWithResolutionVariant(URL url,
+ URL resolutionVariantURL) {
+ synchronized (imgCache) {
+ Image image = getImageFromHash(this, url);
+ if (image instanceof MultiResolutionImage) {
+ return image;
+ }
+ Image resolutionVariant = getImageFromHash(this, resolutionVariantURL);
+ image = createImageWithResolutionVariant(image, resolutionVariant);
+ imgCache.put(url, image);
+ return image;
+ }
+ }
+
+
+ public Image createImage(String filename) {
+ checkPermissions(filename);
+ return createImage(new FileImageSource(filename));
+ }
+
+ public Image createImage(URL url) {
+ checkPermissions(url);
+ return createImage(new URLImageSource(url));
+ }
+
+ public Image createImage(byte[] data, int offset, int length) {
+ return createImage(new ByteArrayImageSource(data, offset, length));
+ }
+
public Image createImage(ImageProducer producer) {
return new ToolkitImage(producer);
}
+ public static Image createImageWithResolutionVariant(Image image,
+ Image resolutionVariant) {
+ return new MultiResolutionToolkitImage(image, resolutionVariant);
+ }
+
public int checkImage(Image img, int w, int h, ImageObserver o) {
if (!(img instanceof ToolkitImage)) {
return ImageObserver.ALLBITS;
@@ -765,7 +813,7 @@ public abstract class SunToolkit extends Toolkit
} else {
repbits = tkimg.getImageRep().check(o);
}
- return tkimg.check(o) | repbits;
+ return (tkimg.check(o) | repbits) & checkResolutionVariant(img, w, h, o);
}
public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
@@ -787,7 +835,105 @@ public abstract class SunToolkit extends Toolkit
return false;
}
ImageRepresentation ir = tkimg.getImageRep();
- return ir.prepare(o);
+ return ir.prepare(o) & prepareResolutionVariant(img, w, h, o);
+ }
+
+ private int checkResolutionVariant(Image img, int w, int h, ImageObserver o) {
+ ToolkitImage rvImage = getResolutionVariant(img);
+ int rvw = getRVSize(w);
+ int rvh = getRVSize(h);
+ // Ignore the resolution variant in case of error
+ return (rvImage == null || rvImage.hasError()) ? 0xFFFF :
+ checkImage(rvImage, rvw, rvh, MultiResolutionToolkitImage.
+ getResolutionVariantObserver(
+ img, o, w, h, rvw, rvh, true));
+ }
+
+ private boolean prepareResolutionVariant(Image img, int w, int h,
+ ImageObserver o) {
+
+ ToolkitImage rvImage = getResolutionVariant(img);
+ int rvw = getRVSize(w);
+ int rvh = getRVSize(h);
+ // Ignore the resolution variant in case of error
+ return rvImage == null || rvImage.hasError() || prepareImage(
+ rvImage, rvw, rvh,
+ MultiResolutionToolkitImage.getResolutionVariantObserver(
+ img, o, w, h, rvw, rvh, true));
+ }
+
+ private static int getRVSize(int size){
+ return size == -1 ? -1 : 2 * size;
+ }
+
+ private static ToolkitImage getResolutionVariant(Image image) {
+ if (image instanceof MultiResolutionToolkitImage) {
+ Image resolutionVariant = ((MultiResolutionToolkitImage) image).
+ getResolutionVariant();
+ if (resolutionVariant instanceof ToolkitImage) {
+ return (ToolkitImage) resolutionVariant;
+ }
+ }
+ return null;
+ }
+
+ protected static boolean imageCached(Object key) {
+ return imgCache.containsKey(key);
+ }
+
+ protected static boolean imageExists(String filename) {
+ checkPermissions(filename);
+ return filename != null && new File(filename).exists();
+ }
+
+ @SuppressWarnings("try")
+ protected static boolean imageExists(URL url) {
+ checkPermissions(url);
+ if (url != null) {
+ try (InputStream is = url.openStream()) {
+ return true;
+ }catch(IOException e){
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private static void checkPermissions(String filename) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(filename);
+ }
+ }
+
+ private static void checkPermissions(URL url) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ java.security.Permission perm =
+ URLUtil.getConnectPermission(url);
+ if (perm != null) {
+ try {
+ sm.checkPermission(perm);
+ } catch (SecurityException se) {
+ // fallback to checkRead/checkConnect for pre 1.2
+ // security managers
+ if ((perm instanceof java.io.FilePermission) &&
+ perm.getActions().indexOf("read") != -1) {
+ sm.checkRead(perm.getName());
+ } else if ((perm instanceof
+ java.net.SocketPermission) &&
+ perm.getActions().indexOf("connect") != -1) {
+ sm.checkConnect(url.getHost(), url.getPort());
+ } else {
+ throw se;
+ }
+ }
+ }
+ } catch (java.io.IOException ioe) {
+ sm.checkConnect(url.getHost(), url.getPort());
+ }
+ }
}
/**
@@ -984,6 +1130,20 @@ public abstract class SunToolkit extends Toolkit
}
/**
+ * Returns a new input method window, with behavior as specified in
+ * {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}.
+ * If the inputContext is not null, the window should return it from its
+ * getInputContext() method. The window needs to implement
+ * sun.awt.im.InputMethodWindow.
+ * <p>
+ * SunToolkit subclasses can override this method to return better input
+ * method windows.
+ */
+ public Window createInputMethodWindow(String title, InputContext context) {
+ throw new Error();
+ }
+
+ /**
* Returns whether enableInputMethods should be set to true for peered
* TextComponent instances on this platform. False by default.
*/
@@ -999,10 +1159,10 @@ public abstract class SunToolkit extends Toolkit
public static Locale getStartupLocale() {
if (startupLocale == null) {
String language, region, country, variant;
- language = (String) AccessController.doPrivileged(
+ language = AccessController.doPrivileged(
new GetPropertyAction("user.language", "en"));
// for compatibility, check for old user.region property
- region = (String) AccessController.doPrivileged(
+ region = AccessController.doPrivileged(
new GetPropertyAction("user.region"));
if (region != null) {
// region can be of form country, country_variant, or _variant
@@ -1015,9 +1175,9 @@ public abstract class SunToolkit extends Toolkit
variant = "";
}
} else {
- country = (String) AccessController.doPrivileged(
+ country = AccessController.doPrivileged(
new GetPropertyAction("user.country", ""));
- variant = (String) AccessController.doPrivileged(
+ variant = AccessController.doPrivileged(
new GetPropertyAction("user.variant", ""));
}
startupLocale = new Locale(language, country, variant);
@@ -1032,19 +1192,6 @@ public abstract class SunToolkit extends Toolkit
return getStartupLocale();
}
- private static String dataTransfererClassName = null;
-
- protected static void setDataTransfererClassName(String className) {
- dataTransfererClassName = className;
- }
-
- public static String getDataTransfererClassName() {
- if (dataTransfererClassName == null) {
- Toolkit.getDefaultToolkit(); // transferer set during toolkit init
- }
- return dataTransfererClassName;
- }
-
// Support for window closing event notifications
private transient WindowClosingListener windowClosingListener = null;
/**
@@ -1089,7 +1236,7 @@ public abstract class SunToolkit extends Toolkit
* @return <code>true</code>, if XEmbed is needed, <code>false</code> otherwise
*/
public static boolean needsXEmbed() {
- String noxembed = (String) AccessController.
+ String noxembed = AccessController.
doPrivileged(new GetPropertyAction("sun.awt.noxembed", "false"));
if ("true".equals(noxembed)) {
return false;
@@ -1301,22 +1448,7 @@ public abstract class SunToolkit extends Toolkit
|| comp instanceof Window);
}
- public static Method getMethod(final Class clz, final String methodName, final Class[] params) {
- Method res = null;
- try {
- res = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
- public Method run() throws Exception {
- Method m = clz.getDeclaredMethod(methodName, params);
- m.setAccessible(true);
- return m;
- }
- });
- } catch (PrivilegedActionException ex) {
- ex.printStackTrace();
- }
- return res;
- }
-
+ @SuppressWarnings("serial")
public static class OperationTimedOut extends RuntimeException {
public OperationTimedOut(String msg) {
super(msg);
@@ -1324,9 +1456,12 @@ public abstract class SunToolkit extends Toolkit
public OperationTimedOut() {
}
}
+
+ @SuppressWarnings("serial")
public static class InfiniteLoop extends RuntimeException {
}
+ @SuppressWarnings("serial")
public static class IllegalThreadException extends RuntimeException {
public IllegalThreadException(String msg) {
super(msg);
@@ -1459,21 +1594,9 @@ public abstract class SunToolkit extends Toolkit
private boolean queueEmpty = false;
private final Object waitLock = "Wait Lock";
- static Method eqNoEvents;
-
private boolean isEQEmpty() {
EventQueue queue = getSystemEventQueueImpl();
- synchronized(SunToolkit.class) {
- if (eqNoEvents == null) {
- eqNoEvents = getMethod(java.awt.EventQueue.class, "noEvents", null);
- }
- }
- try {
- return (Boolean)eqNoEvents.invoke(queue);
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
+ return AWTAccessor.getEventQueueAccessor().noEvents(queue);
}
/**
@@ -1483,6 +1606,7 @@ public abstract class SunToolkit extends Toolkit
* Should return <code>true</code> if more processing is
* necessary, <code>false</code> otherwise.
*/
+ @SuppressWarnings("serial")
protected final boolean waitForIdle(final long timeout) {
flushPendingEvents();
boolean queueWasEmpty = isEQEmpty();
@@ -1666,7 +1790,7 @@ public abstract class SunToolkit extends Toolkit
Toolkit tk = Toolkit.getDefaultToolkit();
if (tk instanceof SunToolkit) {
systemAAFonts =
- (String)AccessController.doPrivileged(
+ AccessController.doPrivileged(
new GetPropertyAction("awt.useSystemAAFontSettings"));
}
if (systemAAFonts != null) {
@@ -1728,20 +1852,14 @@ public abstract class SunToolkit extends Toolkit
* consumeNextKeyTyped() method is not currently used,
* however Swing could use it in the future.
*/
- private static Method consumeNextKeyTypedMethod = null;
public static synchronized void consumeNextKeyTyped(KeyEvent keyEvent) {
- if (consumeNextKeyTypedMethod == null) {
- consumeNextKeyTypedMethod = getMethod(DefaultKeyboardFocusManager.class,
- "consumeNextKeyTyped",
- new Class[] {KeyEvent.class});
- }
try {
- consumeNextKeyTypedMethod.invoke(KeyboardFocusManager.getCurrentKeyboardFocusManager(),
- keyEvent);
- } catch (IllegalAccessException iae) {
- iae.printStackTrace();
- } catch (InvocationTargetException ite) {
- ite.printStackTrace();
+ AWTAccessor.getDefaultKeyboardFocusManagerAccessor().consumeNextKeyTyped(
+ (DefaultKeyboardFocusManager)KeyboardFocusManager.
+ getCurrentKeyboardFocusManager(),
+ keyEvent);
+ } catch (ClassCastException cce) {
+ cce.printStackTrace();
}
}
@@ -1861,7 +1979,7 @@ public abstract class SunToolkit extends Toolkit
*/
public static boolean isContainingTopLevelTranslucent(Component c) {
Window w = getContainingWindow(c);
- return w != null && ((Window)w).getOpacity() < 1.0f;
+ return w != null && w.getOpacity() < 1.0f;
}
/**
@@ -1903,14 +2021,14 @@ public abstract class SunToolkit extends Toolkit
return isInstanceOf(obj.getClass(), type);
}
- private static boolean isInstanceOf(Class cls, String type) {
+ private static boolean isInstanceOf(Class<?> cls, String type) {
if (cls == null) return false;
if (cls.getName().equals(type)) {
return true;
}
- for (Class c : cls.getInterfaces()) {
+ for (Class<?> c : cls.getInterfaces()) {
if (c.getName().equals(type)) {
return true;
}
@@ -1918,6 +2036,19 @@ public abstract class SunToolkit extends Toolkit
return isInstanceOf(cls.getSuperclass(), type);
}
+ protected static LightweightFrame getLightweightFrame(Component c) {
+ for (; c != null; c = c.getParent()) {
+ if (c instanceof LightweightFrame) {
+ return (LightweightFrame)c;
+ }
+ if (c instanceof Window) {
+ // Don't traverse owner windows
+ return null;
+ }
+ }
+ return null;
+ }
+
///////////////////////////////////////////////////////////////////////////
//
// The following methods help set and identify whether a particular
@@ -1953,17 +2084,12 @@ class PostEventQueue {
private EventQueueItem queueTail = null;
private final EventQueue eventQueue;
- // For the case when queue is cleared but events are not posted
- private volatile boolean isFlushing = false;
+ private Thread flushThread = null;
PostEventQueue(EventQueue eq) {
eventQueue = eq;
}
- public synchronized boolean noEvents() {
- return queueHead == null && !isFlushing;
- }
-
/*
* Continually post pending AWTEvents to the Java EventQueue. The method
* is synchronized to ensure the flush is completed before a new event
@@ -1974,20 +2100,48 @@ class PostEventQueue {
* potentially lead to deadlock
*/
public void flush() {
- EventQueueItem tempQueue;
- synchronized (this) {
- tempQueue = queueHead;
- queueHead = queueTail = null;
- isFlushing = (tempQueue != null);
- }
+
+ Thread newThread = Thread.currentThread();
+
try {
- while (tempQueue != null) {
- eventQueue.postEvent(tempQueue.event);
- tempQueue = tempQueue.next;
+ EventQueueItem tempQueue;
+ synchronized (this) {
+ // Avoid method recursion
+ if (newThread == flushThread) {
+ return;
+ }
+ // Wait for other threads' flushing
+ while (flushThread != null) {
+ wait();
+ }
+ // Skip everything if queue is empty
+ if (queueHead == null) {
+ return;
+ }
+ // Remember flushing thread
+ flushThread = newThread;
+
+ tempQueue = queueHead;
+ queueHead = queueTail = null;
+ }
+ try {
+ while (tempQueue != null) {
+ eventQueue.postEvent(tempQueue.event);
+ tempQueue = tempQueue.next;
+ }
+ }
+ finally {
+ // Only the flushing thread can get here
+ synchronized (this) {
+ // Forget flushing thread, inform other pending threads
+ flushThread = null;
+ notifyAll();
+ }
}
}
- finally {
- isFlushing = false;
+ catch (InterruptedException e) {
+ // Couldn't allow exception go up, so at least recover the flag
+ newThread.interrupt();
}
}
diff --git a/openjdk/sun/awt/shell/Win32ShellFolder2.java b/openjdk/sun/awt/shell/Win32ShellFolder2.java
index 0f5f6816..c7d6ea86 100644
--- a/openjdk/sun/awt/shell/Win32ShellFolder2.java
+++ b/openjdk/sun/awt/shell/Win32ShellFolder2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (C) 2009 Volker Berlin (i-net software)
* Copyright (C) 2010 Karsten Heinrich (i-net software)
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -596,8 +596,23 @@ final class Win32ShellFolder2 extends ShellFolder {
}
// Needs to be accessible to Win32ShellFolderManager2
- @cli.System.Security.SecurityCriticalAttribute.Annotation
- static native String getFileSystemPath(int csidl) throws IOException, InterruptedException;
+ static String getFileSystemPath(final int csidl) throws IOException, InterruptedException {
+ String path = invoke(new Callable<String>() {
+ public String call() throws IOException {
+ return getFileSystemPath0(csidl);
+ }
+ }, IOException.class);
+ if (path != null) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(path);
+ }
+ }
+ return path;
+ }
+
+ // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
+ private static native String getFileSystemPath0(int csidl) throws IOException;
// Return whether the path is a network root.
// Path is assumed to be non-null
diff --git a/openjdk/sun/awt/shell/Win32ShellFolderManager2.java b/openjdk/sun/awt/shell/Win32ShellFolderManager2.java
index d688b6a0..09bbe97f 100644
--- a/openjdk/sun/awt/shell/Win32ShellFolderManager2.java
+++ b/openjdk/sun/awt/shell/Win32ShellFolderManager2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -36,14 +36,15 @@ import java.security.PrivilegedAction;
import java.util.*;
import java.util.List;
import java.util.concurrent.*;
+import java.util.stream.Stream;
import cli.System.IntPtr;
import cli.System.Drawing.Bitmap;
import cli.System.Drawing.SystemIcons;
-import sun.security.action.LoadLibraryAction;
import static sun.awt.shell.Win32ShellFolder2.*;
import sun.awt.OSInfo;
+import sun.misc.ThreadGroupUtils;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
@@ -139,6 +140,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (desktop == null) {
try {
desktop = new Win32ShellFolder2(DESKTOP);
+ } catch (SecurityException e) {
+ // Ignore error
} catch (IOException e) {
// Ignore error
} catch (InterruptedException e) {
@@ -152,6 +155,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (drives == null) {
try {
drives = new Win32ShellFolder2(DRIVES);
+ } catch (SecurityException e) {
+ // Ignore error
} catch (IOException e) {
// Ignore error
} catch (InterruptedException e) {
@@ -169,6 +174,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (path != null) {
recent = createShellFolder(getDesktop(), new File(path));
}
+ } catch (SecurityException e) {
+ // Ignore error
} catch (InterruptedException e) {
// Ignore error
} catch (IOException e) {
@@ -182,6 +189,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (network == null) {
try {
network = new Win32ShellFolder2(NETWORK);
+ } catch (SecurityException e) {
+ // Ignore error
} catch (IOException e) {
// Ignore error
} catch (InterruptedException e) {
@@ -206,6 +215,8 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
personal.setIsPersonal();
}
}
+ } catch (SecurityException e) {
+ // Ignore error
} catch (InterruptedException e) {
// Ignore error
} catch (IOException e) {
@@ -246,7 +257,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
if (file == null) {
file = getDesktop();
}
- return file;
+ return checkFile(file);
} else if (key.equals("roots")) {
// Should be "History" and "Desktop" ?
if (roots == null) {
@@ -257,11 +268,11 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
roots = (File[])super.get(key);
}
}
- return roots;
+ return checkFiles(roots);
} else if (key.equals("fileChooserComboBoxFolders")) {
Win32ShellFolder2 desktop = getDesktop();
- if (desktop != null) {
+ if (desktop != null && checkFile(desktop) != null) {
ArrayList<File> folders = new ArrayList<File>();
Win32ShellFolder2 drives = getDrives();
@@ -272,15 +283,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
folders.add(desktop);
// Add all second level folders
- File[] secondLevelFolders = desktop.listFiles();
+ File[] secondLevelFolders = checkFiles(desktop.listFiles());
Arrays.sort(secondLevelFolders);
for (File secondLevelFolder : secondLevelFolders) {
Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder;
- if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink()) ) {
+ if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) {
folders.add(folder);
// Add third level for "My Computer"
if (folder.equals(drives)) {
- File[] thirdLevelFolders = folder.listFiles();
+ File[] thirdLevelFolders = checkFiles(folder.listFiles());
if (thirdLevelFolders != null && thirdLevelFolders.length > 0) {
List<File> thirdLevelFoldersList = Arrays.asList(thirdLevelFolders);
@@ -290,7 +301,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
}
}
}
- return folders.toArray(new File[folders.size()]);
+ return checkFiles(folders);
} else {
return super.get(key);
}
@@ -327,7 +338,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
}
}
}
- return folders.toArray(new File[folders.size()]);
+ return checkFiles(folders);
} else if (key.startsWith("fileChooserIcon ")) {
String name = key.substring(key.indexOf(" ") + 1);
@@ -373,6 +384,41 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
return null;
}
+ private File checkFile(File file) {
+ SecurityManager sm = System.getSecurityManager();
+ return (sm == null || file == null) ? file : checkFile(file, sm);
+ }
+
+ private File checkFile(File file, SecurityManager sm) {
+ try {
+ sm.checkRead(file.getPath());
+ return file;
+ } catch (SecurityException se) {
+ return null;
+ }
+ }
+
+ private File[] checkFiles(File[] files) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null || files == null || files.length == 0) {
+ return files;
+ }
+ return checkFiles(Arrays.stream(files), sm);
+ }
+
+ private File[] checkFiles(List<File> files) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm == null || files.isEmpty()) {
+ return files.toArray(new File[files.size()]);
+ }
+ return checkFiles(files.stream(), sm);
+ }
+
+ private File[] checkFiles(Stream<File> filesStream, SecurityManager sm) {
+ return filesStream.filter((file) -> checkFile(file, sm) != null)
+ .toArray(File[]::new);
+ }
+
/**
* Does <code>dir</code> represent a "computer" such as a node on the network, or
* "My Computer" on the desktop.
diff --git a/openjdk/sun/java2d/loops/TransformHelper.java b/openjdk/sun/java2d/loops/TransformHelper.java
new file mode 100644
index 00000000..29208ff8
--- /dev/null
+++ b/openjdk/sun/java2d/loops/TransformHelper.java
@@ -0,0 +1,27 @@
+/*
+ Copyright (C) 2015 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+package sun.java2d.loops;
+
+// only needed at compile time, to satisfy import statement
+public class TransformHelper { }
diff --git a/openjdk/sun/misc/VM.java b/openjdk/sun/misc/VM.java
index 6cfa7fbe..2607d95f 100644
--- a/openjdk/sun/misc/VM.java
+++ b/openjdk/sun/misc/VM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -48,6 +48,7 @@ public class VM {
return suspended;
}
+ @SuppressWarnings("deprecation")
public static boolean allowThreadSuspension(ThreadGroup g, boolean b) {
return g.allowThreadSuspension(b);
}
@@ -145,7 +146,9 @@ public class VM {
*/
// public native static void writeJavaProfilerReport();
+
private static volatile boolean booted = false;
+ private static final Object lock = new Object();
static {
// [IKVM] force System properties initialization ("booting")
@@ -163,13 +166,27 @@ public class VM {
// the booted flag to determine whether it is safe to query the system
// properties).
public static void booted() {
- booted = true;
+ synchronized (lock) {
+ booted = true;
+ lock.notifyAll();
+ }
}
public static boolean isBooted() {
return booted;
}
+ // Waits until VM completes initialization
+ //
+ // This method is invoked by the Finalizer thread
+ public static void awaitBooted() throws InterruptedException {
+ synchronized (lock) {
+ while (!booted) {
+ lock.wait();
+ }
+ }
+ }
+
// Returns the maximum amount of allocatable direct buffer memory.
// The directMemory variable is initialized during system initialization
// in the saveAndRemoveProperties method.
@@ -217,6 +234,14 @@ public class VM {
}
/**
+ * Returns true if the given class loader is in the system domain
+ * in which all permissions are granted.
+ */
+ public static boolean isSystemDomainLoader(ClassLoader loader) {
+ return loader == null;
+ }
+
+ /**
* Returns the system property of the specified key saved at
* system initialization time. This method should only be used
* for the system properties that are not changed during runtime.
@@ -282,6 +307,9 @@ public class VM {
// used by sun.launcher.LauncherHelper
props.remove("sun.java.launcher.diag");
+
+ // used by sun.misc.URLClassPath
+ props.remove("sun.cds.enableSharedLookupCache");
}
// Initialize any miscellenous operating system settings that need to be
@@ -361,6 +389,12 @@ public class VM {
private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
+ /*
+ * Returns the first non-null class loader up the execution stack,
+ * or null if only code from the null class loader is on the stack.
+ */
+ public static native ClassLoader latestUserDefinedLoader();
+
static {
initialize();
}
diff --git a/openjdk/sun/misc/Version.java b/openjdk/sun/misc/Version.java
index 7e0f3724..e11b3671 100644
--- a/openjdk/sun/misc/Version.java
+++ b/openjdk/sun/misc/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -33,13 +33,16 @@ public class Version {
"openjdk";
private static final String java_version =
- "1.7.0-internal";
+ "1.8.0-internal";
private static final String java_runtime_name =
- "OpenJDK Runtime Environment";
-
+ "OpenJDK Runtime Environment";
+
+ private static final String java_profile_name =
+ "";
+
private static final String java_runtime_version =
- "1.7.0-internal-jeroen_2012_05_22_06_05-b00";
+ "1.8.0-internal-jeroen_2015_06_02_10_38-b00";
static {
init();
@@ -87,23 +90,28 @@ public class Version {
boolean isHeadless = false;
/* Report that we're running headless if the property is true */
- String headless = System.getProperty("java.awt.headless");
- if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
+ String headless = System.getProperty("java.awt.headless");
+ if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
isHeadless = true;
- }
+ }
/* First line: platform version. */
ps.println(launcher_name + " version \"" + java_version + "\"");
/* Second line: runtime version (ie, libraries). */
- ps.print(java_runtime_name + " (build " + java_runtime_version);
+ ps.print(java_runtime_name + " (build " + java_runtime_version);
- if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
- // embedded builds report headless state
- ps.print(", headless");
- }
- ps.println(')');
+ if (java_profile_name.length() > 0) {
+ // profile name
+ ps.print(", profile " + java_profile_name);
+ }
+
+ if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
+ // embedded builds report headless state
+ ps.print(", headless");
+ }
+ ps.println(')');
/* Third line: JVM information. */
String java_vm_name = System.getProperty("java.vm.name");
@@ -328,7 +336,6 @@ public class Version {
// Return false if not available which implies an old VM (Tiger or before).
private static native boolean getJvmVersionInfo();
private static native void getJdkVersionInfo();
-
}
// Help Emacs a little because this file doesn't end in .java.
diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java
index 08cc5c95..b2c8607b 100644
--- a/openjdk/sun/nio/ch/DatagramChannelImpl.java
+++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -33,7 +33,7 @@ import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
import sun.net.ResourceManager;
-
+import sun.net.ExtendedOptionsImpl;
/**
* An implementation of DatagramChannels.
@@ -169,6 +169,7 @@ class DatagramChannelImpl
synchronized (stateLock) {
if (!isOpen())
throw new ClosedChannelException();
+ // Perform security check before returning address
return Net.getRevealedLocalAddress(localAddress);
}
}
@@ -194,15 +195,8 @@ class DatagramChannelImpl
synchronized (stateLock) {
ensureOpen();
- if (name == StandardSocketOptions.IP_TOS) {
- // IPv4 only; no-op for IPv6
- if (family == StandardProtocolFamily.INET) {
- Net.setSocketOption(fd, family, name, value);
- }
- return this;
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
+ if (name == StandardSocketOptions.IP_TOS ||
+ name == StandardSocketOptions.IP_MULTICAST_TTL ||
name == StandardSocketOptions.IP_MULTICAST_LOOP)
{
// options are protocol dependent
@@ -255,16 +249,8 @@ class DatagramChannelImpl
synchronized (stateLock) {
ensureOpen();
- if (name == StandardSocketOptions.IP_TOS) {
- // IPv4 only; always return 0 on IPv6
- if (family == StandardProtocolFamily.INET) {
- return (T) Net.getSocketOption(fd, family, name);
- } else {
- return (T) Integer.valueOf(0);
- }
- }
-
- if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
+ if (name == StandardSocketOptions.IP_TOS ||
+ name == StandardSocketOptions.IP_MULTICAST_TTL ||
name == StandardSocketOptions.IP_MULTICAST_LOOP)
{
return (T) Net.getSocketOption(fd, family, name);
@@ -317,6 +303,9 @@ class DatagramChannelImpl
set.add(StandardSocketOptions.IP_MULTICAST_IF);
set.add(StandardSocketOptions.IP_MULTICAST_TTL);
set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+ if (ExtendedOptionsImpl.flowSupported()) {
+ set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
+ }
return Collections.unmodifiableSet(set);
}
}
@@ -553,7 +542,7 @@ class DatagramChannelImpl
return 0;
readerThread = NativeThread.current();
do {
- n = IOUtil.read(fd, buf, -1, nd, readLock);
+ n = IOUtil.read(fd, buf, -1, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -609,7 +598,7 @@ class DatagramChannelImpl
return 0;
writerThread = NativeThread.current();
do {
- n = IOUtil.write(fd, buf, -1, nd, writeLock);
+ n = IOUtil.write(fd, buf, -1, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
@@ -747,6 +736,26 @@ class DatagramChannelImpl
// set or refresh local address
localAddress = Net.localAddress(fd);
+
+ // flush any packets already received.
+ boolean blocking = false;
+ synchronized (blockingLock()) {
+ try {
+ blocking = isBlocking();
+ // remainder of each packet thrown away
+ ByteBuffer tmpBuf = ByteBuffer.allocate(1);
+ if (blocking) {
+ configureBlocking(false);
+ }
+ do {
+ tmpBuf.clear();
+ } while (receive(tmpBuf) != null);
+ } finally {
+ if (blocking) {
+ configureBlocking(true);
+ }
+ }
+ }
}
}
}
@@ -1032,25 +1041,24 @@ class DatagramChannelImpl
int oldOps = sk.nioReadyOps();
int newOps = initialOps;
- if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+ if ((ops & Net.POLLNVAL) != 0) {
// This should only happen if this channel is pre-closed while a
// selection operation is in progress
// ## Throw an error if this channel has not been pre-closed
return false;
}
- if ((ops & (PollArrayWrapper.POLLERR
- | PollArrayWrapper.POLLHUP)) != 0) {
+ if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
newOps = intOps;
sk.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
- if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+ if (((ops & Net.POLLIN) != 0) &&
((intOps & SelectionKey.OP_READ) != 0))
newOps |= SelectionKey.OP_READ;
- if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+ if (((ops & Net.POLLOUT) != 0) &&
((intOps & SelectionKey.OP_WRITE) != 0))
newOps |= SelectionKey.OP_WRITE;
@@ -1066,6 +1074,28 @@ class DatagramChannelImpl
return translateReadyOps(ops, 0, sk);
}
+ // package-private
+ int poll(int events, long timeout) throws IOException {
+ assert Thread.holdsLock(blockingLock()) && !isBlocking();
+
+ synchronized (readLock) {
+ int n = 0;
+ try {
+ begin();
+ synchronized (stateLock) {
+ if (!isOpen())
+ return 0;
+ readerThread = NativeThread.current();
+ }
+ n = Net.poll(fd, events, timeout);
+ } finally {
+ readerThread = 0;
+ end(n > 0);
+ }
+ return n;
+ }
+ }
+
/**
* Translates an interest operation set into a native poll event set
*/
@@ -1073,11 +1103,11 @@ class DatagramChannelImpl
int newOps = 0;
if ((ops & SelectionKey.OP_READ) != 0)
- newOps |= PollArrayWrapper.POLLIN;
+ newOps |= Net.POLLIN;
if ((ops & SelectionKey.OP_WRITE) != 0)
- newOps |= PollArrayWrapper.POLLOUT;
+ newOps |= Net.POLLOUT;
if ((ops & SelectionKey.OP_CONNECT) != 0)
- newOps |= PollArrayWrapper.POLLIN;
+ newOps |= Net.POLLIN;
sk.selector.putEventOps(sk, newOps);
}
@@ -1106,7 +1136,7 @@ class DatagramChannelImpl
throws IOException;
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
diff --git a/openjdk/sun/nio/ch/DotNetSelectorImpl.java b/openjdk/sun/nio/ch/DotNetSelectorImpl.java
index 897cf9a1..5f20394b 100644
--- a/openjdk/sun/nio/ch/DotNetSelectorImpl.java
+++ b/openjdk/sun/nio/ch/DotNetSelectorImpl.java
@@ -165,9 +165,9 @@ final class DotNetSelectorImpl extends SelectorImpl
private int updateSelectedKeys(ArrayList read, ArrayList write, ArrayList error)
{
updateCount++;
- int keys = processFDSet(updateCount, read, PollArrayWrapper.POLLIN);
- keys += processFDSet(updateCount, write, PollArrayWrapper.POLLCONN | PollArrayWrapper.POLLOUT);
- keys += processFDSet(updateCount, error, PollArrayWrapper.POLLIN | PollArrayWrapper.POLLCONN | PollArrayWrapper.POLLOUT);
+ int keys = processFDSet(updateCount, read, Net.POLLIN);
+ keys += processFDSet(updateCount, write, Net.POLLCONN | Net.POLLOUT);
+ keys += processFDSet(updateCount, error, Net.POLLIN | Net.POLLCONN | Net.POLLOUT);
return keys;
}
diff --git a/openjdk/sun/nio/ch/FileChannelImpl.java b/openjdk/sun/nio/ch/FileChannelImpl.java
index 902509bd..e0b4f8ba 100644
--- a/openjdk/sun/nio/ch/FileChannelImpl.java
+++ b/openjdk/sun/nio/ch/FileChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -33,12 +33,21 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
-import java.nio.channels.*;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.FileLockInterruptionException;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.security.AccessController;
import java.util.ArrayList;
import java.util.List;
-import java.security.AccessController;
+
import sun.misc.Cleaner;
-import sun.misc.IoTrace;
import sun.security.action.GetPropertyAction;
public class FileChannelImpl
@@ -63,7 +72,8 @@ public class FileChannelImpl
// Required to prevent finalization of creating stream (immutable)
private final Object parent;
- // The path of the referenced file (null if the parent stream is created with a file descriptor)
+ // The path of the referenced file
+ // (null if the parent stream is created with a file descriptor)
private final String path;
// Thread-safe set of IDs of native threads, for signalling
@@ -121,7 +131,7 @@ public class FileChannelImpl
}
}
- nd.preClose(fd);
+ // signal any threads blocked on this channel
threads.signalAndWait();
if (parent != null) {
@@ -145,19 +155,17 @@ public class FileChannelImpl
synchronized (positionLock) {
int n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileReadBegin(path);
try {
begin();
ti = threads.add();
if (!isOpen())
return 0;
do {
- n = IOUtil.read(fd, dst, -1, nd, positionLock);
+ n = IOUtil.read(fd, dst, -1, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
- IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
end(n > 0);
assert IOStatus.check(n);
}
@@ -175,7 +183,6 @@ public class FileChannelImpl
synchronized (positionLock) {
long n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileReadBegin(path);
try {
begin();
ti = threads.add();
@@ -187,7 +194,6 @@ public class FileChannelImpl
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
- IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
end(n > 0);
assert IOStatus.check(n);
}
@@ -201,20 +207,18 @@ public class FileChannelImpl
synchronized (positionLock) {
int n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileWriteBegin(path);
try {
begin();
ti = threads.add();
if (!isOpen())
return 0;
do {
- n = IOUtil.write(fd, src, -1, nd, positionLock);
+ n = IOUtil.write(fd, src, -1, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
end(n > 0);
- IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
assert IOStatus.check(n);
}
}
@@ -231,7 +235,6 @@ public class FileChannelImpl
synchronized (positionLock) {
long n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileWriteBegin(path);
try {
begin();
ti = threads.add();
@@ -243,7 +246,6 @@ public class FileChannelImpl
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
- IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
end(n > 0);
assert IOStatus.check(n);
}
@@ -321,12 +323,10 @@ public class FileChannelImpl
}
}
- public FileChannel truncate(long size) throws IOException {
+ public FileChannel truncate(long newSize) throws IOException {
ensureOpen();
- if (size < 0)
- throw new IllegalArgumentException();
- if (size > size())
- return this;
+ if (newSize < 0)
+ throw new IllegalArgumentException("Negative size");
if (!writable)
throw new NonWritableChannelException();
synchronized (positionLock) {
@@ -339,6 +339,14 @@ public class FileChannelImpl
if (!isOpen())
return null;
+ // get current size
+ long size;
+ do {
+ size = nd.size(fd);
+ } while ((size == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+
// get current position
do {
p = position0(fd, -1);
@@ -347,20 +355,22 @@ public class FileChannelImpl
return null;
assert p >= 0;
- // truncate file
- do {
- rv = nd.truncate(fd, size);
- } while ((rv == IOStatus.INTERRUPTED) && isOpen());
- if (!isOpen())
- return null;
+ // truncate file if given size is less than the current size
+ if (newSize < size) {
+ do {
+ rv = nd.truncate(fd, newSize);
+ } while ((rv == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+ }
// [IKVM] in append mode we're not allowed to seek backwards, but the atomic append will honor the new file size
if (append)
return this;
- // set position to size if greater than size
- if (p > size)
- p = size;
+ // if position is beyond new size then adjust it
+ if (p > newSize)
+ p = newSize;
do {
rv = (int)position0(fd, p);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
@@ -522,21 +532,30 @@ public class FileChannelImpl
if (!readable)
throw new NonReadableChannelException();
ensureOpen();
+ if (nd.needsPositionLock()) {
+ synchronized (positionLock) {
+ return readInternal(dst, position);
+ }
+ } else {
+ return readInternal(dst, position);
+ }
+ }
+
+ private int readInternal(ByteBuffer dst, long position) throws IOException {
+ assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
int n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileReadBegin(path);
try {
begin();
ti = threads.add();
if (!isOpen())
return -1;
do {
- n = IOUtil.read(fd, dst, position, nd, positionLock);
+ n = IOUtil.read(fd, dst, position, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
- IoTrace.fileReadEnd(traceContext, n > 0 ? n : 0);
end(n > 0);
assert IOStatus.check(n);
}
@@ -550,22 +569,31 @@ public class FileChannelImpl
if (!writable)
throw new NonWritableChannelException();
ensureOpen();
+ if (nd.needsPositionLock()) {
+ synchronized (positionLock) {
+ return writeInternal(src, position);
+ }
+ } else {
+ return writeInternal(src, position);
+ }
+ }
+
+ private int writeInternal(ByteBuffer src, long position) throws IOException {
+ assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
int n = 0;
int ti = -1;
- Object traceContext = IoTrace.fileWriteBegin(path);
try {
begin();
ti = threads.add();
if (!isOpen())
return -1;
do {
- n = IOUtil.write(fd, src, position, nd, positionLock);
+ n = IOUtil.write(fd, src, position, nd);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
end(n > 0);
- IoTrace.fileWriteEnd(traceContext, n > 0 ? n : 0);
assert IOStatus.check(n);
}
}
@@ -642,6 +670,8 @@ public class FileChannelImpl
throws IOException
{
ensureOpen();
+ if (mode == null)
+ throw new NullPointerException("Mode is null");
if (position < 0L)
throw new IllegalArgumentException("Negative position");
if (size < 0L)
@@ -650,6 +680,7 @@ public class FileChannelImpl
throw new IllegalArgumentException("Position + size overflow");
if (size > Integer.MAX_VALUE)
throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
+
int imode = -1;
if (mode == MapMode.READ_ONLY)
imode = MAP_RO;
@@ -670,7 +701,15 @@ public class FileChannelImpl
ti = threads.add();
if (!isOpen())
return null;
- if (size() < position + size) { // Extend file size
+
+ long filesize;
+ do {
+ filesize = nd.size(fd);
+ } while ((filesize == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
+
+ if (filesize < position + size) { // Extend file size
if (!writable) {
throw new IOException("Channel not open for writing " +
"- cannot extend file to required size");
@@ -679,6 +718,8 @@ public class FileChannelImpl
do {
rv = nd.truncate(fd, position + size);
} while ((rv == IOStatus.INTERRUPTED) && isOpen());
+ if (!isOpen())
+ return null;
}
if (size == 0) {
addr = 0;
diff --git a/openjdk/sun/nio/ch/Net.java b/openjdk/sun/nio/ch/Net.java
index d9ab0f0f..edf52a68 100644
--- a/openjdk/sun/nio/ch/Net.java
+++ b/openjdk/sun/nio/ch/Net.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -27,14 +27,16 @@ package sun.nio.ch;
import java.io.*;
import java.net.*;
+import jdk.net.*;
import java.nio.channels.*;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
+import sun.net.ExtendedOptionsImpl;
-class Net { // package-private
+public class Net {
private Net() { }
@@ -45,12 +47,6 @@ class Net { // package-private
}
};
- // Value of jdk.net.revealLocalAddress
- private static boolean revealLocalAddress;
-
- // True if jdk.net.revealLocalAddress had been read
- private static volatile boolean propRevealLocalAddress;
-
// set to true if exclusive binding is on for Windows
private static final boolean exclusiveBind;
@@ -59,8 +55,8 @@ class Net { // package-private
if (availLevel >= 0) {
String exclBindProp =
java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
+ new PrivilegedAction<String>() {
+ @Override
public String run() {
return System.getProperty(
"sun.net.useExclusiveBind");
@@ -117,7 +113,7 @@ class Net { // package-private
return canJoin6WithIPv4Group0();
}
- static InetSocketAddress checkAddress(SocketAddress sa) {
+ public static InetSocketAddress checkAddress(SocketAddress sa) {
if (sa == null)
throw new NullPointerException();
if (!(sa instanceof InetSocketAddress))
@@ -197,43 +193,19 @@ class Net { // package-private
if (addr == null || sm == null)
return addr;
- if (!getRevealLocalAddress()) {
+ try{
+ sm.checkConnect(addr.getAddress().getHostAddress(), -1);
+ // Security check passed
+ } catch (SecurityException e) {
// Return loopback address only if security check fails
- try{
- sm.checkConnect(addr.getAddress().getHostAddress(), -1);
- //Security check passed
- } catch (SecurityException e) {
- //Return loopback address
- addr = getLoopbackAddress(addr.getPort());
- }
+ addr = getLoopbackAddress(addr.getPort());
}
return addr;
}
static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
- if (!getRevealLocalAddress() && System.getSecurityManager() != null)
- addr = getLoopbackAddress(addr.getPort());
- return addr.toString();
- }
-
- private static boolean getRevealLocalAddress() {
- if (!propRevealLocalAddress) {
- try {
- revealLocalAddress = Boolean.parseBoolean(
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<String>() {
- public String run() {
- return System.getProperty(
- "jdk.net.revealLocalAddress");
- }
- }));
-
- } catch (Exception e) {
- // revealLocalAddress is false
- }
- propRevealLocalAddress = true;
- }
- return revealLocalAddress;
+ return System.getSecurityManager() == null ? addr.toString() :
+ getLoopbackAddress(addr.getPort()).toString();
}
private static InetSocketAddress getLoopbackAddress(int port) {
@@ -327,6 +299,16 @@ class Net { // package-private
// only simple values supported by this method
Class<?> type = name.type();
+
+ if (type == SocketFlow.class) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
+ }
+ ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
+ return;
+ }
+
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
@@ -370,7 +352,8 @@ class Net { // package-private
}
boolean mayNeedConversion = (family == UNSPEC);
- setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg);
+ boolean isIPv6 = (family == StandardProtocolFamily.INET6);
+ setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
}
static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
@@ -379,6 +362,16 @@ class Net { // package-private
{
Class<?> type = name.type();
+ if (type == SocketFlow.class) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
+ }
+ SocketFlow flow = SocketFlow.create();
+ ExtendedOptionsImpl.getFlowOption(fd, flow);
+ return flow;
+ }
+
// only simple values supported by this method
if (type != Integer.class && type != Boolean.class)
throw new AssertionError("Should not reach here");
@@ -430,7 +423,7 @@ class Net { // package-private
// Due to oddities SO_REUSEADDR on windows reuse is ignored
private static native FileDescriptor socket0(boolean preferIPv6, boolean stream, boolean reuse);
- static void bind(FileDescriptor fd, InetAddress addr, int port)
+ public static void bind(FileDescriptor fd, InetAddress addr, int port)
throws IOException
{
bind(UNSPEC, fd, addr, port);
@@ -484,7 +477,7 @@ class Net { // package-private
private static native InetAddress localInetAddress(FileDescriptor fd)
throws IOException;
- static InetSocketAddress localAddress(FileDescriptor fd)
+ public static InetSocketAddress localAddress(FileDescriptor fd)
throws IOException
{
return new InetSocketAddress(localInetAddress(fd), localPort(fd));
@@ -507,7 +500,10 @@ class Net { // package-private
throws IOException;
private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
- int level, int opt, int arg)
+ int level, int opt, int arg, boolean isIPv6)
+ throws IOException;
+
+ static native int poll(FileDescriptor fd, int events, long timeout)
throws IOException;
// -- Multicast support --
@@ -606,4 +602,15 @@ class Net { // package-private
static native int getInterface6(FileDescriptor fd) throws IOException;
+ /**
+ * Event masks for the various poll system calls.
+ * They will be set platform dependant in the static initializer below.
+ */
+ public static final short POLLIN = 0x0001;
+ public static final short POLLCONN = 0x0002;
+ public static final short POLLOUT = 0x0004;
+ public static final short POLLERR = 0x0008;
+ public static final short POLLHUP = 0x0010;
+ public static final short POLLNVAL = 0x0020;
+ public static final short POLLREMOVE = 0x0800;
}
diff --git a/openjdk/sun/nio/ch/PollArrayWrapper.java b/openjdk/sun/nio/ch/PollArrayWrapper.java
deleted file mode 100644
index 72ed9adc..00000000
--- a/openjdk/sun/nio/ch/PollArrayWrapper.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2001, 2002, 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.nio.ch;
-
-class PollArrayWrapper
-{
- static final short POLLIN = 0x0001;
- static final short POLLCONN = 0x0002;
- static final short POLLOUT = 0x0004;
- static final short POLLERR = 0x0008;
- static final short POLLHUP = 0x0010;
- static final short POLLNVAL = 0x0020;
- static final short POLLREMOVE = 0x0800;
-}
diff --git a/openjdk/sun/nio/ch/SocketOptionRegistry.java b/openjdk/sun/nio/ch/SocketOptionRegistry.java
index 83887fbc..f8e33066 100644
--- a/openjdk/sun/nio/ch/SocketOptionRegistry.java
+++ b/openjdk/sun/nio/ch/SocketOptionRegistry.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -24,7 +24,7 @@
* questions.
*
*/
-
+// AUTOMATICALLY GENERATED FILE - DO NOT EDIT
package sun.nio.ch;
import java.net.SocketOption;
import java.net.StandardSocketOptions;
@@ -34,7 +34,6 @@ import java.util.Map;
import java.util.HashMap;
import cli.System.Net.Sockets.SocketOptionLevel;
import cli.System.Net.Sockets.SocketOptionName;
-
class SocketOptionRegistry {
private SocketOptionRegistry() { }
private static class RegistryKey {
@@ -72,6 +71,7 @@ class SocketOptionRegistry {
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastInterface));
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET), new OptionKey(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback));
+ map.put(new RegistryKey(StandardSocketOptions.IP_TOS, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, ikvm.internal.Winsock.IPV6_TCLASS));
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_IF, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastInterface));
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_TTL, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.IpTimeToLive));
map.put(new RegistryKey(StandardSocketOptions.IP_MULTICAST_LOOP, StandardProtocolFamily.INET6), new OptionKey(SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback));
diff --git a/openjdk/sun/nio/fs/NetFileSystemProvider.java b/openjdk/sun/nio/fs/NetFileSystemProvider.java
index 1f112199..999c1231 100644
--- a/openjdk/sun/nio/fs/NetFileSystemProvider.java
+++ b/openjdk/sun/nio/fs/NetFileSystemProvider.java
@@ -338,7 +338,7 @@ final class NetFileSystemProvider extends AbstractFileSystemProvider
}
}
- return FileChannelImpl.open(open(npath.path, mode, rights, share, options), read, write, append, null);
+ return FileChannelImpl.open(open(npath.path, mode, rights, share, options), npath.path, read, write, append, null);
}
private static FileDescriptor open(String path, int mode, int rights, int share, int options) throws IOException
diff --git a/openjdk/sun/reflect/Reflection.java b/openjdk/sun/reflect/Reflection.java
index 6cff5746..2df2e2d4 100644
--- a/openjdk/sun/reflect/Reflection.java
+++ b/openjdk/sun/reflect/Reflection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -34,7 +34,6 @@
package sun.reflect;
import java.lang.reflect.*;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -47,17 +46,18 @@ public class Reflection {
view, where they are sensitive or they may contain VM-internal objects.
These Maps are updated very rarely. Rather than synchronize on
each access, we use copy-on-write */
- private static volatile Map<Class,String[]> fieldFilterMap;
- private static volatile Map<Class,String[]> methodFilterMap;
+ private static volatile Map<Class<?>,String[]> fieldFilterMap;
+ private static volatile Map<Class<?>,String[]> methodFilterMap;
static {
- Map<Class,String[]> map = new HashMap<Class,String[]>();
+ Map<Class<?>,String[]> map = new HashMap<Class<?>,String[]>();
map.put(Reflection.class,
new String[] {"fieldFilterMap", "methodFilterMap"});
map.put(System.class, new String[] {"security"});
+ map.put(Class.class, new String[] {"classLoader"});
fieldFilterMap = map;
- methodFilterMap = new HashMap<Class,String[]>();
+ methodFilterMap = new HashMap<>();
// [IKVM] to avoid initialization order issues, we actually add
// Unsafe.getUnsafe() here, instead of in Unsafe's class initializer
methodFilterMap.put(sun.misc.Unsafe.class, new String[] {"getUnsafe"});
@@ -67,21 +67,15 @@ public class Reflection {
ignoring frames associated with java.lang.reflect.Method.invoke()
and its implementation. */
@CallerSensitive
- public static Class getCallerClass() {
- return getCallerClass(2);
- }
+ public static native Class<?> getCallerClass();
- /** Returns the class of the method <code>realFramesToSkip</code>
- frames up the stack (zero-based), ignoring frames associated
- with java.lang.reflect.Method.invoke() and its implementation.
- The first frame is that associated with this method, so
- <code>getCallerClass(0)</code> returns the Class object for
- sun.reflect.Reflection. Frames associated with
- java.lang.reflect.Method.invoke() and its implementation are
- completely ignored and do not count toward the number of "real"
- frames skipped. */
- @CallerSensitive
- public static native Class getCallerClass(int realFramesToSkip);
+ /**
+ * @deprecated This method will be removed in JDK 9.
+ * This method is a private JDK API and retained temporarily for
+ * existing code to run until a replacement API is defined.
+ */
+ @Deprecated
+ public static native Class<?> getCallerClass(int depth);
/** Retrieves the access flags written to the class file. For
inner classes these flags may differ from those returned by
@@ -91,18 +85,18 @@ public class Reflection {
to compatibility reasons; see 4471811. Only the values of the
low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
valid. */
- private static native int getClassAccessFlags(Class c);
+ public static native int getClassAccessFlags(Class<?> c);
/** A quick "fast-path" check to try to avoid getCallerClass()
calls. */
- public static boolean quickCheckMemberAccess(Class memberClass,
+ public static boolean quickCheckMemberAccess(Class<?> memberClass,
int modifiers)
{
return Modifier.isPublic(getClassAccessFlags(memberClass) & modifiers);
}
- public static void ensureMemberAccess(Class currentClass,
- Class memberClass,
+ public static void ensureMemberAccess(Class<?> currentClass,
+ Class<?> memberClass,
Object target,
int modifiers)
throws IllegalAccessException
@@ -124,13 +118,13 @@ public class Reflection {
/*IKVM*/
private static native boolean checkInternalAccess(Class currentClass, Class memberClass);
- public static boolean verifyMemberAccess(Class currentClass,
+ public static boolean verifyMemberAccess(Class<?> currentClass,
// Declaring class of field
// or method
- Class memberClass,
+ Class<?> memberClass,
// May be NULL in case of statics
- Object target,
- int modifiers)
+ Object target,
+ int modifiers)
{
// Verify that currentClass can access a field, method, or
// constructor of memberClass, where that member's access bits are
@@ -192,7 +186,7 @@ public class Reflection {
if (Modifier.isProtected(modifiers)) {
// Additional test for protected members: JLS 6.6.2
- Class targetClass = (target == null ? memberClass : target.getClass());
+ Class<?> targetClass = (target == null ? memberClass : target.getClass());
if (targetClass != currentClass) {
if (!gotIsSameClassPackage) {
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
@@ -209,7 +203,7 @@ public class Reflection {
return true;
}
- private static boolean isSameClassPackage(Class c1, Class c2) {
+ private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
return isSameClassPackage(c1.getClassLoader(), c1.getName(),
c2.getClassLoader(), c2.getName());
}
@@ -264,8 +258,8 @@ public class Reflection {
}
}
- static boolean isSubclassOf(Class queryClass,
- Class ofClass)
+ static boolean isSubclassOf(Class<?> queryClass,
+ Class<?> ofClass)
{
while (queryClass != null) {
if (queryClass == ofClass) {
@@ -277,31 +271,31 @@ public class Reflection {
}
// fieldNames must contain only interned Strings
- public static synchronized void registerFieldsToFilter(Class containingClass,
+ public static synchronized void registerFieldsToFilter(Class<?> containingClass,
String ... fieldNames) {
fieldFilterMap =
registerFilter(fieldFilterMap, containingClass, fieldNames);
}
// methodNames must contain only interned Strings
- public static synchronized void registerMethodsToFilter(Class containingClass,
+ public static synchronized void registerMethodsToFilter(Class<?> containingClass,
String ... methodNames) {
methodFilterMap =
registerFilter(methodFilterMap, containingClass, methodNames);
}
- private static Map<Class,String[]> registerFilter(Map<Class,String[]> map,
- Class containingClass, String ... names) {
+ private static Map<Class<?>,String[]> registerFilter(Map<Class<?>,String[]> map,
+ Class<?> containingClass, String ... names) {
if (map.get(containingClass) != null) {
throw new IllegalArgumentException
("Filter already registered: " + containingClass);
}
- map = new HashMap<Class,String[]>(map);
+ map = new HashMap<Class<?>,String[]>(map);
map.put(containingClass, names);
return map;
}
- public static Field[] filterFields(Class containingClass,
+ public static Field[] filterFields(Class<?> containingClass,
Field[] fields) {
if (fieldFilterMap == null) {
// Bootstrapping
@@ -310,7 +304,7 @@ public class Reflection {
return (Field[])filter(fields, fieldFilterMap.get(containingClass));
}
- public static Method[] filterMethods(Class containingClass, Method[] methods) {
+ public static Method[] filterMethods(Class<?> containingClass, Method[] methods) {
if (methodFilterMap == null) {
// Bootstrapping
return methods;
@@ -352,4 +346,27 @@ public class Reflection {
}
return newMembers;
}
+
+ /**
+ * Tests if the given method is caller-sensitive and the declaring class
+ * is defined by either the bootstrap class loader or extension class loader.
+ */
+ public static boolean isCallerSensitive(Method m) {
+ final ClassLoader loader = m.getDeclaringClass().getClassLoader();
+ if (sun.misc.VM.isSystemDomainLoader(loader) || isExtClassLoader(loader)) {
+ return m.isAnnotationPresent(CallerSensitive.class);
+ }
+ return false;
+ }
+
+ private static boolean isExtClassLoader(ClassLoader loader) {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ while (cl != null) {
+ if (cl.getParent() == null && cl == loader) {
+ return true;
+ }
+ cl = cl.getParent();
+ }
+ return false;
+ }
}
diff --git a/openjdk/sun/reflect/ReflectionFactory.java b/openjdk/sun/reflect/ReflectionFactory.java
index 5a3a848e..35cae84c 100644
--- a/openjdk/sun/reflect/ReflectionFactory.java
+++ b/openjdk/sun/reflect/ReflectionFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -32,12 +32,14 @@
package sun.reflect;
import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
+import sun.reflect.misc.ReflectUtil;
/** <P> The master factory for all reflective objects, both those in
java.lang.reflect (Fields, Methods, Constructors) as well as their
@@ -53,9 +55,9 @@ import java.security.PrivilegedAction;
public class ReflectionFactory {
- private static Permission reflectionFactoryAccessPerm
+ private static final Permission reflectionFactoryAccessPerm
= new RuntimePermission("reflectionFactoryAccess");
- private static ReflectionFactory soleInstance = new ReflectionFactory();
+ private static final ReflectionFactory soleInstance = new ReflectionFactory();
// Provides access to package-private mechanisms in java.lang.reflect
private static volatile LangReflectAccess langReflectAccess;
@@ -129,7 +131,7 @@ public class ReflectionFactory {
private native ConstructorAccessor newConstructorAccessor0(Constructor c);
- public ConstructorAccessor newConstructorAccessor(Constructor c) {
+ public ConstructorAccessor newConstructorAccessor(Constructor<?> c) {
Class<?> declaringClass = c.getDeclaringClass();
if (Modifier.isAbstract(declaringClass.getModifiers())) {
return new InstantiationExceptionConstructorAccessorImpl(null);
@@ -195,14 +197,14 @@ public class ReflectionFactory {
/** Creates a new java.lang.reflect.Constructor. Access checks as
per java.lang.reflect.AccessibleObject are not overridden. */
- public Constructor newConstructor(Class<?> declaringClass,
- Class<?>[] parameterTypes,
- Class<?>[] checkedExceptions,
- int modifiers,
- int slot,
- String signature,
- byte[] annotations,
- byte[] parameterAnnotations)
+ public Constructor<?> newConstructor(Class<?> declaringClass,
+ Class<?>[] parameterTypes,
+ Class<?>[] checkedExceptions,
+ int modifiers,
+ int slot,
+ String signature,
+ byte[] annotations,
+ byte[] parameterAnnotations)
{
return langReflectAccess().newConstructor(declaringClass,
parameterTypes,
@@ -226,13 +228,13 @@ public class ReflectionFactory {
/** Gets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
- public ConstructorAccessor getConstructorAccessor(Constructor c) {
+ public ConstructorAccessor getConstructorAccessor(Constructor<?> c) {
return langReflectAccess().getConstructorAccessor(c);
}
/** Sets the ConstructorAccessor object for a
java.lang.reflect.Constructor */
- public void setConstructorAccessor(Constructor c,
+ public void setConstructorAccessor(Constructor<?> c,
ConstructorAccessor accessor)
{
langReflectAccess().setConstructorAccessor(c, accessor);
@@ -259,6 +261,12 @@ public class ReflectionFactory {
return langReflectAccess().copyConstructor(arg);
}
+ /** Gets the byte[] that encodes TypeAnnotations on an executable.
+ */
+ public byte[] getExecutableTypeAnnotationBytes(Executable ex) {
+ return langReflectAccess().getExecutableTypeAnnotationBytes(ex);
+ }
+
//--------------------------------------------------------------------------
//
// Routines used by serialization
@@ -267,8 +275,8 @@ public class ReflectionFactory {
private static native ConstructorAccessor newConstructorAccessorForSerialization(Class classToInstantiate, Constructor constructorToCall);
- public Constructor newConstructorForSerialization
- (Class<?> classToInstantiate, Constructor constructorToCall)
+ public Constructor<?> newConstructorForSerialization
+ (Class<?> classToInstantiate, Constructor<?> constructorToCall)
{
// Fast path
if (constructorToCall.getDeclaringClass() == classToInstantiate) {
@@ -276,18 +284,18 @@ public class ReflectionFactory {
}
ConstructorAccessor acc = newConstructorAccessorForSerialization(classToInstantiate, constructorToCall);
- Constructor c = newConstructor(constructorToCall.getDeclaringClass(),
- constructorToCall.getParameterTypes(),
- constructorToCall.getExceptionTypes(),
- constructorToCall.getModifiers(),
- langReflectAccess().
- getConstructorSlot(constructorToCall),
- langReflectAccess().
- getConstructorSignature(constructorToCall),
- langReflectAccess().
- getConstructorAnnotations(constructorToCall),
- langReflectAccess().
- getConstructorParameterAnnotations(constructorToCall));
+ Constructor<?> c = newConstructor(constructorToCall.getDeclaringClass(),
+ constructorToCall.getParameterTypes(),
+ constructorToCall.getExceptionTypes(),
+ constructorToCall.getModifiers(),
+ langReflectAccess().
+ getConstructorSlot(constructorToCall),
+ langReflectAccess().
+ getConstructorSignature(constructorToCall),
+ langReflectAccess().
+ getConstructorAnnotations(constructorToCall),
+ langReflectAccess().
+ getConstructorParameterAnnotations(constructorToCall));
setConstructorAccessor(c, acc);
return c;
}
diff --git a/runtime/openjdk/java.lang.cs b/runtime/openjdk/java.lang.cs
index 4cb85bed..95bd78f9 100644
--- a/runtime/openjdk/java.lang.cs
+++ b/runtime/openjdk/java.lang.cs
@@ -34,7 +34,7 @@ using IKVM.Internal;
static class Java_java_lang_Class
{
- public static java.lang.Class forName0(string name, bool initialize, java.lang.ClassLoader loader)
+ public static java.lang.Class forName0(string name, bool initialize, java.lang.ClassLoader loader, java.lang.Class caller)
{
#if FIRST_PASS
return null;
@@ -80,6 +80,11 @@ static class Java_java_lang_Class
throw x.ToJava();
}
}
+ java.security.ProtectionDomain pd;
+ if (loader != null && caller != null && (pd = getProtectionDomain0(caller)) != null)
+ {
+ loader.checkPackageAccess(tw.ClassObject, pd);
+ }
if (initialize && !tw.IsArray)
{
try
diff --git a/runtime/openjdk/java.lang.invoke.cs b/runtime/openjdk/java.lang.invoke.cs
index e038a809..80fc0a9b 100644
--- a/runtime/openjdk/java.lang.invoke.cs
+++ b/runtime/openjdk/java.lang.invoke.cs
@@ -78,6 +78,14 @@ static class Java_java_lang_invoke_MethodHandle
static class Java_java_lang_invoke_MethodHandleNatives
{
+ // called from map.xml as a replacement for Class.isInstance() in java.lang.invoke.MethodHandleImpl.castReference()
+ public static bool Class_isInstance(java.lang.Class clazz, object obj)
+ {
+ TypeWrapper tw = TypeWrapper.FromClass(clazz);
+ // handle the type system hole that is caused by arrays being both derived from cli.System.Array and directly from java.lang.Object
+ return tw.IsInstance(obj) || (tw == CoreClasses.cli.System.Object.Wrapper && obj is Array);
+ }
+
// called from Lookup.revealDirect() (instead of MethodHandle.internalMemberName()) via map.xml replace-method-call
public static MemberName internalMemberName(MethodHandle mh)
{
diff --git a/runtime/openjdk/java.net.cs b/runtime/openjdk/java.net.cs
index f84cbf81..b5626d79 100644
--- a/runtime/openjdk/java.net.cs
+++ b/runtime/openjdk/java.net.cs
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2007-2013 Jeroen Frijters
+ Copyright (C) 2007-2015 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -28,6 +28,36 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Security;
+static class Java_java_net_AbstractPlainDatagramSocketImpl
+{
+ public static void init()
+ {
+ }
+
+ public static int dataAvailable(object _this)
+ {
+#if FIRST_PASS
+ return 0;
+#else
+ try
+ {
+ java.net.AbstractPlainDatagramSocketImpl obj = (java.net.AbstractPlainDatagramSocketImpl)_this;
+ if (obj.fd != null)
+ {
+ return obj.fd.getSocket().Available;
+ }
+ }
+ catch (ObjectDisposedException)
+ {
+ }
+ catch (SocketException)
+ {
+ }
+ throw new java.net.SocketException("Socket closed");
+#endif
+ }
+}
+
static class Java_java_net_DatagramPacket
{
public static void init()
diff --git a/runtime/openjdk/java.util.cs b/runtime/openjdk/java.util.cs
new file mode 100644
index 00000000..c0d3b82e
--- /dev/null
+++ b/runtime/openjdk/java.util.cs
@@ -0,0 +1,339 @@
+/*
+ Copyright (C) 2007-2013 Jeroen Frijters
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jeroen Frijters
+ jeroen@frijters.net
+
+*/
+using System;
+
+static class Java_java_util_TimeZone
+{
+ private static string GetCurrentTimeZoneID()
+ {
+#if NET_4_0
+ return TimeZoneInfo.Local.Id;
+#else
+ // we don't want a static dependency on System.Core (to be able to run on .NET 2.0)
+ Type typeofTimeZoneInfo = Type.GetType("System.TimeZoneInfo, System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
+ if (typeofTimeZoneInfo != null)
+ {
+ try
+ {
+ return (string)typeofTimeZoneInfo.GetProperty("Id").GetValue(typeofTimeZoneInfo.GetProperty("Local").GetValue(null, null), null);
+ }
+ catch (Exception x)
+ {
+ // older Mono versions did not wrap the exception in a TargetInvocationExcception,
+ // so we check both x and x.InnerException
+ if (typeofTimeZoneInfo.Assembly.GetType("System.TimeZoneNotFoundException").IsInstanceOfType(x)
+ || typeofTimeZoneInfo.Assembly.GetType("System.TimeZoneNotFoundException").IsInstanceOfType(x.InnerException))
+ {
+ // MONOBUG Mono's TimeZoneInfo.Local property throws a TimeZoneNotFoundException on Windows
+ // (https://bugzilla.novell.com/show_bug.cgi?id=622524)
+ return TimeZone.CurrentTimeZone.StandardName;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+ else
+ {
+ // HACK this is very lame and probably won't work on localized windows versions
+ return TimeZone.CurrentTimeZone.StandardName;
+ }
+#endif
+ }
+
+ public static string getSystemTimeZoneID(string javaHome)
+ {
+ // (the switch was generated from the contents of $JAVA_HOME/lib/tzmappings)
+ switch (GetCurrentTimeZoneID())
+ {
+ case "Romance":
+ case "Romance Standard Time":
+ return "Europe/Paris";
+ case "Warsaw":
+ return "Europe/Warsaw";
+ case "Central Europe":
+ case "Central Europe Standard Time":
+ case "Prague Bratislava":
+ return "Europe/Prague";
+ case "W. Central Africa Standard Time":
+ return "Africa/Luanda";
+ case "FLE":
+ case "FLE Standard Time":
+ return "Europe/Helsinki";
+ case "GFT":
+ case "GFT Standard Time":
+ case "GTB":
+ case "GTB Standard Time":
+ return "Europe/Athens";
+ case "Israel":
+ case "Israel Standard Time":
+ return "Asia/Jerusalem";
+ case "Arab":
+ case "Arab Standard Time":
+ return "Asia/Riyadh";
+ case "Arabic Standard Time":
+ return "Asia/Baghdad";
+ case "E. Africa":
+ case "E. Africa Standard Time":
+ return "Africa/Nairobi";
+ case "Saudi Arabia":
+ case "Saudi Arabia Standard Time":
+ return "Asia/Riyadh";
+ case "Iran":
+ case "Iran Standard Time":
+ return "Asia/Tehran";
+ case "Afghanistan":
+ case "Afghanistan Standard Time":
+ return "Asia/Kabul";
+ case "India":
+ case "India Standard Time":
+ return "Asia/Calcutta";
+ case "Myanmar Standard Time":
+ return "Asia/Rangoon";
+ case "Nepal Standard Time":
+ return "Asia/Katmandu";
+ case "Sri Lanka":
+ case "Sri Lanka Standard Time":
+ return "Asia/Colombo";
+ case "Beijing":
+ case "China":
+ case "China Standard Time":
+ return "Asia/Shanghai";
+ case "AUS Central":
+ case "AUS Central Standard Time":
+ return "Australia/Darwin";
+ case "Cen. Australia":
+ case "Cen. Australia Standard Time":
+ return "Australia/Adelaide";
+ case "Vladivostok":
+ case "Vladivostok Standard Time":
+ return "Asia/Vladivostok";
+ case "West Pacific":
+ case "West Pacific Standard Time":
+ return "Pacific/Guam";
+ case "E. South America":
+ case "E. South America Standard Time":
+ return "America/Sao_Paulo";
+ case "Greenland Standard Time":
+ return "America/Godthab";
+ case "Newfoundland":
+ case "Newfoundland Standard Time":
+ return "America/St_Johns";
+ case "Pacific SA":
+ case "Pacific SA Standard Time":
+ return "America/Santiago";
+ case "SA Western":
+ case "SA Western Standard Time":
+ return "America/Caracas";
+ case "SA Pacific":
+ case "SA Pacific Standard Time":
+ return "America/Bogota";
+ case "US Eastern":
+ case "US Eastern Standard Time":
+ return "America/Indianapolis";
+ case "Central America Standard Time":
+ return "America/Regina";
+ case "Mexico":
+ case "Mexico Standard Time":
+ return "America/Mexico_City";
+ case "Canada Central":
+ case "Canada Central Standard Time":
+ return "America/Regina";
+ case "US Mountain":
+ case "US Mountain Standard Time":
+ return "America/Phoenix";
+ case "GMT":
+ case "GMT Standard Time":
+ return "Europe/London";
+ case "Ekaterinburg":
+ case "Ekaterinburg Standard Time":
+ return "Asia/Yekaterinburg";
+ case "West Asia":
+ case "West Asia Standard Time":
+ return "Asia/Karachi";
+ case "Central Asia":
+ case "Central Asia Standard Time":
+ return "Asia/Dhaka";
+ case "N. Central Asia Standard Time":
+ return "Asia/Novosibirsk";
+ case "Bangkok":
+ case "Bangkok Standard Time":
+ return "Asia/Bangkok";
+ case "North Asia Standard Time":
+ return "Asia/Krasnoyarsk";
+ case "SE Asia":
+ case "SE Asia Standard Time":
+ return "Asia/Bangkok";
+ case "North Asia East Standard Time":
+ return "Asia/Ulaanbaatar";
+ case "Singapore":
+ case "Singapore Standard Time":
+ return "Asia/Singapore";
+ case "Taipei":
+ case "Taipei Standard Time":
+ return "Asia/Taipei";
+ case "W. Australia":
+ case "W. Australia Standard Time":
+ return "Australia/Perth";
+ case "Korea":
+ case "Korea Standard Time":
+ return "Asia/Seoul";
+ case "Tokyo":
+ case "Tokyo Standard Time":
+ return "Asia/Tokyo";
+ case "Yakutsk":
+ case "Yakutsk Standard Time":
+ return "Asia/Yakutsk";
+ case "Central European":
+ case "Central European Standard Time":
+ return "Europe/Belgrade";
+ case "W. Europe":
+ case "W. Europe Standard Time":
+ return "Europe/Berlin";
+ case "Tasmania":
+ case "Tasmania Standard Time":
+ return "Australia/Hobart";
+ case "AUS Eastern":
+ case "AUS Eastern Standard Time":
+ return "Australia/Sydney";
+ case "E. Australia":
+ case "E. Australia Standard Time":
+ return "Australia/Brisbane";
+ case "Sydney Standard Time":
+ return "Australia/Sydney";
+ case "Central Pacific":
+ case "Central Pacific Standard Time":
+ return "Pacific/Guadalcanal";
+ case "Dateline":
+ case "Dateline Standard Time":
+ return "GMT-1200";
+ case "Fiji":
+ case "Fiji Standard Time":
+ return "Pacific/Fiji";
+ case "Samoa":
+ case "Samoa Standard Time":
+ return "Pacific/Apia";
+ case "Hawaiian":
+ case "Hawaiian Standard Time":
+ return "Pacific/Honolulu";
+ case "Alaskan":
+ case "Alaskan Standard Time":
+ return "America/Anchorage";
+ case "Pacific":
+ case "Pacific Standard Time":
+ return "America/Los_Angeles";
+ case "Mexico Standard Time 2":
+ return "America/Chihuahua";
+ case "Mountain":
+ case "Mountain Standard Time":
+ return "America/Denver";
+ case "Central":
+ case "Central Standard Time":
+ return "America/Chicago";
+ case "Eastern":
+ case "Eastern Standard Time":
+ return "America/New_York";
+ case "E. Europe":
+ case "E. Europe Standard Time":
+ return "Europe/Minsk";
+ case "Egypt":
+ case "Egypt Standard Time":
+ return "Africa/Cairo";
+ case "South Africa":
+ case "South Africa Standard Time":
+ return "Africa/Harare";
+ case "Atlantic":
+ case "Atlantic Standard Time":
+ return "America/Halifax";
+ case "SA Eastern":
+ case "SA Eastern Standard Time":
+ return "America/Buenos_Aires";
+ case "Mid-Atlantic":
+ case "Mid-Atlantic Standard Time":
+ return "Atlantic/South_Georgia";
+ case "Azores":
+ case "Azores Standard Time":
+ return "Atlantic/Azores";
+ case "Cape Verde Standard Time":
+ return "Atlantic/Cape_Verde";
+ case "Russian":
+ case "Russian Standard Time":
+ return "Europe/Moscow";
+ case "New Zealand":
+ case "New Zealand Standard Time":
+ return "Pacific/Auckland";
+ case "Tonga Standard Time":
+ return "Pacific/Tongatapu";
+ case "Arabian":
+ case "Arabian Standard Time":
+ return "Asia/Muscat";
+ case "Caucasus":
+ case "Caucasus Standard Time":
+ return "Asia/Yerevan";
+ case "Greenwich":
+ case "Greenwich Standard Time":
+ return "GMT";
+ case "Central Brazilian Standard Time":
+ return "America/Manaus";
+ case "Central Standard Time (Mexico)":
+ return "America/Mexico_City";
+ case "Georgian Standard Time":
+ return "Asia/Tbilisi";
+ case "Mountain Standard Time (Mexico)":
+ return "America/Chihuahua";
+ case "Namibia Standard Time":
+ return "Africa/Windhoek";
+ case "Pacific Standard Time (Mexico)":
+ return "America/Tijuana";
+ case "Western Brazilian Standard Time":
+ return "America/Rio_Branco";
+ case "Azerbaijan Standard Time":
+ return "Asia/Baku";
+ case "Jordan Standard Time":
+ return "Asia/Amman";
+ case "Middle East Standard Time":
+ return "Asia/Beirut";
+ default:
+ // this means fall back to GMT offset
+ return getSystemGMTOffsetID();
+ }
+ }
+
+ public static string getSystemGMTOffsetID()
+ {
+ TimeSpan sp = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
+ int hours = sp.Hours;
+ int mins = sp.Minutes;
+ if (hours >= 0 && mins >= 0)
+ {
+ return String.Format("GMT+{0:D2}:{1:D2}", hours, mins);
+ }
+ else
+ {
+ return String.Format("GMT-{0:D2}:{1:D2}", -hours, -mins);
+ }
+ }
+}
+
diff --git a/runtime/openjdk/misc.cs b/runtime/openjdk/misc.cs
index 368c22de..dfba8338 100644
--- a/runtime/openjdk/misc.cs
+++ b/runtime/openjdk/misc.cs
@@ -197,17 +197,6 @@ static class Java_sun_invoke_anon_AnonymousClassLoader
}
}
-static class Java_sun_invoke_util_ValueConversions
-{
- // called from map.xml as a replacement for Class.isInstance() in sun.invoke.util.ValueConversions.castReference()
- public static bool Class_isInstance(java.lang.Class clazz, object obj)
- {
- TypeWrapper tw = TypeWrapper.FromClass(clazz);
- // handle the type system hole that is caused by arrays being both derived from cli.System.Array and directly from java.lang.Object
- return tw.IsInstance(obj) || (tw == CoreClasses.cli.System.Object.Wrapper && obj is Array);
- }
-}
-
static class Java_sun_invoke_util_VerifyAccess
{
// called from map.xml as a replacement for Class.getClassLoader() in sun.invoke.util.VerifyAccess.isTypeVisible()
@@ -547,6 +536,7 @@ static class Java_java_awt_SplashScreen
public static String _getImageFileName(long splashPtr) { return null; }
public static String _getImageJarName(long splashPtr) { return null; }
public static bool _setImageData(long splashPtr, byte[] data) { return false; }
+ public static float _getScaleFactor(long SplashPtr) { return 1; }
}
static class Java_java_awt_TextArea
@@ -618,3 +608,30 @@ static class Java_java_awt_image_SampleModel
{
public static void initIDs() { }
}
+
+static class Java_sun_net_ExtendedOptionsImpl
+{
+ public static void init()
+ {
+ }
+
+ public static void setFlowOption(java.io.FileDescriptor fd, object f)
+ {
+#if !FIRST_PASS
+ throw new java.lang.UnsupportedOperationException();
+#endif
+ }
+
+ public static void getFlowOption(java.io.FileDescriptor fd, object f)
+ {
+#if !FIRST_PASS
+ throw new java.lang.UnsupportedOperationException();
+#endif
+ }
+
+ public static bool flowSupported()
+ {
+ // We don't support this. Solaris only functionality.
+ return false;
+ }
+}
diff --git a/runtime/openjdk/sun.misc.cs b/runtime/openjdk/sun.misc.cs
index 446da7e7..45939f10 100644
--- a/runtime/openjdk/sun.misc.cs
+++ b/runtime/openjdk/sun.misc.cs
@@ -733,6 +733,24 @@ static class Java_sun_misc_Unsafe
}
}
+static class Java_sun_misc_URLClassPath
+{
+ public static java.net.URL[] getLookupCacheURLs(java.lang.ClassLoader loader)
+ {
+ return null;
+ }
+
+ public static int[] getLookupCacheForClassLoader(java.lang.ClassLoader loader, string name)
+ {
+ return null;
+ }
+
+ public static bool knownToNotExist0(java.lang.ClassLoader loader, string className)
+ {
+ return false;
+ }
+}
+
static class Java_sun_misc_Version
{
public static string getJvmSpecialVersion()
@@ -803,4 +821,9 @@ static class Java_sun_misc_VMSupport
{
return props;
}
+
+ public static string getVMTemporaryDirectory()
+ {
+ return System.IO.Path.GetTempPath();
+ }
}
diff --git a/runtime/openjdk/sun.nio.ch.cs b/runtime/openjdk/sun.nio.ch.cs
index 7b5258fa..06a63da4 100644
--- a/runtime/openjdk/sun.nio.ch.cs
+++ b/runtime/openjdk/sun.nio.ch.cs
@@ -646,6 +646,10 @@ namespace IKVM.NativeCode.sun.nio.ch
#if FIRST_PASS
return 0;
#else
+ if (level == global::ikvm.@internal.Winsock.IPPROTO_IPV6 && opt == global::ikvm.@internal.Winsock.IPV6_TCLASS)
+ {
+ return 0;
+ }
System.Net.Sockets.SocketOptionLevel sol = (System.Net.Sockets.SocketOptionLevel)level;
System.Net.Sockets.SocketOptionName son = (System.Net.Sockets.SocketOptionName)opt;
try
@@ -678,9 +682,13 @@ namespace IKVM.NativeCode.sun.nio.ch
#endif
}
- public static void setIntOption0(FileDescriptor fd, bool mayNeedConversion, int level, int opt, int arg)
+ public static void setIntOption0(FileDescriptor fd, bool mayNeedConversion, int level, int opt, int arg, bool isIPv6)
{
#if !FIRST_PASS
+ if (level == global::ikvm.@internal.Winsock.IPPROTO_IPV6 && opt == global::ikvm.@internal.Winsock.IPV6_TCLASS)
+ {
+ return;
+ }
System.Net.Sockets.SocketOptionLevel sol = (System.Net.Sockets.SocketOptionLevel)level;
System.Net.Sockets.SocketOptionName son = (System.Net.Sockets.SocketOptionName)opt;
if (mayNeedConversion)
@@ -998,8 +1006,7 @@ namespace IKVM.NativeCode.sun.nio.ch
{
if (useExclBind)
{
- // TODO enable this after we merge OpenJDK 7u40
- //global::java.net.net_util_md.setExclusiveBind(fd.getSocket());
+ global::java.net.net_util_md.setExclusiveBind(fd.getSocket());
}
fd.getSocket().Bind(new System.Net.IPEndPoint(global::java.net.SocketUtil.getAddressFromInetAddress(addr, preferIPv6), port));
}
@@ -1078,6 +1085,44 @@ namespace IKVM.NativeCode.sun.nio.ch
}
#endif
}
+
+ public static int poll(FileDescriptor fd, int events, long timeout)
+ {
+#if FIRST_PASS
+ return 0;
+#else
+ System.Net.Sockets.SelectMode selectMode;
+ switch (events)
+ {
+ case global::sun.nio.ch.Net.POLLCONN:
+ case global::sun.nio.ch.Net.POLLOUT:
+ selectMode = System.Net.Sockets.SelectMode.SelectWrite;
+ break;
+ case global::sun.nio.ch.Net.POLLIN:
+ selectMode = System.Net.Sockets.SelectMode.SelectRead;
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+ int microSeconds = timeout >= Int32.MaxValue / 1000 ? Int32.MaxValue : (int)(timeout * 1000);
+ try
+ {
+ if (fd.getSocket().Poll(microSeconds, selectMode))
+ {
+ return events;
+ }
+ }
+ catch (System.Net.Sockets.SocketException x)
+ {
+ throw new global::java.net.SocketException(x.Message);
+ }
+ catch (System.ObjectDisposedException)
+ {
+ throw new global::java.net.SocketException("Socket is closed");
+ }
+ return 0;
+#endif
+ }
}
static class ServerSocketChannelImpl