diff options
author | jfrijters <jfrijters> | 2015-06-09 12:28:37 +0300 |
---|---|---|
committer | jfrijters <jfrijters> | 2015-06-09 12:28:37 +0300 |
commit | be6daf30426500ed3c3188b9c2a7882b55176705 (patch) | |
tree | 710493db1ddeca45498846e6885d164a832d44c1 | |
parent | dab43d5cf4bf3b8b9a5b5f8cb175dee38a5fe69f (diff) |
Integrated OpenJDK 8u45.
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 <= b <= 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 << 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 <= b1, b2 <= 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 <= b1, b2 <= 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 <= b1, b2, b3, b4 <= 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 <= b1, b2, b3, b4, b5, b6, b7, b8 <=255, * </pre></blockquote> * <p> * then the result is equal to: - * <p><blockquote><pre> + * <blockquote><pre> * ((long)b1 << 56) + ((long)b2 << 48) * + ((long)b3 << 40) + ((long)b4 << 32) * + ((long)b5 << 24) + ((long)b6 << 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>'\r'</code>), a newline character (<code>'\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™ 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 ( + ), 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 < 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>) != 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> >= fromIndex) + * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> >= 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> >= fromIndex) + * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> >= 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> <= fromIndex) + * (this.charAt(<i>k</i>) == ch) {@code &&} (<i>k</i> <= 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> <= fromIndex) + * (this.codePointAt(<i>k</i>) == ch) {@code &&} (<i>k</i> <= 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> >= fromIndex && this.startsWith(str, <i>k</i>) + * <i>k</i> >= 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> <= 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> - 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> <i>n</i><tt>)</tt> + * <i>str.</i>{@code split(}<i>regex</i>{@code ,} <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> <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>, <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>'\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>'\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>'\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>'\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>, <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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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™ 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<?> 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<?>[] { 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 |