This commit is contained in:
Lev Serebryakov 2008-12-05 15:06:37 -05:00
commit 1d59997abe
155 changed files with 8361 additions and 2655 deletions

View File

@ -14,3 +14,4 @@ d718a441936196b93d8bc9f084933af9a4c2a350 jdk7-b36
c2036bf76829c03b99108fffab52e20910a9be4f jdk7-b37
a2879b2837f5a4c87e9542efe69ef138194af8ff jdk7-b38
126f365cec6c3c2c72de934fa1c64b5f082b55b5 jdk7-b39
3c53424bbe3bb77e01b468b4b0140deec33e11fc jdk7-b40

View File

@ -14,3 +14,4 @@ bb1ef4ee3d2c8cbf43a37d372325a7952be590b9 jdk7-b33
744554f5a3290e11c71cd2ddb1aff49e431f9ed0 jdk7-b37
cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39
44be42de6693063fb191989bf0e188de2fa51e7c jdk7-b40

View File

@ -98,7 +98,8 @@
<h2><a name="MBE">Minimum Build Environments</a></h2>
<blockquote>
This file often describes specific requirements for what we call the
"minimum build environments" (MBE) for the JDK.
"minimum build environments" (MBE) for this
specific release of the JDK,
Building with the MBE will generate the most compatible
bits that install on, and run correctly on, the most variations
of the same base OS and hardware architecture.
@ -116,22 +117,22 @@
<tr>
<th>Base OS and Architecture</th>
<th>OS</th>
<th>Compiler</th>
<th>C/C++ Compiler</th>
</tr>
</thead>
<tbody>
<tr>
<td>Linux X86 (32bit)</td>
<td>Red Hat Enterprise Linux 4 </td>
<td>Linux X86 (32-bit)</td>
<td>Fedora 9</td>
<td>gcc 4 </td>
</tr>
<tr>
<td>Linux X64 (64bit)</td>
<td>Red Hat Enterprise Linux 4 </td>
<td>Linux X64 (64-bit)</td>
<td>Fedora 9</td>
<td>gcc 4 </td>
</tr>
<tr>
<td>Solaris SPARC (32bit)</td>
<td>Solaris SPARC (32-bit)</td>
<td>Solaris 10 + patches
<br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
@ -140,7 +141,7 @@
<td>Sun Studio 12</td>
</tr>
<tr>
<td>Solaris SPARCV9 (64bit)</td>
<td>Solaris SPARCV9 (64-bit)</td>
<td>Solaris 10 + patches
<br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
@ -149,7 +150,7 @@
<td>Sun Studio 12</td>
</tr>
<tr>
<td>Solaris X86 (32bit)</td>
<td>Solaris X86 (32-bit)</td>
<td>Solaris 10 + patches
<br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
@ -158,7 +159,7 @@
<td>Sun Studio 12</td>
</tr>
<tr>
<td>Solaris X64 (64bit)</td>
<td>Solaris X64 (64-bit)</td>
<td>Solaris 10 + patches
<br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
@ -167,17 +168,28 @@
<td>Sun Studio 12</td>
</tr>
<tr>
<td>Windows X86 (32bit)</td>
<td>Windows X86 (32-bit)</td>
<td>Windows XP</td>
<td>Microsoft Visual Studio .NET 2003 Professional</td>
<td>Microsoft Visual Studio C++ 2008 Standard Edition</td>
</tr>
<tr>
<td>Windows X64 (64bit)</td>
<td>Windows X64 (64-bit)</td>
<td>Windows Server 2003 - Enterprise x64 Edition</td>
<td>Microsoft Platform SDK - April 2005</td>
</tr>
</tbody>
</table>
<p>
These same sources do indeed build on many more systems than the
above older generation systems, again the above is just a minimum.
<p>
Compilation problems with newer or different C/C++ compilers is a
common problem.
Similarly, compilation problems related to changes to the
<tt>/usr/include</tt> or system header files is also a
common problem with newer or unreleased OS versions.
Please report these types of problems as bugs so that they
can be dealt with accordingly.
</blockquote>
<!-- ------------------------------------------------------ -->
<hr>
@ -488,7 +500,7 @@
not work due to a lack of support for MS-DOS drive letter paths
like <tt>C:/</tt> or <tt>C:\</tt>.
Use a 3.80 version, or find a newer
version that has this problem fixed, like 3.82.
version that has this problem fixed.
The older 3.80 version of make.exe can be downloaded with this
<a href="http://cygwin.paracoda.com/release/make/make-3.80-1.tar.bz2" target="_blank">
link</a>.
@ -575,8 +587,8 @@
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
<a href="#ant">Ant</a>,
make sure it is in your PATH.
</li>
</ol>
</blockquote>
@ -592,7 +604,7 @@
Approximately 1.4 GB of free disk
space is needed for a 32-bit build.
<p>
If you are building the 64bit version, you should
If you are building the 64-bit version, you should
run the command "isainfo -v" to verify that you have a
64-bit installation, it should say <tt>sparcv9</tt> or
<tt>amd64</tt>.
@ -640,8 +652,8 @@
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
<a href="#ant">Ant</a>,
make sure it is in your PATH.
</li>
</ol>
</blockquote>
@ -650,11 +662,11 @@
<h3><a name="windows">Basic Windows System Setup</a></h3>
<blockquote>
<strong>i586 only:</strong>
The minimum recommended hardware for building the 32bit or X86
The minimum recommended hardware for building the 32-bit or X86
Windows version is an Pentium class processor or better, at least
512 MB of RAM, and approximately 600 MB of free disk space.
<strong>
NOTE: The Windows 2000 build machines need to use the
NOTE: The Windows build machines need to use the
file system NTFS.
Build machines formatted to FAT32 will not work
because FAT32 doesn't support case-sensitivity in file names.
@ -719,8 +731,11 @@
</li>
<li>
Install the
<a href="#msvc">Microsoft Visual Studio .NET 2003 Professional</a> (32bit) or the
<a href="#mssdk">Microsoft Platform SDK</a> (64bit).
<a href="#msvc">Microsoft Visual Studio Compilers</a> (32-bit).
</li>
<li>
Install the
<a href="#mssdk">Microsoft Platform SDK</a>.
</li>
<li>
Setup all environment variables for compilers
@ -732,7 +747,8 @@
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<a href="#ant">Ant</a>,
make sure it is in your PATH and set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
</li>
</ol>
@ -787,7 +803,9 @@
you must first download and install the appropriate
binary plug bundles for the OpenJDK, go to the
<a href="http://openjdk.java.net" target="_blank">OpenJDK</a> site and select
the "<b>Bundles(7)</b>" link and download the binaryplugs for
the
"<b>Bundles(7)</b>"
link and download the binaryplugs for
your particular platform.
The file downloaded is a jar file that must be extracted by running
the jar file with:
@ -823,14 +841,12 @@
The Ant tool is available from the
<a href="http://ant.apache.org/antlibs/bindownload.cgi" target="_blank">
Ant download site</a>.
You should always set
You should always make sure <tt>ant</tt> is in your PATH, and
on Windows you may also need to set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>
to point to the location of
the Ant installation, this is the directory pathname
that contains a <tt>bin and lib</tt>.
It's also a good idea to also place its <tt>bin</tt> directory
in the <tt>PATH</tt> environment variable, although it's
not absolutely required.
</blockquote>
<!-- ------------------------------------------------------ -->
<h4><a name="cacerts">Certificate Authority File (cacert)</a></h4>
@ -862,25 +878,9 @@
<blockquote>
<strong><a name="gcc">Linux gcc/binutils</a></strong>
<blockquote>
The GNU gcc compiler version should be 3.2.2 or newer.
The binutils package should be 2.11.93.0.2-11 or newer.
The GNU gcc compiler version should be 4 or newer.
The compiler used should be the default compiler installed
in <tt>/usr/bin</tt>.
<p>
Older Linux systems may require a gcc and bunutils update.
The Redhat Enterprise Advanced Server 2.1 update 2 system
is one of these systems.
RedHat Linux users can obtain this binutils package from
<a href="http://www.redhat.com"
target="_blank">Redhat web site</a>.
You will need to remove the default compiler and binutils
packages and install the required packages
into the default location on the system.
However if you have a new video card driver, like
Geforce 4 it is best to use
the same compiler as the kernel was built with to
build the new video card driver module.
So you should build the modules before making this change.
</blockquote>
<strong><a name="studio">Solaris: Sun Studio</a></strong>
<blockquote>
@ -903,19 +903,20 @@
are also an option, although these compilers have not
been extensively used yet.
</blockquote>
<strong><a name="msvc">Windows i586: Microsoft Visual Studio .NET 2003 Professional</a></strong>
<strong><a name="msvc">Windows i586: Microsoft Visual Studio Compilers</a></strong>
<blockquote>
The 32-bit OpenJDK Windows build
requires Microsoft Visual Studio .NET 2003 (VS2003) Professional
requires
Microsoft Visual Studio C++ 2008 (VS2008) Standard
Edition compiler.
The compiler and other tools are expected to reside
in the location defined by the variable <tt>VS71COMNTOOLS</tt> which
is set by the Microsoft Visual Studio .NET installer.
in the location defined by the variable
<tt>VS90COMNTOOLS</tt> which
is set by the Microsoft Visual Studio installer.
<p>
Once the compiler is installed,
it is recommended that you run <tt>VCVARS32.BAT</tt>
to set the compiler environment variables
<tt>MSVCDIR</tt>,
<tt>INCLUDE</tt>,
<tt>LIB</tt>, and
<tt>PATH</tt>
@ -923,16 +924,12 @@
OpenJDK.
The above environment variables <b>MUST</b> be set.
<p>
The Microsoft Visual Studio .NET 2005 (VS2005) compiler
will not work at this time due to the new runtime dll
and the manifest requirements.
<p>
<b>WARNING:</b> Make sure you check out the
<a href="#cygwin">CYGWIN link.exe WARNING</a>.
The path <tt>/usr/bin</tt> must be after the path to the
Visual Studio product.
</blockquote>
<strong><a name="mssdk">Windows X64: Microsoft Platform SDK April 2005</a></strong>
<strong><a name="mssdk">Windows: Microsoft Platform SDK</a></strong>
<blockquote>
On <b>X64</b>, the Microsoft Platform Software
Development Kit (SDK), April 2005 Edition compiler,
@ -953,10 +950,9 @@
OpenJDK.
The above environment variables <b>MUST</b> be set.
<p>
Note that this compiler may say it's version is a
Microsoft Visual Studio .NET 2005 (VS2005), but be careful,
it will not match the official VS2005 product.
This Platform SDK compiler is only used on X64 builds.
This Platform SDK compiler is only used on X64 builds
but other parts of the Platform SDK may be used
for the X86 builds.
</blockquote>
</blockquote>
<!-- ------------------------------------------------------ -->
@ -1241,37 +1237,37 @@
<strong><a name="msvcrt"><tt>MSVCRT.DLL</tt></a></strong>
<blockquote>
<strong>i586 only:</strong>
The OpenJDK 32bit build requires access to
<tt>MSVCRT.DLL</tt> version 6.00.8337.0 or newer.
The OpenJDK 32-bit build requires access to a redistributable
<tt>MSVCRT.DLL</tt>.
If the <tt>MSVCRT.DLL</tt> is not installed in
the system32 directory set the
<a href="#ALT_MSVCRT_DLL_PATH"><tt>ALT_MSVCRT_DLL_PATH</tt></a>
variable to the location.
variable to the location of this file.
<p>
<strong>X64 only:</strong>
The OpenJDK 64bit build requires access to
<tt>MSVCRT.DLL</tt> version 7.0.3790.0 or newer, which is
The OpenJDK 64-bit build requires access to a redistributable
<tt>MSVCRT.DLL</tt>, which is
usually supplied by the
<a href="#mssdk">Platform SDK</a>.
If it is not available from the Platform SDK,
set the
<a href="#ALT_MSVCRT_DLL_PATH"><tt>ALT_MSVCRT_DLL_PATH</tt></a>
variable to the location.
variable to the location of this file.
</blockquote>
<strong><tt><a name="msvcr71">MSVCR71.DLL</a></tt></strong>
<strong><tt><a name="msvcr90">MSVCR90.DLL</a></tt></strong>
<blockquote>
<strong>i586 only:</strong>
The
OpenJDK
build requires access to
MSVCR71.DLL version 7.10.3052.4 or newer which should be
build requires access to a redistributable
<tt>MSVCR90.DLL</tt> which should be
supplied by the
<a href="#msvc">Visual Studio product</a>
If the <tt>MSVCR71.DLL</tt> is not available from the
<a href="#msvc">Visual Studio product</a>.
If the <tt>MSVCR90.DLL</tt> is not available from the
Visual Studio product
set the
<a href="#ALT_MSVCR71_DLL_PATH"><tt>ALT_MSVCR71_DLL_PATH</tt></a>
variable to the location.
<a href="#ALT_MSVCR90_DLL_PATH"><tt>ALT_MSVCR90_DLL_PATH</tt></a>
variable to the location of this file.
</blockquote>
</blockquote>
<!-- ------------------------------------------------------ -->
@ -1359,13 +1355,38 @@
document) that can impact the build are:
<blockquote>
<dl>
<dt><a name="ALT_BINARY_PLUGS_PATH"><tt>ALT_BINARY_PLUGS_PATH</tt></a></dt>
<dt><a name="path"><tt>PATH</tt></a> </dt>
<dd>Typically you want to set the <tt>PATH</tt> to include:
<ul>
<li>The location of the GNU make binary</li>
<li>The location of the Bootstrap JDK <tt>java</tt>
(see <a href="#bootjdk">Bootstrap JDK</a>)</li>
<li>The location of the C/C++ compilers
(see <a href="#compilers"><tt>compilers</tt></a>)</li>
<li>The location or locations for the Unix command utilities
(e.g. <tt>/usr/bin</tt>)</li>
</ul>
</dd>
<dt><tt>MILESTONE</tt> </dt>
<dd>
The location of the binary plugs installation.
See <a href="#binaryplugs">Binary Plugs</a> for more information.
You should always have a local copy of a
recent Binary Plugs install image
and set this variable to that location.
The milestone name for the build (<i>e.g.</i>"beta").
The default value is "internal".
</dd>
<dt><tt>BUILD_NUMBER</tt> </dt>
<dd>
The build number for the build (<i>e.g.</i> "b27").
The default value is "b00".
</dd>
<dt><a name="arch_data_model"><tt>ARCH_DATA_MODEL</tt></a></dt>
<dd>The <tt>ARCH_DATA_MODEL</tt> variable
is used to specify whether the build is to generate 32-bit or 64-bit
binaries.
The Solaris build supports either 32-bit or 64-bit builds, but
Windows and Linux will support only one, depending on the specific
OS being used.
Normally, setting this variable is only necessary on Solaris.
Set <tt>ARCH_DATA_MODEL</tt> to <tt>32</tt> for generating 32-bit binaries,
or to <tt>64</tt> for generating 64-bit binaries.
</dd>
<dt><a name="ALT_BOOTDIR"><tt>ALT_BOOTDIR</tt></a></dt>
<dd>
@ -1374,25 +1395,89 @@
You should always install your own local Bootstrap JDK and
always set <tt>ALT_BOOTDIR</tt> explicitly.
</dd>
<dt><a name="ALT_BUILD_BINARY_PLUGS_PATH"><tt>ALT_BUILD_BINARY_PLUGS_PATH</tt></a></dt>
<dt><a name="ALT_BINARY_PLUGS_PATH"><tt>ALT_BINARY_PLUGS_PATH</tt></a></dt>
<dd>
These are useful in managing builds on multiple platforms.
The default network location for all of the binary plug images
for all platforms.
If <tt><a href="#ALT_BINARY_PLUGS_PATH">ALT_BINARY_PLUGS_PATH</a></tt>
is not set, this directory will be used and should contain
the following directories:
<tt>solaris-sparc</tt>,
<tt>solaris-i586</tt>,
<tt>solaris-sparcv9</tt>,
<tt>solaris-amd64</tt>,
<tt>linux-i586</tt>,
<tt>linux-amd64</tt>,
<tt>windows-i586</tt>,
and
<tt>windows-amd64</tt>.
Where each of these directories contain the binary plugs image
for that platform.
The location of the binary plugs installation.
See <a href="#binaryplugs">Binary Plugs</a> for more information.
You should always have a local copy of a
recent Binary Plugs install image
and set this variable to that location.
</dd>
<dt><a name="ALT_JDK_IMPORT_PATH"><tt>ALT_JDK_IMPORT_PATH</tt></a></dt>
<dd>
The location of a previously built JDK installation.
See <a href="#importjdk">Optional Import JDK</a> for more information.
</dd>
<dt><a name="ALT_OUTPUTDIR"><tt>ALT_OUTPUTDIR</tt></a> </dt>
<dd>
An override for specifying the (absolute) path of where the
build output is to go.
The default output directory will be build/<i>platform</i>.
</dd>
<dt><a name="ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a> </dt>
<dd>
The location of the C/C++ compiler.
The default varies depending on the platform.
</dd>
<dt><tt><a name="ALT_CACERTS_FILE">ALT_CACERTS_FILE</a></tt></dt>
<dd>
The location of the <a href="#cacerts">cacerts</a> file.
The default will refer to
<tt>jdk/src/share/lib/security/cacerts</tt>.
</dd>
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
<dd>
The location of the CUPS header files.
See <a href="#cups">CUPS information</a> for more information.
If this path does not exist the fallback path is
<tt>/usr/include</tt>.
</dd>
<dt><a name="ALT_FREETYPE_LIB_PATH"><tt>ALT_FREETYPE_LIB_PATH</tt></a></dt>
<dd>
The location of the FreeType shared library.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_FREETYPE_HEADERS_PATH"><tt>ALT_FREETYPE_HEADERS_PATH</tt></a></dt>
<dd>
The location of the FreeType header files.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_JDK_DEVTOOLS_PATH"><tt>ALT_JDK_DEVTOOLS_PATH</tt></a></dt>
<dd>
The default root location of the devtools.
The default value is
<tt>$(ALT_SLASH_JAVA)/devtools</tt>.
</dd>
<dt><tt><a name="ALT_DEVTOOLS_PATH">ALT_DEVTOOLS_PATH</a></tt> </dt>
<dd>
The location of tools like the
<a href="#zip"><tt>zip</tt> and <tt>unzip</tt></a>
binaries, but might also contain the GNU make utility
(<tt><i>gmake</i></tt>).
So this area is a bit of a grab bag, especially on Windows.
The default value depends on the platform and
Unix Commands being used.
On Linux the default will be
<tt>$(ALT_JDK_DEVTOOLS_PATH)/linux/bin</tt>,
on Solaris
<tt>$(ALT_JDK_DEVTOOLS_PATH)/<i>{sparc,i386}</i>/bin</tt>,
and on Windows with CYGWIN
<tt>/usr/bin</tt>.
</dd>
<dt><a name="ALT_UNIXCCS_PATH"><tt>ALT_UNIXCCS_PATH</tt></a></dt>
<dd>
<strong>Solaris only:</strong>
An override for specifying where the Unix CCS
command set are located.
The default location is <tt>/usr/ccs/bin</tt>
</dd>
<dt><a name="ALT_SLASH_JAVA"><tt>ALT_SLASH_JAVA</tt></a></dt>
<dd>
The default root location for many of the ALT path locations
of the following ALT variables.
The default value is
<tt>"/java"</tt> on Solaris and Linux,
<tt>"J:"</tt> on Windows.
</dd>
<dt><a name="ALT_BUILD_JDK_IMPORT_PATH"><tt>ALT_BUILD_JDK_IMPORT_PATH</tt></a></dt>
<dd>
@ -1414,166 +1499,57 @@
Where each of these directories contain the import JDK image
for that platform.
</dd>
<dt><tt><a name="ALT_CACERTS_FILE">ALT_CACERTS_FILE</a></tt></dt>
<dt><a name="ALT_BUILD_BINARY_PLUGS_PATH"><tt>ALT_BUILD_BINARY_PLUGS_PATH</tt></a></dt>
<dd>
The location of the <a href="#cacerts">cacerts</a> file.
The default will refer to
<tt>jdk/src/share/lib/security/cacerts</tt>.
These are useful in managing builds on multiple platforms.
The default network location for all of the binary plug images
for all platforms.
If <tt><a href="#ALT_BINARY_PLUGS_PATH">ALT_BINARY_PLUGS_PATH</a></tt>
is not set, this directory will be used and should contain
the following directories:
<tt>solaris-sparc</tt>,
<tt>solaris-i586</tt>,
<tt>solaris-sparcv9</tt>,
<tt>solaris-amd64</tt>,
<tt>linux-i586</tt>,
<tt>linux-amd64</tt>,
<tt>windows-i586</tt>,
and
<tt>windows-amd64</tt>.
Where each of these directories contain the binary plugs image
for that platform.
</dd>
<dt><a name="ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a> </dt>
<dt><strong>Windows specific:</strong></dt>
<dd>
The location of the C/C++ compiler.
The default varies depending on the platform.
</dd>
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
<dd>
The location of the CUPS header files.
See <a href="#cups">CUPS information</a> for more information.
If this path does not exist the fallback path is
<tt>/usr/include</tt>.
</dd>
<dt><tt><a name="ALT_DEVTOOLS_PATH">ALT_DEVTOOLS_PATH</a></tt> </dt>
<dd>
The location of tools like the
<a href="#zip"><tt>zip</tt> and <tt>unzip</tt></a>
binaries, but might also contain the GNU make utility
(<tt><i>gmake</i></tt>).
So this area is a bit of a grab bag, especially on Windows.
The default value depends on the platform and
Unix Commands being used.
On Linux the default will be
<tt>$(ALT_JDK_DEVTOOLS_PATH)/linux/bin</tt>,
on Solaris
<tt>$(ALT_JDK_DEVTOOLS_PATH)/<i>{sparc,i386}</i>/bin</tt>,
on Windows with MKS
<tt>%SYSTEMDRIVE%/UTILS</tt>,
and on Windows with CYGWIN
<tt>/usr/bin</tt>.
</dd>
<dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the
<a href="#dxsdk">Microsoft DirectX 9 SDK</a>.
The default will be to try and use the DirectX environment
variable <tt>DXSDK_DIR</tt>,
failing that, look in <tt>C:/DXSDK</tt>.
</dd>
<dt><a name="ALT_FREETYPE_HEADERS_PATH"><tt>ALT_FREETYPE_HEADERS_PATH</tt></a></dt>
<dd>
The location of the FreeType header files.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_FREETYPE_LIB_PATH"><tt>ALT_FREETYPE_LIB_PATH</tt></a></dt>
<dd>
The location of the FreeType shared library.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_JDK_DEVTOOLS_PATH"><tt>ALT_JDK_DEVTOOLS_PATH</tt></a></dt>
<dd>
The default root location of the devtools.
The default value is
<tt>$(ALT_SLASH_JAVA)/devtools</tt>.
</dd>
<dt><a name="ALT_JDK_IMPORT_PATH"><tt>ALT_JDK_IMPORT_PATH</tt></a></dt>
<dd>
The location of a previously built JDK installation.
See <a href="#importjdk">Optional Import JDK</a> for more information.
</dd>
<dt><a name="ALT_MSDEVTOOLS_PATH"><tt>ALT_MSDEVTOOLS_PATH</tt></a> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the Microsoft Visual Studio .NET 2003
tools 'bin' directory.
The default is usually derived from
<a href="#ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCR71_DLL_PATH">ALT_MSVCR71_DLL_PATH</a></tt> </dt>
<dd>
<strong>Windows i586 only:</strong>
The location of the
<a href="#msvcr71"><tt>MSVCR71.DLL</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the
<a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
</dd>
<dt><a name="ALT_OUTPUTDIR"><tt>ALT_OUTPUTDIR</tt></a> </dt>
<dd>
An override for specifying the (absolute) path of where the
build output is to go.
The default output directory will be build/<i>platform</i>.
</dd>
<dt><a name="ALT_SLASH_JAVA"><tt>ALT_SLASH_JAVA</tt></a></dt>
<dd>
The default root location for many of the ALT path locations
of the following ALT variables.
The default value is
<tt>"/java"</tt> on Solaris and Linux,
<tt>"J:"</tt> on Windows.
</dd>
<dt><a name="ALT_UNIXCCS_PATH"><tt>ALT_UNIXCCS_PATH</tt></a></dt>
<dd>
<strong>Solaris only:</strong>
An override for specifying where the Unix CCS
command set are located.
The default location is <tt>/usr/ccs/bin</tt>
</dd>
<dt><a name="ALT_UNIXCOMMAND_PATH"><tt>ALT_UNIXCOMMAND_PATH</tt></a> </dt>
<dd>
An override for specifying where the
Unix command set are located.
The default location varies depending on the platform,
<tt>"%SYSTEMDRIVE%/MKSNT"</tt> or
<tt>$(ROOTDIR)</tt> on Windows with MKS, otherwise it's
<tt>"/bin"</tt> or <tt>/usr/bin</tt>.
</dd>
<dt><a name="ALT_USRBIN_PATH"><tt>ALT_USRBIN_PATH</tt></a></dt>
<dd>
An override for specifying where the
Unix <tt>/usr/bin</tt> commands are located. You usually do not need
to set this variable: the default location is <tt>/usr/bin</tt>)
</dd>
<dt><a name="ANT_HOME"><tt>ANT_HOME</tt></a></dt>
<dd>
The location of the Ant installation.
See <a href="#ant">Ant</a> for more information.
You should always set <tt>ANT_HOME</tt> explicitly.
</dd>
<dt><a name="arch_data_model"><tt>ARCH_DATA_MODEL</tt></a></dt>
<dd>The <tt>ARCH_DATA_MODEL</tt> variable
is used to specify whether the build is to generate 32-bit or 64-bit
binaries.
The Solaris build supports either 32-bit or 64-bit builds, but
Windows and Linux will support only one, depending on the specific
OS being used.
Normally, setting this variable is only necessary on Solaris.
Set <tt>ARCH_DATA_MODEL</tt> to <tt>32</tt> for generating 32-bit binaries,
or to <tt>64</tt> for generating 64-bit binaries.
</dd>
<dt><tt>BUILD_NUMBER</tt> </dt>
<dd>
The build number for the build (<i>e.g.</i> "b27").
The default value is "b00".
</dd>
<dt><tt>MILESTONE</tt> </dt>
<dd>
The milestone name for the build (<i>e.g.</i>"beta").
The default value is "internal".
</dd>
<dt><a name="path"><tt>PATH</tt></a> </dt>
<dd>Typically you want to set the <tt>PATH</tt> to include:
<ul>
<li>The location of the GNU make binary</li>
<li>The location of the Bootstrap JDK <tt>java</tt>
(see <a href="#bootjdk">Bootstrap JDK</a>)</li>
<li>The location of the C/C++ compilers
(see <a href="#compilers"><tt>compilers</tt></a>)</li>
<li>The location or locations for the Unix command utilities
(e.g. <tt>/usr/bin</tt>)</li>
</ul>
<dl>
<dt><a name="ALT_MSDEVTOOLS_PATH"><tt>ALT_MSDEVTOOLS_PATH</tt></a> </dt>
<dd>
The location of the
Microsoft Visual Studio
tools 'bin' directory.
The default is usually derived from
<a href="#ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a>.
</dd>
<dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt>
<dd>
The location of the
<a href="#dxsdk">Microsoft DirectX 9 SDK</a>.
The default will be to try and use the DirectX environment
variable <tt>DXSDK_DIR</tt>,
failing that, look in <tt>C:/DXSDK</tt>.
</dd>
<dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
<dd>
The location of the
<a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCR90_DLL_PATH">ALT_MSVCR90_DLL_PATH</a></tt> </dt>
<dd>
<strong>i586 only:</strong>
The location of the
<a href="#msvcr90"><tt>MSVCR90.DLL</tt></a>.
</dd>
</dl>
</dd>
</dl>
</blockquote>
@ -1661,8 +1637,8 @@
This is caused by a missing libstdc++.a library.
This is installed as part of a specific package
(e.g. libstdc++.so.devel.386).
By default some 64bit Linux versions (e.g. Fedora)
only install the 64bit version of the libstdc++ package.
By default some 64-bit Linux versions (e.g. Fedora)
only install the 64-bit version of the libstdc++ package.
Various parts of the JDK build require a static
link of the C++ runtime libraries to allow for maximum
portability of the built images.

View File

@ -14,3 +14,4 @@ ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31
59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37
08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39
184e21992f47a8d730df1adc5b21a108f3125489 jdk7-b40

View File

@ -14,3 +14,4 @@ e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36
9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37
d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39
81a0cbe3b28460ce836109934ece03db7afaf9cc jdk7-b40

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008
HS_MAJOR_VER=14
HS_MINOR_VER=0
HS_BUILD_NUMBER=07
HS_BUILD_NUMBER=08
JDK_MAJOR_VER=1
JDK_MINOR_VER=7

View File

@ -200,29 +200,6 @@ BUILD_WIN_SA = 0
checkSA::
@echo Not building SA: ARCH = ia64
!elseif exist("$(MSVCDIR)\PlatformSDK\Include\dbgeng.h")
# These don't have to be set because the default
# setting of INCLUDE and LIB already contain the needed dirs.
SA_INCLUDE =
SA_LIB =
!elseif exist("$(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h")
# These don't have to be set because the default
# setting of INCLUDE and LIB already contain the needed dirs.
SA_INCLUDE =
SA_LIB =
!else
checkSA::
@echo .
@echo ERROR: Can't build SA because dbgeng.h does not exist here:
@echo $(MSVCDIR)\PlatformSDK\Include\dbgeng.h
@echo nor here:
@echo $(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h
@echo You must use Vis. Studio .Net 2003 on Win 32, and you must
@echo have the Microsoft SDK installed on Win amd64.
@echo You can disable building of SA by specifying BUILD_WIN_SA = 0
@echo . && false
!endif # ! "$(BUILD_WIN_SA)" != "1"
#########################################################################

View File

@ -119,7 +119,7 @@ endif
# we want to release it. If we build it here,
# the SDK makefiles will copy it over and put it into
# the created image.
BUILD_WIN_SA = 0
BUILD_WIN_SA = 1
ifneq ($(ALT_BUILD_WIN_SA),)
BUILD_WIN_SA = $(ALT_BUILD_WIN_SA)
endif

View File

@ -49,6 +49,9 @@ SA_PROPERTIES = $(SA_CLASSDIR)\sa.properties
default:: $(GENERATED)\sa-jdi.jar
# Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space
# at the end of SA version string and causes a version mismatch with the target VM version.
$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
@echo ...Building sa-jdi.jar
@ -56,15 +59,15 @@ $(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP) > $(SA_PROPERTIES)
$(RUN_JAR) cf $@ -C saclasses .
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql
$(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/*
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/
$(QUIETLY) rm -rf $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) mkdir $(SA_CLASSDIR)\sun\jvm\hotspot\ui\resources
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)
$(RUN_JAR) cf $@ -C saclasses .
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext
@ -93,7 +96,7 @@ SA_LINK_FLAGS = bufferoverflowU.lib
SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
!endif
!if "$(MT)" != ""
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
!endif
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)

View File

@ -2272,7 +2272,9 @@ void os::free_memory(char *addr, size_t bytes) {
uncommit_memory(addr, bytes);
}
void os::numa_make_global(char *addr, size_t bytes) { }
void os::numa_make_global(char *addr, size_t bytes) {
Linux::numa_interleave_memory(addr, bytes);
}
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
Linux::numa_tonode_memory(addr, bytes, lgrp_hint);
@ -2314,7 +2316,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
extern "C" void numa_warn(int number, char *where, ...) { }
extern "C" void numa_error(char *where) { }
void os::Linux::libnuma_init() {
bool os::Linux::libnuma_init() {
// sched_getcpu() should be in libc.
set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
dlsym(RTLD_DEFAULT, "sched_getcpu")));
@ -2330,31 +2332,51 @@ void os::Linux::libnuma_init() {
dlsym(handle, "numa_available")));
set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
dlsym(handle, "numa_tonode_memory")));
set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
dlsym(handle, "numa_interleave_memory")));
if (numa_available() != -1) {
set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes"));
// Create a cpu -> node mapping
_cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
rebuild_cpu_to_node_map();
return true;
}
}
}
return false;
}
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
int cpu_num = os::active_processor_count();
const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
// in libnuma (possible values are starting from 16,
// and continuing up with every other power of 2, but less
// than the maximum number of CPUs supported by kernel), and
// is a subject to change (in libnuma version 2 the requirements
// are more reasonable) we'll just hardcode the number they use
// in the library.
const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
size_t cpu_num = os::active_processor_count();
size_t cpu_map_size = NCPUS / BitsPerCLong;
size_t cpu_map_valid_size =
MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
cpu_to_node()->clear();
cpu_to_node()->at_grow(cpu_num - 1);
int node_num = numa_get_groups_num();
int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong;
size_t node_num = numa_get_groups_num();
unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
for (int i = 0; i < node_num; i++) {
for (size_t i = 0; i < node_num; i++) {
if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
for (int j = 0; j < cpu_map_size; j++) {
for (size_t j = 0; j < cpu_map_valid_size; j++) {
if (cpu_map[j] != 0) {
for (int k = 0; k < BitsPerLong; k++) {
for (size_t k = 0; k < BitsPerCLong; k++) {
if (cpu_map[j] & (1UL << k)) {
cpu_to_node()->at_put(j * BitsPerLong + k, i);
cpu_to_node()->at_put(j * BitsPerCLong + k, i);
}
}
}
@ -2377,7 +2399,8 @@ os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus;
os::Linux::numa_max_node_func_t os::Linux::_numa_max_node;
os::Linux::numa_available_func_t os::Linux::_numa_available;
os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory;
os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
unsigned long* os::Linux::_numa_all_nodes;
bool os::uncommit_memory(char* addr, size_t size) {
return ::mmap(addr, size,
@ -3695,7 +3718,17 @@ jint os::init_2(void)
}
if (UseNUMA) {
Linux::libnuma_init();
if (!Linux::libnuma_init()) {
UseNUMA = false;
} else {
if ((Linux::numa_max_node() < 1)) {
// There's only one node(they start from 0), disable NUMA.
UseNUMA = false;
}
}
if (!UseNUMA && ForceNUMA) {
UseNUMA = true;
}
}
if (MaxFDLimit) {

View File

@ -146,7 +146,7 @@ class Linux {
static bool is_floating_stack() { return _is_floating_stack; }
static void libpthread_init();
static void libnuma_init();
static bool libnuma_init();
// Minimum stack size a thread can be created with (allowing
// the VM to completely create the thread and enter user code)
@ -240,20 +240,23 @@ private:
typedef int (*numa_max_node_func_t)(void);
typedef int (*numa_available_func_t)(void);
typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
static sched_getcpu_func_t _sched_getcpu;
static numa_node_to_cpus_func_t _numa_node_to_cpus;
static numa_max_node_func_t _numa_max_node;
static numa_available_func_t _numa_available;
static numa_tonode_memory_func_t _numa_tonode_memory;
static numa_interleave_memory_func_t _numa_interleave_memory;
static unsigned long* _numa_all_nodes;
static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
public:
static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
@ -264,6 +267,11 @@ public:
static int numa_tonode_memory(void *start, size_t size, int node) {
return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
}
static void numa_interleave_memory(void *start, size_t size) {
if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
_numa_interleave_memory(start, size, _numa_all_nodes);
}
}
static int get_node_by_cpu(int cpu_id);
};

View File

@ -4638,7 +4638,7 @@ void os::Solaris::synchronization_init() {
}
}
void os::Solaris::liblgrp_init() {
bool os::Solaris::liblgrp_init() {
void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
if (handle != NULL) {
os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
@ -4653,9 +4653,9 @@ void os::Solaris::liblgrp_init() {
lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
set_lgrp_cookie(c);
} else {
warning("your OS does not support NUMA");
return true;
}
return false;
}
void os::Solaris::misc_sym_init() {
@ -4824,9 +4824,25 @@ jint os::init_2(void) {
vm_page_size()));
Solaris::libthread_init();
if (UseNUMA) {
Solaris::liblgrp_init();
if (!Solaris::liblgrp_init()) {
UseNUMA = false;
} else {
size_t lgrp_limit = os::numa_get_groups_num();
int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
FREE_C_HEAP_ARRAY(int, lgrp_ids);
if (lgrp_num < 2) {
// There's only one locality group, disable NUMA.
UseNUMA = false;
}
}
if (!UseNUMA && ForceNUMA) {
UseNUMA = true;
}
}
Solaris::misc_sym_init();
Solaris::signal_sets_init();
Solaris::init_signal_mem();

View File

@ -176,7 +176,7 @@ class Solaris {
public:
static void libthread_init();
static void synchronization_init();
static void liblgrp_init();
static bool liblgrp_init();
// Load miscellaneous symbols.
static void misc_sym_init();
// This boolean allows users to forward their own non-matching signals

View File

@ -3347,6 +3347,10 @@ jint os::init_2(void) {
// initialize thread priority policy
prio_init();
if (UseNUMA && !ForceNUMA) {
UseNUMA = false; // Currently unsupported.
}
return JNI_OK;
}

View File

@ -676,21 +676,6 @@ GraphBuilder::ScopeData::ScopeData(ScopeData* parent)
}
void GraphBuilder::kill_field(ciField* field) {
if (UseLocalValueNumbering) {
vmap()->kill_field(field);
}
}
void GraphBuilder::kill_array(Value value) {
if (UseLocalValueNumbering) {
vmap()->kill_array(value->type());
}
_memory->store_value(value);
}
void GraphBuilder::kill_all() {
if (UseLocalValueNumbering) {
vmap()->kill_all();
@ -987,8 +972,8 @@ void GraphBuilder::store_indexed(BasicType type) {
length = append(new ArrayLength(array, lock_stack()));
}
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, lock_stack());
kill_array(value); // invalidate all CSEs that are memory accesses of the same type
append(result);
_memory->store_value(value);
}
@ -1478,9 +1463,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
case Bytecodes::_putstatic:
{ Value val = pop(type);
append(new StoreField(append(obj), offset, field, val, true, lock_stack(), state_copy, is_loaded, is_initialized));
if (UseLocalValueNumbering) {
vmap()->kill_field(field); // invalidate all CSEs that are memory accesses
}
}
break;
case Bytecodes::_getfield :
@ -1503,7 +1485,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
if (is_loaded) store = _memory->store(store);
if (store != NULL) {
append(store);
kill_field(field); // invalidate all CSEs that are accesses of this field
}
}
break;
@ -1900,6 +1881,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
assert(i2->bci() != -1, "should already be linked");
return i2;
}
ValueNumberingEffects vne(vmap());
i1->visit(&vne);
}
if (i1->as_Phi() == NULL && i1->as_Local() == NULL) {
@ -1926,14 +1909,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
assert(_last == i1, "adjust code below");
StateSplit* s = i1->as_StateSplit();
if (s != NULL && i1->as_BlockEnd() == NULL) {
// Continue CSE across certain intrinsics
Intrinsic* intrinsic = s->as_Intrinsic();
if (UseLocalValueNumbering) {
if (intrinsic == NULL || !intrinsic->preserves_state()) {
vmap()->kill_all(); // for now, hopefully we need this only for calls eventually
}
}
if (EliminateFieldAccess) {
Intrinsic* intrinsic = s->as_Intrinsic();
if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) {
_memory->kill();
}

View File

@ -283,8 +283,6 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
Dependencies* dependency_recorder() const; // = compilation()->dependencies()
bool direct_compare(ciKlass* k);
void kill_field(ciField* field);
void kill_array(Value value);
void kill_all();
ValueStack* lock_stack();

View File

@ -133,53 +133,77 @@ class ValueNumberingVisitor: public InstructionVisitor {
virtual void kill_array(ValueType* type) = 0;
// visitor functions
void do_StoreField (StoreField* x) { kill_field(x->field()); };
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); };
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); };
void do_MonitorExit (MonitorExit* x) { kill_memory(); };
void do_Invoke (Invoke* x) { kill_memory(); };
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); };
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); };
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); };
void do_StoreField (StoreField* x) {
if (!x->is_initialized()) {
kill_memory();
} else {
kill_field(x->field());
}
}
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); }
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); }
void do_MonitorExit (MonitorExit* x) { kill_memory(); }
void do_Invoke (Invoke* x) { kill_memory(); }
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); }
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); }
void do_Phi (Phi* x) { /* nothing to do */ };
void do_Local (Local* x) { /* nothing to do */ };
void do_Constant (Constant* x) { /* nothing to do */ };
void do_LoadField (LoadField* x) { /* nothing to do */ };
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ };
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ };
void do_NegateOp (NegateOp* x) { /* nothing to do */ };
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ };
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ };
void do_LogicOp (LogicOp* x) { /* nothing to do */ };
void do_CompareOp (CompareOp* x) { /* nothing to do */ };
void do_IfOp (IfOp* x) { /* nothing to do */ };
void do_Convert (Convert* x) { /* nothing to do */ };
void do_NullCheck (NullCheck* x) { /* nothing to do */ };
void do_NewInstance (NewInstance* x) { /* nothing to do */ };
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ };
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ };
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ };
void do_CheckCast (CheckCast* x) { /* nothing to do */ };
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ };
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ };
void do_Goto (Goto* x) { /* nothing to do */ };
void do_If (If* x) { /* nothing to do */ };
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ };
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ };
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ };
void do_Return (Return* x) { /* nothing to do */ };
void do_Throw (Throw* x) { /* nothing to do */ };
void do_Base (Base* x) { /* nothing to do */ };
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ };
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
void do_RoundFP (RoundFP* x) { /* nothing to do */ };
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ };
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ };
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ };
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ };
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ };
void do_Phi (Phi* x) { /* nothing to do */ }
void do_Local (Local* x) { /* nothing to do */ }
void do_Constant (Constant* x) { /* nothing to do */ }
void do_LoadField (LoadField* x) {
if (!x->is_initialized()) {
kill_memory();
}
}
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }
void do_NegateOp (NegateOp* x) { /* nothing to do */ }
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ }
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }
void do_LogicOp (LogicOp* x) { /* nothing to do */ }
void do_CompareOp (CompareOp* x) { /* nothing to do */ }
void do_IfOp (IfOp* x) { /* nothing to do */ }
void do_Convert (Convert* x) { /* nothing to do */ }
void do_NullCheck (NullCheck* x) { /* nothing to do */ }
void do_NewInstance (NewInstance* x) { /* nothing to do */ }
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }
void do_CheckCast (CheckCast* x) { /* nothing to do */ }
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }
void do_Goto (Goto* x) { /* nothing to do */ }
void do_If (If* x) { /* nothing to do */ }
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }
void do_Return (Return* x) { /* nothing to do */ }
void do_Throw (Throw* x) { /* nothing to do */ }
void do_Base (Base* x) { /* nothing to do */ }
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
void do_RoundFP (RoundFP* x) { /* nothing to do */ }
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ }
};
class ValueNumberingEffects: public ValueNumberingVisitor {
private:
ValueMap* _map;
public:
// implementation for abstract methods of ValueNumberingVisitor
void kill_memory() { _map->kill_memory(); }
void kill_field(ciField* field) { _map->kill_field(field); }
void kill_array(ValueType* type) { _map->kill_array(type); }
ValueNumberingEffects(ValueMap* map): _map(map) {}
};

View File

@ -325,24 +325,30 @@ class Par_PushOrMarkClosure: public OopClosure {
// For objects in CMS generation, this closure marks
// given objects (transitively) as being reachable/live.
// This is currently used during the (weak) reference object
// processing phase of the CMS final checkpoint step.
// processing phase of the CMS final checkpoint step, as
// well as during the concurrent precleaning of the discovered
// reference lists.
class CMSKeepAliveClosure: public OopClosure {
private:
CMSCollector* _collector;
const MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
bool _concurrent_precleaning;
protected:
DO_OOP_WORK_DEFN
public:
CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack):
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack) {
_mark_stack(mark_stack),
_concurrent_precleaning(cpc) {
assert(!_span.is_empty(), "Empty span could spell trouble");
}
bool concurrent_precleaning() const { return _concurrent_precleaning; }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); }

View File

@ -538,6 +538,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
_survivor_chunk_capacity(0), // -- ditto --
_survivor_chunk_index(0), // -- ditto --
_ser_pmc_preclean_ovflw(0),
_ser_kac_preclean_ovflw(0),
_ser_pmc_remark_ovflw(0),
_par_pmc_remark_ovflw(0),
_ser_kac_ovflw(0),
@ -1960,6 +1961,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
ref_processor()->set_enqueuing_is_done(false);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_soft_refs);
// If an asynchronous collection finishes, the _modUnionTable is
// all clear. If we are assuming the collection from an asynchronous
// collection, clear the _modUnionTable.
@ -2383,6 +2385,9 @@ void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
Universe::verify(true);
}
// Snapshot the soft reference policy to be used in this collection cycle.
ref_processor()->setup_policy(clear_all_soft_refs);
bool init_mark_was_synchronous = false; // until proven otherwise
while (_collectorState != Idling) {
if (TraceCMSState) {
@ -4388,10 +4393,10 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
CMSPrecleanRefsYieldClosure yield_cl(this);
assert(rp->span().equals(_span), "Spans should be equal");
CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
&_markStack);
&_markStack, true /* preclean */);
CMSDrainMarkingStackClosure complete_trace(this,
_span, &_markBitMap, &_markStack,
&keep_alive);
_span, &_markBitMap, &_markStack,
&keep_alive, true /* preclean */);
// We don't want this step to interfere with a young
// collection because we don't want to take CPU
@ -4590,11 +4595,11 @@ size_t CMSCollector::preclean_mod_union_table(
if (!dirtyRegion.is_empty()) {
assert(numDirtyCards > 0, "consistency check");
HeapWord* stop_point = NULL;
stopTimer();
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
bitMapLock());
startTimer();
{
stopTimer();
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
bitMapLock());
startTimer();
verify_work_stacks_empty();
verify_overflow_empty();
sample_eden();
@ -4611,10 +4616,6 @@ size_t CMSCollector::preclean_mod_union_table(
assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
(_collectorState == AbortablePreclean && should_abort_preclean()),
"Unparsable objects should only be in perm gen.");
stopTimer();
CMSTokenSyncWithLocks ts(true, bitMapLock());
startTimer();
_modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
if (should_abort_preclean()) {
break; // out of preclean loop
@ -4852,17 +4853,19 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch,
// recurrence of that condition.
assert(_markStack.isEmpty(), "No grey objects");
size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
_ser_kac_ovflw;
_ser_kac_ovflw + _ser_kac_preclean_ovflw;
if (ser_ovflw > 0) {
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Marking stack overflow (benign) "
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT
", kac_preclean="SIZE_FORMAT")",
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
_ser_kac_ovflw);
_ser_kac_ovflw, _ser_kac_preclean_ovflw);
}
_markStack.expand();
_ser_pmc_remark_ovflw = 0;
_ser_pmc_preclean_ovflw = 0;
_ser_kac_preclean_ovflw = 0;
_ser_kac_ovflw = 0;
}
if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
@ -5675,40 +5678,29 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
ReferencePolicy* soft_ref_policy;
assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
// Process weak references.
if (clear_all_soft_refs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
verify_work_stacks_empty();
ReferenceProcessor* rp = ref_processor();
assert(rp->span().equals(_span), "Spans should be equal");
assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
// Process weak references.
rp->setup_policy(clear_all_soft_refs);
verify_work_stacks_empty();
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
&_markStack);
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure);
&cmsKeepAliveClosure, false /* !preclean */);
{
TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
if (rp->processing_is_mt()) {
CMSRefProcTaskExecutor task_executor(*this);
rp->process_discovered_references(soft_ref_policy,
&_is_alive_closure,
rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor);
} else {
rp->process_discovered_references(soft_ref_policy,
&_is_alive_closure,
rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL);
@ -6163,8 +6155,8 @@ void CMSCollector::verify_ok_to_terminate() const {
#endif
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
"missing Printezis mark?");
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
"missing Printezis mark?");
HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
size_t size = pointer_delta(nextOneAddr + 1, addr);
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
@ -8302,8 +8294,29 @@ void CMSKeepAliveClosure::do_oop(oop obj) {
}
)
if (simulate_overflow || !_mark_stack->push(obj)) {
_collector->push_on_overflow_list(obj);
_collector->_ser_kac_ovflw++;
if (_concurrent_precleaning) {
// We dirty the overflown object and let the remark
// phase deal with it.
assert(_collector->overflow_list_is_empty(), "Error");
// In the case of object arrays, we need to dirty all of
// the cards that the object spans. No locking or atomics
// are needed since no one else can be mutating the mod union
// table.
if (obj->is_objArray()) {
size_t sz = obj->size();
HeapWord* end_card_addr =
(HeapWord*)round_to((intptr_t)(addr+sz), CardTableModRefBS::card_size);
MemRegion redirty_range = MemRegion(addr, end_card_addr);
assert(!redirty_range.is_empty(), "Arithmetical tautology");
_collector->_modUnionTable.mark_range(redirty_range);
} else {
_collector->_modUnionTable.mark(addr);
}
_collector->_ser_kac_preclean_ovflw++;
} else {
_collector->push_on_overflow_list(obj);
_collector->_ser_kac_ovflw++;
}
}
}
}
@ -8400,6 +8413,8 @@ const char* CMSExpansionCause::to_string(CMSExpansionCause::Cause cause) {
void CMSDrainMarkingStackClosure::do_void() {
// the max number to take from overflow list at a time
const size_t num = _mark_stack->capacity()/4;
assert(!_concurrent_precleaning || _collector->overflow_list_is_empty(),
"Overflow list should be NULL during concurrent phases");
while (!_mark_stack->isEmpty() ||
// if stack is empty, check the overflow list
_collector->take_from_overflow_list(num, _mark_stack)) {

View File

@ -592,6 +592,7 @@ class CMSCollector: public CHeapObj {
size_t _ser_pmc_preclean_ovflw;
size_t _ser_pmc_remark_ovflw;
size_t _par_pmc_remark_ovflw;
size_t _ser_kac_preclean_ovflw;
size_t _ser_kac_ovflw;
size_t _par_kac_ovflw;
NOT_PRODUCT(size_t _num_par_pushes;)
@ -1749,21 +1750,30 @@ class SweepClosure: public BlkClosureCareful {
// work-routine/closure used to complete transitive
// marking of objects as live after a certain point
// in which an initial set has been completely accumulated.
// This closure is currently used both during the final
// remark stop-world phase, as well as during the concurrent
// precleaning of the discovered reference lists.
class CMSDrainMarkingStackClosure: public VoidClosure {
CMSCollector* _collector;
MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
CMSKeepAliveClosure* _keep_alive;
bool _concurrent_precleaning;
public:
CMSDrainMarkingStackClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
CMSKeepAliveClosure* keep_alive):
CMSKeepAliveClosure* keep_alive,
bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_keep_alive(keep_alive) { }
_keep_alive(keep_alive),
_concurrent_precleaning(cpc) {
assert(_concurrent_precleaning == _keep_alive->concurrent_precleaning(),
"Mismatch");
}
void do_void();
};

View File

@ -811,6 +811,7 @@ void ConcurrentMark::checkpointRootsInitialPost() {
ReferenceProcessor* rp = g1h->ref_processor();
rp->verify_no_references_recorded();
rp->enable_discovery(); // enable ("weak") refs discovery
rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
@ -1829,32 +1830,21 @@ class G1CMDrainMarkingStackClosure: public VoidClosure {
void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
ReferencePolicy* soft_ref_policy;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
ReferenceProcessor* rp = g1h->ref_processor();
// Process weak references.
if (clear_all_soft_refs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif
}
rp->setup_policy(clear_all_soft_refs);
assert(_markStack.isEmpty(), "mark stack should be empty");
G1CollectedHeap* g1 = G1CollectedHeap::heap();
G1CMIsAliveClosure g1IsAliveClosure(g1);
G1CMKeepAliveClosure g1KeepAliveClosure(g1, this, nextMarkBitMap());
G1CMIsAliveClosure g1IsAliveClosure (g1h);
G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap());
G1CMDrainMarkingStackClosure
g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack,
&g1KeepAliveClosure);
// XXXYYY Also: copy the parallel ref processing code from CMS.
ReferenceProcessor* rp = g1->ref_processor();
rp->process_discovered_references(soft_ref_policy,
&g1IsAliveClosure,
rp->process_discovered_references(&g1IsAliveClosure,
&g1KeepAliveClosure,
&g1DrainMarkingStackClosure,
NULL);

View File

@ -891,6 +891,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_soft_refs);
// Do collection work
{
@ -2463,7 +2464,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
// We want to turn off ref discovere, if necessary, and turn it back on
// We want to turn off ref discovery, if necessary, and turn it back on
// on again later if we do.
bool was_enabled = ref_processor()->discovery_enabled();
if (was_enabled) ref_processor()->disable_discovery();

View File

@ -33,8 +33,9 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
// hook up weak ref data so it can be used during Mark-Sweep
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
GenMarkSweep::_ref_processor = rp;
assert(rp != NULL, "should be non-NULL");
GenMarkSweep::_ref_processor = rp;
rp->setup_policy(clear_all_softrefs);
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
@ -121,23 +122,12 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
&GenMarkSweep::follow_root_closure);
// Process reference objects found during marking
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif
}
assert(soft_ref_policy != NULL,"No soft reference policy");
GenMarkSweep::ref_processor()->process_discovered_references(
soft_ref_policy,
&GenMarkSweep::is_alive,
&GenMarkSweep::keep_alive,
&GenMarkSweep::follow_stack_closure,
NULL);
ReferenceProcessor* rp = GenMarkSweep::ref_processor();
rp->setup_policy(clear_all_softrefs);
rp->process_discovered_references(&GenMarkSweep::is_alive,
&GenMarkSweep::keep_alive,
&GenMarkSweep::follow_stack_closure,
NULL);
// Follow system dictionary roots and unload classes
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);

View File

@ -759,17 +759,12 @@ void ParNewGeneration::collect(bool full,
thread_state_set.steals(),
thread_state_set.pops()+thread_state_set.steals());
}
assert(thread_state_set.pushes() == thread_state_set.pops() + thread_state_set.steals(),
assert(thread_state_set.pushes() == thread_state_set.pops()
+ thread_state_set.steals(),
"Or else the queues are leaky.");
// For now, process discovered weak refs sequentially.
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
// Process (weak) reference objects found during scavenge.
ReferenceProcessor* rp = ref_processor();
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
KeepAliveClosure keep_alive(&scan_weak_ref);
@ -778,18 +773,17 @@ void ParNewGeneration::collect(bool full,
set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
&scan_without_gc_barrier, &scan_with_gc_barrier);
if (ref_processor()->processing_is_mt()) {
rp->setup_policy(clear_all_soft_refs);
if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
&task_executor);
rp->process_discovered_references(&is_alive, &keep_alive,
&evacuate_followers, &task_executor);
} else {
thread_state_set.flush();
gch->set_par_threads(0); // 0 ==> non-parallel.
gch->save_marks();
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
NULL);
rp->process_discovered_references(&is_alive, &keep_alive,
&evacuate_followers, NULL);
}
if (!promotion_failed()) {
// Swap the survivor spaces.
@ -851,14 +845,14 @@ void ParNewGeneration::collect(bool full,
SpecializationStats::print();
ref_processor()->set_enqueuing_is_done(true);
if (ref_processor()->processing_is_mt()) {
rp->set_enqueuing_is_done(true);
if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
ref_processor()->enqueue_discovered_references(&task_executor);
rp->enqueue_discovered_references(&task_executor);
} else {
ref_processor()->enqueue_discovered_references(NULL);
rp->enqueue_discovered_references(NULL);
}
ref_processor()->verify_no_references_recorded();
rp->verify_no_references_recorded();
}
static int sum;
@ -1211,7 +1205,7 @@ ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
int n = 0;
while (cur != NULL) {
oop obj_to_push = cur->forwardee();
oop next = oop(cur->klass());
oop next = oop(cur->klass_or_null());
cur->set_klass(obj_to_push->klass());
if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
obj_to_push = cur;

View File

@ -172,6 +172,7 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_softrefs);
mark_sweep_phase1(clear_all_softrefs);
@ -517,20 +518,9 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
// Process reference objects found during marking
{
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL,"No soft reference policy");
ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), mark_and_push_closure(),
follow_stack_closure(), NULL);
is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL);
}
// Follow system dictionary roots and unload classes

View File

@ -1578,6 +1578,7 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
ref_processor()->setup_policy(maximum_heap_compaction);
bool marked_for_unloading = false;
@ -1894,26 +1895,14 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
// Process reference objects found during marking
{
TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
ReferencePolicy *soft_ref_policy;
if (maximum_heap_compaction) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL, "No soft reference policy");
if (ref_processor()->processing_is_mt()) {
RefProcTaskExecutor task_executor;
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
&follow_stack_closure, &task_executor);
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
&task_executor);
} else {
ref_processor()->process_discovered_references(
soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
&follow_stack_closure, NULL);
is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
}
}

View File

@ -330,6 +330,7 @@ bool PSScavenge::invoke_no_policy() {
COMPILER2_PRESENT(DerivedPointerTable::clear());
reference_processor()->enable_discovery();
reference_processor()->setup_policy(false);
// We track how much was promoted to the next generation for
// the AdaptiveSizePolicy.
@ -394,24 +395,16 @@ bool PSScavenge::invoke_no_policy() {
// Process reference objects discovered during scavenge
{
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
reference_processor()->setup_policy(false); // not always_clear
PSKeepAliveClosure keep_alive(promotion_manager);
PSEvacuateFollowersClosure evac_followers(promotion_manager);
assert(soft_ref_policy != NULL,"No soft reference policy");
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->process_discovered_references(
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
&task_executor);
&_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
} else {
reference_processor()->process_discovered_references(
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
NULL);
&_is_alive_closure, &keep_alive, &evac_followers, NULL);
}
}

View File

@ -414,9 +414,20 @@ size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) {
if (limit > 0) {
limit = round_down(limit, page_size());
if (chunk_size > current_chunk_size(i)) {
chunk_size = MIN2((off_t)chunk_size, (off_t)current_chunk_size(i) + (off_t)limit);
size_t upper_bound = pages_available * page_size();
if (upper_bound > limit &&
current_chunk_size(i) < upper_bound - limit) {
// The resulting upper bound should not exceed the available
// amount of memory (pages_available * page_size()).
upper_bound = current_chunk_size(i) + limit;
}
chunk_size = MIN2(chunk_size, upper_bound);
} else {
chunk_size = MAX2((off_t)chunk_size, (off_t)current_chunk_size(i) - (off_t)limit);
size_t lower_bound = page_size();
if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
lower_bound = current_chunk_size(i) - limit;
}
chunk_size = MAX2(chunk_size, lower_bound);
}
}
assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");

View File

@ -3435,6 +3435,7 @@ referenceProcessor.cpp referenceProcessor.hpp
referenceProcessor.cpp systemDictionary.hpp
referenceProcessor.hpp instanceRefKlass.hpp
referenceProcessor.hpp referencePolicy.hpp
reflection.cpp arguments.hpp
reflection.cpp handles.inline.hpp

View File

@ -540,14 +540,6 @@ void DefNewGeneration::collect(bool full,
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
// Weak refs.
// FIXME: Are these storage leaks, or are they resource objects?
#ifdef COMPILER2
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
#else
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
// Not very pretty.
CollectorPolicy* cp = gch->collector_policy();
@ -574,8 +566,10 @@ void DefNewGeneration::collect(bool full,
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL);
ReferenceProcessor* rp = ref_processor();
rp->setup_policy(clear_all_soft_refs);
rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
NULL);
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);

View File

@ -525,8 +525,9 @@ void GenCollectedHeap::do_collection(bool full,
if (rp->discovery_is_atomic()) {
rp->verify_no_references_recorded();
rp->enable_discovery();
rp->setup_policy(clear_all_soft_refs);
} else {
// collect() will enable discovery as appropriate
// collect() below will enable discovery as appropriate
}
_gens[i]->collect(full, clear_all_soft_refs, size, is_tlab);
if (!rp->enqueuing_is_done()) {

View File

@ -31,8 +31,9 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
_ref_processor = rp;
assert(rp != NULL, "should be non-NULL");
_ref_processor = rp;
rp->setup_policy(clear_all_softrefs);
TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
@ -245,20 +246,9 @@ void GenMarkSweep::mark_sweep_phase1(int level,
// Process reference objects found during marking
{
ReferencePolicy *soft_ref_policy;
if (clear_all_softrefs) {
soft_ref_policy = new AlwaysClearPolicy();
} else {
#ifdef COMPILER2
soft_ref_policy = new LRUMaxHeapPolicy();
#else
soft_ref_policy = new LRUCurrentHeapPolicy();
#endif // COMPILER2
}
assert(soft_ref_policy != NULL,"No soft reference policy");
ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
soft_ref_policy, &is_alive, &keep_alive,
&follow_stack_closure, NULL);
&is_alive, &keep_alive, &follow_stack_closure, NULL);
}
// Follow system dictionary roots and unload classes

View File

@ -26,6 +26,11 @@
# include "incls/_referencePolicy.cpp.incl"
LRUCurrentHeapPolicy::LRUCurrentHeapPolicy() {
setup();
}
// Capture state (of-the-VM) information needed to evaluate the policy
void LRUCurrentHeapPolicy::setup() {
_max_interval = (Universe::get_heap_free_at_last_gc() / M) * SoftRefLRUPolicyMSPerMB;
assert(_max_interval >= 0,"Sanity check");
}
@ -47,6 +52,11 @@ bool LRUCurrentHeapPolicy::should_clear_reference(oop p) {
/////////////////////// MaxHeap //////////////////////
LRUMaxHeapPolicy::LRUMaxHeapPolicy() {
setup();
}
// Capture state (of-the-VM) information needed to evaluate the policy
void LRUMaxHeapPolicy::setup() {
size_t max_heap = MaxHeapSize;
max_heap -= Universe::get_heap_used_at_last_gc();
max_heap /= M;

View File

@ -26,9 +26,11 @@
// should be cleared.
class ReferencePolicy : public ResourceObj {
class ReferencePolicy : public CHeapObj {
public:
virtual bool should_clear_reference(oop p) { ShouldNotReachHere(); return true; }
// Capture state (of-the-VM) information needed to evaluate the policy
virtual void setup() { /* do nothing */ }
};
class NeverClearPolicy : public ReferencePolicy {
@ -48,6 +50,8 @@ class LRUCurrentHeapPolicy : public ReferencePolicy {
public:
LRUCurrentHeapPolicy();
// Capture state (of-the-VM) information needed to evaluate the policy
void setup();
bool should_clear_reference(oop p);
};
@ -58,5 +62,7 @@ class LRUMaxHeapPolicy : public ReferencePolicy {
public:
LRUMaxHeapPolicy();
// Capture state (of-the-VM) information needed to evaluate the policy
void setup();
bool should_clear_reference(oop p);
};

View File

@ -25,6 +25,11 @@
# include "incls/_precompiled.incl"
# include "incls/_referenceProcessor.cpp.incl"
ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
oop ReferenceProcessor::_sentinelRef = NULL;
const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
// List of discovered references.
class DiscoveredList {
public:
@ -47,7 +52,9 @@ public:
}
bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); }
size_t length() { return _len; }
void set_length(size_t len) { _len = len; }
void set_length(size_t len) { _len = len; }
void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); }
void dec_length(size_t dec) { _len -= dec; }
private:
// Set value depending on UseCompressedOops. This could be a template class
// but then we have to fix all the instantiations and declarations that use this class.
@ -56,10 +63,6 @@ private:
size_t _len;
};
oop ReferenceProcessor::_sentinelRef = NULL;
const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
void referenceProcessor_init() {
ReferenceProcessor::init_statics();
}
@ -80,6 +83,12 @@ void ReferenceProcessor::init_statics() {
}
assert(_sentinelRef != NULL && _sentinelRef->is_oop(),
"Just constructed it!");
_always_clear_soft_ref_policy = new AlwaysClearPolicy();
_default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
NOT_COMPILER2(LRUCurrentHeapPolicy());
if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
vm_exit_during_initialization("Could not allocate reference policy object");
}
guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
RefDiscoveryPolicy == ReferentBasedDiscovery,
"Unrecongnized RefDiscoveryPolicy");
@ -106,6 +115,7 @@ ReferenceProcessor::create_ref_processor(MemRegion span,
vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
}
rp->set_is_alive_non_header(is_alive_non_header);
rp->setup_policy(false /* default soft ref policy */);
return rp;
}
@ -192,7 +202,6 @@ void ReferenceProcessor::update_soft_ref_master_clock() {
}
void ReferenceProcessor::process_discovered_references(
ReferencePolicy* policy,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
@ -207,7 +216,7 @@ void ReferenceProcessor::process_discovered_references(
// Soft references
{
TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
process_discovered_reflist(_discoveredSoftRefs, policy, true,
process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
is_alive, keep_alive, complete_gc, task_executor);
}
@ -436,13 +445,13 @@ public:
// The "allow_null_referent" argument tells us to allow for the possibility
// of a NULL referent in the discovered Reference object. This typically
// happens in the case of concurrent collectors that may have done the
// discovery concurrently or interleaved with mutator execution.
// discovery concurrently, or interleaved, with mutator execution.
inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent));
// Move to the next discovered reference.
inline void next();
// Remove the current reference from the list and move to the next.
// Remove the current reference from the list
inline void remove();
// Make the Reference object active again.
@ -476,7 +485,6 @@ public:
inline size_t removed() const { return _removed; }
)
private:
inline void move_to_next();
private:
@ -553,7 +561,7 @@ inline void DiscoveredListIterator::remove() {
oopDesc::store_heap_oop((oop*)_prev_next, _next);
}
NOT_PRODUCT(_removed++);
move_to_next();
_refs_list.dec_length(1);
}
inline void DiscoveredListIterator::move_to_next() {
@ -591,12 +599,13 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// Remove Reference object from list
iter.remove();
// Make the Reference object active again
iter.make_active();
// keep the referent around
iter.make_referent_alive();
// Remove Reference object from list
iter.remove();
iter.move_to_next();
} else {
iter.next();
}
@ -629,12 +638,13 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// The referent is reachable after all.
// Remove Reference object from list.
iter.remove();
// Update the referent pointer as necessary: Note that this
// should not entail any recursive marking because the
// referent must already have been traversed.
iter.make_referent_alive();
// Remove Reference object from list
iter.remove();
iter.move_to_next();
} else {
iter.next();
}
@ -670,6 +680,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
} else {
keep_alive->do_oop((oop*)next_addr);
}
iter.move_to_next();
} else {
iter.next();
}
@ -832,9 +843,9 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[])
}
java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head());
ref_lists[to_idx].set_head(move_head);
ref_lists[to_idx].set_length(ref_lists[to_idx].length() + refs_to_move);
ref_lists[to_idx].inc_length(refs_to_move);
ref_lists[from_idx].set_head(new_head);
ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move);
ref_lists[from_idx].dec_length(refs_to_move);
} else {
++to_idx;
}
@ -923,7 +934,6 @@ void ReferenceProcessor::clean_up_discovered_references() {
void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
assert(!discovery_is_atomic(), "Else why call this method?");
DiscoveredListIterator iter(refs_list, NULL, NULL);
size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop next = java_lang_ref_Reference::next(iter.obj());
@ -941,12 +951,11 @@ void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list)
)
// Remove Reference object from list
iter.remove();
--length;
iter.move_to_next();
} else {
iter.next();
}
}
refs_list.set_length(length);
NOT_PRODUCT(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print(
@ -1024,7 +1033,7 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list,
// We have separate lists for enqueueing so no synchronization
// is necessary.
refs_list.set_head(obj);
refs_list.set_length(refs_list.length() + 1);
refs_list.inc_length(1);
if (_discovered_list_needs_barrier) {
_bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
}
@ -1090,15 +1099,28 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
// reachable.
if (is_alive_non_header() != NULL) {
oop referent = java_lang_ref_Reference::referent(obj);
// We'd like to assert the following:
// assert(referent != NULL, "Refs with null referents already filtered");
// However, since this code may be executed concurrently with
// mutators, which can clear() the referent, it is not
// guaranteed that the referent is non-NULL.
// In the case of non-concurrent discovery, the last
// disjunct below should hold. It may not hold in the
// case of concurrent discovery because mutators may
// concurrently clear() a Reference.
assert(UseConcMarkSweepGC || UseG1GC || referent != NULL,
"Refs with null referents already filtered");
if (is_alive_non_header()->do_object_b(referent)) {
return false; // referent is reachable
}
}
if (rt == REF_SOFT) {
// For soft refs we can decide now if these are not
// current candidates for clearing, in which case we
// can mark through them now, rather than delaying that
// to the reference-processing phase. Since all current
// time-stamp policies advance the soft-ref clock only
// at a major collection cycle, this is always currently
// accurate.
if (!_current_soft_ref_policy->should_clear_reference(obj)) {
return false;
}
}
HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
const oop discovered = java_lang_ref_Reference::discovered(obj);
@ -1168,7 +1190,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
_bs->write_ref_field((oop*)discovered_addr, current_head);
}
list->set_head(obj);
list->set_length(list->length() + 1);
list->inc_length(1);
}
// In the MT discovery case, it is currently possible to see
@ -1209,45 +1231,48 @@ void ReferenceProcessor::preclean_discovered_references(
TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Weak references
{
TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Final references
{
TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
if (yield->should_return()) {
return;
}
// Phantom references
{
TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
if (yield->should_return()) {
return;
}
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
@ -1256,9 +1281,12 @@ void ReferenceProcessor::preclean_discovered_references(
// Walk the given discovered ref list, and remove all reference objects
// whose referents are still alive, whose referents are NULL or which
// are not active (have a non-NULL next field). NOTE: For this to work
// correctly, refs discovery can not be happening concurrently with this
// step.
// are not active (have a non-NULL next field). NOTE: When we are
// thus precleaning the ref lists (which happens single-threaded today),
// we do not disable refs discovery to honour the correct semantics of
// java.lang.Reference. As a result, we need to be careful below
// that ref removal steps interleave safely with ref discovery steps
// (in this thread).
void
ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
BoolObjectClosure* is_alive,
@ -1266,7 +1294,6 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
VoidClosure* complete_gc,
YieldClosure* yield) {
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop obj = iter.obj();
@ -1281,7 +1308,6 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
}
// Remove Reference object from list
iter.remove();
--length;
// Keep alive its cohort.
iter.make_referent_alive();
if (UseCompressedOops) {
@ -1291,12 +1317,11 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
keep_alive->do_oop(next_addr);
}
iter.move_to_next();
} else {
iter.next();
}
}
refs_list.set_length(length);
// Close the reachable set
complete_gc->do_void();

View File

@ -23,7 +23,7 @@
*/
// ReferenceProcessor class encapsulates the per-"collector" processing
// of "weak" references for GC. The interface is useful for supporting
// of java.lang.Reference objects for GC. The interface is useful for supporting
// a generational abstraction, in particular when there are multiple
// generations that are being independently collected -- possibly
// concurrently and/or incrementally. Note, however, that the
@ -75,6 +75,14 @@ class ReferenceProcessor : public CHeapObj {
// all collectors but the CMS collector).
BoolObjectClosure* _is_alive_non_header;
// Soft ref clearing policies
// . the default policy
static ReferencePolicy* _default_soft_ref_policy;
// . the "clear all" policy
static ReferencePolicy* _always_clear_soft_ref_policy;
// . the current policy below is either one of the above
ReferencePolicy* _current_soft_ref_policy;
// The discovered ref lists themselves
// The MT'ness degree of the queues below
@ -90,6 +98,12 @@ class ReferenceProcessor : public CHeapObj {
DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; }
static oop sentinel_ref() { return _sentinelRef; }
static oop* adr_sentinel_ref() { return &_sentinelRef; }
ReferencePolicy* setup_policy(bool always_clear) {
_current_soft_ref_policy = always_clear ?
_always_clear_soft_ref_policy : _default_soft_ref_policy;
_current_soft_ref_policy->setup(); // snapshot the policy threshold
return _current_soft_ref_policy;
}
public:
// Process references with a certain reachability level.
@ -297,8 +311,7 @@ class ReferenceProcessor : public CHeapObj {
bool discover_reference(oop obj, ReferenceType rt);
// Process references found during GC (called by the garbage collector)
void process_discovered_references(ReferencePolicy* policy,
BoolObjectClosure* is_alive,
void process_discovered_references(BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor);

View File

@ -96,7 +96,7 @@ bool Universe::_bootstrapping = false;
bool Universe::_fully_initialized = false;
size_t Universe::_heap_capacity_at_last_gc;
size_t Universe::_heap_used_at_last_gc;
size_t Universe::_heap_used_at_last_gc = 0;
CollectedHeap* Universe::_collectedHeap = NULL;
address Universe::_heap_base = NULL;

View File

@ -92,7 +92,7 @@ inline void oopDesc::set_klass_to_list_ptr(oop k) {
// This is only to be used during GC, for from-space objects, so no
// barrier is needed.
if (UseCompressedOops) {
_metadata._compressed_klass = encode_heap_oop_not_null(k);
_metadata._compressed_klass = encode_heap_oop(k); // may be null (parnew overflow handling)
} else {
_metadata._klass = (klassOop)k;
}

View File

@ -395,7 +395,13 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
OptoReg::regname(OptoReg::c_frame_pointer),
regalloc->reg2offset(box_reg));
}
format_helper( regalloc, st, obj, "MON-OBJ[", i, &scobjs );
const char* obj_msg = "MON-OBJ[";
if (EliminateLocks) {
while( !box->is_BoxLock() ) box = box->in(1);
if (box->as_BoxLock()->is_eliminated())
obj_msg = "MON-OBJ(LOCK ELIMINATED)[";
}
format_helper( regalloc, st, obj, obj_msg, i, &scobjs );
}
for (i = 0; i < (uint)scobjs.length(); i++) {
@ -908,8 +914,9 @@ void SafePointNode::push_monitor(const FastLockNode *lock) {
add_req(lock->box_node());
add_req(lock->obj_node());
} else {
add_req(NULL);
add_req(NULL);
Node* top = Compile::current()->top();
add_req(top);
add_req(top);
}
jvms()->set_scloff(nextmon+MonitorEdges);
jvms()->set_endoff(req());
@ -1382,7 +1389,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//
// If we are locking an unescaped object, the lock/unlock is unnecessary
//
ConnectionGraph *cgr = Compile::current()->congraph();
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);
@ -1450,6 +1457,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Mark it eliminated to update any counters
lock->set_eliminated();
lock->set_coarsened();
}
} else if (result != NULL && ctrl->is_Region() &&
iter->_worklist.member(ctrl)) {
@ -1484,7 +1492,7 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//
// If we are unlocking an unescaped object, the lock/unlock is unnecessary.
//
ConnectionGraph *cgr = Compile::current()->congraph();
ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);

View File

@ -780,7 +780,8 @@ public:
//------------------------------AbstractLockNode-----------------------------------
class AbstractLockNode: public CallNode {
private:
bool _eliminate; // indicates this lock can be safely eliminated
bool _eliminate; // indicates this lock can be safely eliminated
bool _coarsened; // indicates this lock was coarsened
#ifndef PRODUCT
NamedCounter* _counter;
#endif
@ -801,6 +802,7 @@ protected:
public:
AbstractLockNode(const TypeFunc *tf)
: CallNode(tf, NULL, TypeRawPtr::BOTTOM),
_coarsened(false),
_eliminate(false)
{
#ifndef PRODUCT
@ -819,6 +821,9 @@ public:
// mark node as eliminated and update the counter if there is one
void set_eliminated();
bool is_coarsened() { return _coarsened; }
void set_coarsened() { _coarsened = true; }
// locking does not modify its arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}

View File

@ -1532,11 +1532,6 @@ void Compile::Optimize() {
if (failing()) return;
// get rid of the connection graph since it's information is not
// updated by optimizations
_congraph = NULL;
// Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc.

View File

@ -199,7 +199,8 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform
es = ptnode_adr(idx)->escape_state();
// if we have already computed a value, return it
if (es != PointsToNode::UnknownEscape)
if (es != PointsToNode::UnknownEscape &&
ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
return es;
// PointsTo() calls n->uncast() which can return a new ideal node.

View File

@ -44,10 +44,15 @@ BoxLockNode::BoxLockNode( int slot ) : Node( Compile::current()->root() ),
_inmask.Insert(reg);
}
//-----------------------------hash--------------------------------------------
uint BoxLockNode::hash() const {
return Node::hash() + _slot + (_is_eliminated ? Compile::current()->fixed_slots() : 0);
}
//------------------------------cmp--------------------------------------------
uint BoxLockNode::cmp( const Node &n ) const {
const BoxLockNode &bn = (const BoxLockNode &)n;
return bn._slot == _slot;
return bn._slot == _slot && bn._is_eliminated == _is_eliminated;
}
OptoReg::Name BoxLockNode::stack_slot(Node* box_node) {

View File

@ -36,7 +36,7 @@ public:
virtual const RegMask &in_RegMask(uint) const;
virtual const RegMask &out_RegMask() const;
virtual uint size_of() const;
virtual uint hash() const { return Node::hash() + _slot; }
virtual uint hash() const;
virtual uint cmp( const Node &n ) const;
virtual const class Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
virtual uint ideal_reg() const { return Op_RegP; }

View File

@ -59,7 +59,7 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
for (uint i = old_dbg_start; i < oldcall->req(); i++) {
Node* old_in = oldcall->in(i);
// Clone old SafePointScalarObjectNodes, adjusting their field contents.
if (old_in->is_SafePointScalarObject()) {
if (old_in != NULL && old_in->is_SafePointScalarObject()) {
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
uint old_unique = C->unique();
Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
@ -1509,21 +1509,63 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
if (!alock->is_eliminated()) {
return false;
}
// Mark the box lock as eliminated if all correspondent locks are eliminated
// to construct correct debug info.
BoxLockNode* box = alock->box_node()->as_BoxLock();
if (!box->is_eliminated()) {
bool eliminate = true;
for (DUIterator_Fast imax, i = box->fast_outs(imax); i < imax; i++) {
Node *lck = box->fast_out(i);
if (lck->is_Lock() && !lck->as_AbstractLock()->is_eliminated()) {
eliminate = false;
break;
}
}
if (eliminate)
box->set_eliminated();
}
if (alock->is_Lock() && !alock->is_coarsened()) {
// Create new "eliminated" BoxLock node and use it
// in monitor debug info for the same object.
BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
Node* obj = alock->obj_node();
if (!oldbox->is_eliminated()) {
BoxLockNode* newbox = oldbox->clone()->as_BoxLock();
newbox->set_eliminated();
transform_later(newbox);
// Replace old box node with new box for all users
// of the same object.
for (uint i = 0; i < oldbox->outcnt();) {
bool next_edge = true;
Node* u = oldbox->raw_out(i);
if (u == alock) {
i++;
continue; // It will be removed below
}
if (u->is_Lock() &&
u->as_Lock()->obj_node() == obj &&
// oldbox could be referenced in debug info also
u->as_Lock()->box_node() == oldbox) {
assert(u->as_Lock()->is_eliminated(), "sanity");
_igvn.hash_delete(u);
u->set_req(TypeFunc::Parms + 1, newbox);
next_edge = false;
#ifdef ASSERT
} else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) {
assert(u->as_Unlock()->is_eliminated(), "sanity");
#endif
}
// Replace old box in monitor debug info.
if (u->is_SafePoint() && u->as_SafePoint()->jvms()) {
SafePointNode* sfn = u->as_SafePoint();
JVMState* youngest_jvms = sfn->jvms();
int max_depth = youngest_jvms->depth();
for (int depth = 1; depth <= max_depth; depth++) {
JVMState* jvms = youngest_jvms->of_depth(depth);
int num_mon = jvms->nof_monitors();
// Loop over monitors
for (int idx = 0; idx < num_mon; idx++) {
Node* obj_node = sfn->monitor_obj(jvms, idx);
Node* box_node = sfn->monitor_box(jvms, idx);
if (box_node == oldbox && obj_node == obj) {
int j = jvms->monitor_box_offset(idx);
_igvn.hash_delete(u);
u->set_req(j, newbox);
next_edge = false;
}
} // for (int idx = 0;
} // for (int depth = 1;
} // if (u->is_SafePoint()
if (next_edge) i++;
} // for (uint i = 0; i < oldbox->outcnt();)
} // if (!oldbox->is_eliminated())
} // if (alock->is_Lock() && !lock->is_coarsened())
#ifndef PRODUCT
if (PrintEliminateLocks) {
@ -1562,6 +1604,15 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
_igvn.subsume_node(ctrlproj, fallthroughproj);
_igvn.hash_delete(memproj);
_igvn.subsume_node(memproj, memproj_fallthrough);
// Delete FastLock node also if this Lock node is unique user
// (a loop peeling may clone a Lock node).
Node* flock = alock->as_Lock()->fastlock_node();
if (flock->outcnt() == 1) {
assert(flock->unique_out() == alock, "sanity");
_igvn.hash_delete(flock);
_igvn.subsume_node(flock, top());
}
}
// Seach for MemBarRelease node and delete it also.
@ -1887,8 +1938,28 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
bool PhaseMacroExpand::expand_macro_nodes() {
if (C->macro_count() == 0)
return false;
// attempt to eliminate allocations
// First, attempt to eliminate locks
bool progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
Node * n = C->macro_node(i-1);
bool success = false;
debug_only(int old_macro_count = C->macro_count(););
if (n->is_AbstractLock()) {
success = eliminate_locking_node(n->as_AbstractLock());
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
}
}
// Next, attempt to eliminate allocations
progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
@ -1902,17 +1973,10 @@ bool PhaseMacroExpand::expand_macro_nodes() {
break;
case Node::Class_Lock:
case Node::Class_Unlock:
success = eliminate_locking_node(n->as_AbstractLock());
assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
break;
default:
if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
} else {
assert(false, "unknown node type in macro list");
}
assert(false, "unknown node type in macro list");
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;

View File

@ -849,10 +849,8 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
// Loop over monitors and insert into array
for(idx = 0; idx < num_mon; idx++) {
// Grab the node that defines this monitor
Node* box_node;
Node* obj_node;
box_node = sfn->monitor_box(jvms, idx);
obj_node = sfn->monitor_obj(jvms, idx);
Node* box_node = sfn->monitor_box(jvms, idx);
Node* obj_node = sfn->monitor_obj(jvms, idx);
// Create ScopeValue for object
ScopeValue *scval = NULL;
@ -890,6 +888,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
Location basic_lock = Location::new_stk_loc(Location::normal,_regalloc->reg2offset(box_reg));
while( !box_node->is_BoxLock() ) box_node = box_node->in(1);
monarray->append(new MonitorValue(scval, basic_lock, box_node->as_BoxLock()->is_eliminated()));
}

View File

@ -342,6 +342,9 @@ class CommandLineFlags {
product(bool, UseNUMA, false, \
"Use NUMA if available") \
\
product(bool, ForceNUMA, false, \
"Force NUMA optimizations on single-node/UMA systems") \
\
product(intx, NUMAChunkResizeWeight, 20, \
"Percentage (0-100) used to weight the current sample when " \
"computing exponentially decaying average for " \
@ -1474,7 +1477,7 @@ class CommandLineFlags {
"CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence" \
" ratio") \
\
product(bool, CMSPrecleanRefLists1, false, \
product(bool, CMSPrecleanRefLists1, true, \
"Preclean ref lists during (initial) preclean phase") \
\
product(bool, CMSPrecleanRefLists2, false, \

View File

@ -65,8 +65,10 @@
// COMPILER2 variant
#ifdef COMPILER2
#define COMPILER2_PRESENT(code) code
#define NOT_COMPILER2(code)
#else // COMPILER2
#define COMPILER2_PRESENT(code)
#define NOT_COMPILER2(code) code
#endif // COMPILER2

View File

@ -0,0 +1,55 @@
/*
* Copyright 2008 Sun Microsystems, Inc. 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6756768
* @summary C1 generates invalid code
*
* @run main/othervm -Xcomp Test6756768
*/
class Test6756768a
{
static boolean var_1 = true;
}
final class Test6756768b
{
static boolean var_24 = false;
static int var_25 = 0;
static boolean var_temp1 = Test6756768a.var_1 = false;
}
public final class Test6756768 extends Test6756768a
{
final static int var = var_1 ^ (Test6756768b.var_24 ? var_1 : var_1) ? Test6756768b.var_25 : 1;
static public void main(String[] args) {
if (var != 0) {
throw new InternalError("var = " + var);
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2008 Sun Microsystems, Inc. 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6756768
* @summary C1 generates invalid code
*
* @run main/othervm -Xcomp Test6756768_2
*/
class Test6756768_2a {
static int var = ++Test6756768_2.var;
}
public class Test6756768_2 {
static int var = 1;
static Object d2 = null;
static void test_static_field() {
int v = var;
int v2 = Test6756768_2a.var;
int v3 = var;
var = v3;
}
public static void main(String[] args) {
var = 1;
test_static_field();
if (var != 2) {
throw new InternalError();
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2008 Sun Microsystems, Inc. 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
/*
* @test
* @bug 6775880
* @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
* @compile -source 1.4 -target 1.4 Test.java
* @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
*/
public class Test {
int cnt;
int b[];
String s;
String test() {
String res="";
for (int i=0; i < cnt; i++) {
if (i != 0) {
res = res +".";
}
res = res + b[i];
}
return res;
}
public static void main(String[] args) {
Test t = new Test();
t.cnt = 3;
t.b = new int[3];
t.b[0] = 0;
t.b[1] = 1;
t.b[2] = 2;
int j=0;
t.s = "";
for (int i=0; i<10001; i++) {
t.s = "c";
t.s = t.test();
}
System.out.println("After s=" + t.s);
}
}

View File

@ -14,3 +14,4 @@ c84ca638db42a8b6b227b4e3b63bca192c5ca634 jdk7-b36
af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37
e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38
831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39
54946f466e2c047c44c903f1bec400b685c2508e jdk7-b40

View File

@ -14,3 +14,4 @@ f60187f44a0d62906a5e2f6bd0989b5b24c1ca1e jdk7-b36
a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37
9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38
077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39
70a6ac6dd737fe45c2fadb57646195b2b4fe269d jdk7-b40

View File

@ -14,3 +14,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39
2201dad60231a3c3e0346e3a0250d69ca3b71fd4 jdk7-b40

View File

@ -69,9 +69,9 @@ public class ServiceName {
/**
* The version of the JMX specification implemented by this product.
* <BR>
* The value is <CODE>1.4</CODE>.
* The value is <CODE>2.0</CODE>.
*/
public static final String JMX_SPEC_VERSION = "1.4";
public static final String JMX_SPEC_VERSION = "2.0";
/**
* The vendor of the JMX specification implemented by this product.

View File

@ -41,7 +41,7 @@ public class EventParams {
@SuppressWarnings("cast") // cast for jdk 1.5
public static long getLeaseTimeout() {
long timeout = EventClient.DEFAULT_LEASE_TIMEOUT;
long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
try {
final GetPropertyAction act =
new GetPropertyAction(DEFAULT_LEASE_TIMEOUT);

View File

@ -29,6 +29,7 @@ import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
@ -143,9 +144,10 @@ public class LeaseManager {
private final Runnable callback;
private ScheduledFuture<?> scheduled; // If null, the lease has expired.
private static final ThreadFactory threadFactory =
new DaemonThreadFactory("JMX LeaseManager %d");
private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1,
new DaemonThreadFactory("JMX LeaseManager %d"));
= Executors.newScheduledThreadPool(1, threadFactory);
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");

View File

@ -55,9 +55,19 @@ import javax.management.namespace.JMXNamespaces;
import javax.management.namespace.MBeanServerSupport;
import javax.management.remote.IdentityMBeanServerForwarder;
/**
* <p>An {@link MBeanServerForwarder} that simulates the existence of a
* given MBean. Requests for that MBean, call it X, are intercepted by the
* forwarder, and requests for any other MBean are forwarded to the next
* forwarder in the chain. Requests such as queryNames which can span both the
* X and other MBeans are handled by merging the results for X with the results
* from the next forwarder, unless the "visible" parameter is false, in which
* case X is invisible to such requests.</p>
*/
public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
private final ObjectName mbeanName;
private final boolean visible;
private DynamicMBean mbean;
private MBeanServer mbeanMBS = new MBeanServerSupport() {
@ -85,10 +95,20 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
return null;
}
// This will only be called if mbeanName has an empty domain.
// In that case a getAttribute (e.g.) of that name will have the
// domain replaced by MBeanServerSupport with the default domain,
// so we must be sure that the default domain is empty too.
@Override
public String getDefaultDomain() {
return mbeanName.getDomain();
}
};
public SingleMBeanForwarder(ObjectName mbeanName, DynamicMBean mbean) {
public SingleMBeanForwarder(
ObjectName mbeanName, DynamicMBean mbean, boolean visible) {
this.mbeanName = mbeanName;
this.visible = visible;
setSingleMBean(mbean);
}
@ -213,8 +233,10 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
public String[] getDomains() {
TreeSet<String> domainSet =
new TreeSet<String>(Arrays.asList(super.getDomains()));
String[] domains = super.getDomains();
if (!visible)
return domains;
TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains));
domainSet.add(mbeanName.getDomain());
return domainSet.toArray(new String[domainSet.size()]);
}
@ -222,7 +244,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
public Integer getMBeanCount() {
Integer count = super.getMBeanCount();
if (!super.isRegistered(mbeanName))
if (visible && !super.isRegistered(mbeanName))
count++;
return count;
}
@ -284,7 +306,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
*/
private boolean applies(ObjectName pattern) {
// we know pattern is not null.
if (!pattern.apply(mbeanName))
if (!visible || !pattern.apply(mbeanName))
return false;
final String dompat = pattern.getDomain();
@ -306,10 +328,12 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
Set<ObjectInstance> names = super.queryMBeans(name, query);
if (name == null || applies(name) ) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryMBeans(name, query));
if (visible) {
if (name == null || applies(name) ) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryMBeans(name, query));
}
}
return names;
}
@ -317,10 +341,12 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
Set<ObjectName> names = super.queryNames(name, query);
if (name == null || applies(name)) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryNames(name, query));
if (visible) {
if (name == null || applies(name)) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryNames(name, query));
}
}
return names;
}

View File

@ -122,7 +122,7 @@ public final class JmxMBeanServer
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* instead.
* <p>
* By default, {@link MBeanServerInterceptor} are disabled. Use
* By default, interceptors are disabled. Use
* {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
* </ul>
* @param domain The default domain name used by this MBeanServer.
@ -239,7 +239,7 @@ public final class JmxMBeanServer
this.mBeanServerDelegateObject = delegate;
this.outerShell = outer;
final Repository repository = new Repository(domain,fairLock);
final Repository repository = new Repository(domain);
this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator,
repository);

View File

@ -1,354 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.event.EventClient;
import javax.management.event.EventClientDelegateMBean;
import javax.management.namespace.JMXNamespace;
import javax.management.namespace.JMXNamespaces;
import javax.management.remote.JMXAddressable;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;
/**
* A collection of methods that provide JMXConnector wrappers for
* JMXRemoteNamepaces underlying connectors.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public final class JMXNamespaceUtils {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
private static <K,V> Map<K,V> newWeakHashMap() {
return new WeakHashMap<K,V>();
}
/** There are no instances of this class */
private JMXNamespaceUtils() {
}
// returns un unmodifiable view of a map.
public static <K,V> Map<K,V> unmodifiableMap(Map<K,V> aMap) {
if (aMap == null || aMap.isEmpty())
return Collections.emptyMap();
return Collections.unmodifiableMap(aMap);
}
/**
* A base class that helps writing JMXConnectors that return
* MBeanServerConnection wrappers.
* This base class wraps an inner JMXConnector (the source), and preserve
* its caching policy. If a connection is cached in the source, its wrapper
* will be cached in this connector too.
* Author's note: rewriting this with java.lang.reflect.Proxy could be
* envisaged. It would avoid the combinatory sub-classing introduced by
* JMXAddressable.
* <p>
* Note: all the standard JMXConnector implementations are serializable.
* This implementation here is not. Should it be?
* I believe it must not be serializable unless it becomes
* part of a public API (either standard or officially exposed
* and supported in a documented com.sun package)
**/
static class JMXCachingConnector
implements JMXConnector {
// private static final long serialVersionUID = -2279076110599707875L;
final JMXConnector source;
// if this object is made serializable, then the variable below
// needs to become volatile transient and be lazyly-created...
private final
Map<MBeanServerConnection,MBeanServerConnection> connectionMap;
public JMXCachingConnector(JMXConnector source) {
this.source = checkNonNull(source, "source");
connectionMap = newWeakHashMap();
}
private MBeanServerConnection
getCached(MBeanServerConnection inner) {
return connectionMap.get(inner);
}
private MBeanServerConnection putCached(final MBeanServerConnection inner,
final MBeanServerConnection wrapper) {
if (inner == wrapper) return wrapper;
synchronized (this) {
final MBeanServerConnection concurrent =
connectionMap.get(inner);
if (concurrent != null) return concurrent;
connectionMap.put(inner,wrapper);
}
return wrapper;
}
public void addConnectionNotificationListener(NotificationListener
listener, NotificationFilter filter, Object handback) {
source.addConnectionNotificationListener(listener,filter,handback);
}
public void close() throws IOException {
source.close();
}
public void connect() throws IOException {
source.connect();
}
public void connect(Map<String,?> env) throws IOException {
source.connect(env);
}
public String getConnectionId() throws IOException {
return source.getConnectionId();
}
/**
* Preserve caching policy of the underlying connector.
**/
public MBeanServerConnection
getMBeanServerConnection() throws IOException {
final MBeanServerConnection inner =
source.getMBeanServerConnection();
final MBeanServerConnection cached = getCached(inner);
if (cached != null) return cached;
final MBeanServerConnection wrapper = wrap(inner);
return putCached(inner,wrapper);
}
public MBeanServerConnection
getMBeanServerConnection(Subject delegationSubject)
throws IOException {
final MBeanServerConnection wrapped =
source.getMBeanServerConnection(delegationSubject);
synchronized (this) {
final MBeanServerConnection cached = getCached(wrapped);
if (cached != null) return cached;
final MBeanServerConnection wrapper =
wrapWithSubject(wrapped,delegationSubject);
return putCached(wrapped,wrapper);
}
}
public void removeConnectionNotificationListener(
NotificationListener listener)
throws ListenerNotFoundException {
source.removeConnectionNotificationListener(listener);
}
public void removeConnectionNotificationListener(
NotificationListener l, NotificationFilter f,
Object handback) throws ListenerNotFoundException {
source.removeConnectionNotificationListener(l,f,handback);
}
/**
* This is the method that subclass will redefine. This method
* is called by {@code this.getMBeanServerConnection()}.
* {@code inner} is the connection returned by
* {@code source.getMBeanServerConnection()}.
**/
protected MBeanServerConnection wrap(MBeanServerConnection inner)
throws IOException {
return inner;
}
/**
* Subclass may also want to redefine this method.
* By default it calls wrap(inner). This method
* is called by {@code this.getMBeanServerConnection(Subject)}.
* {@code inner} is the connection returned by
* {@code source.getMBeanServerConnection(Subject)}.
**/
protected MBeanServerConnection wrapWithSubject(
MBeanServerConnection inner, Subject delegationSubject)
throws IOException {
return wrap(inner);
}
@Override
public String toString() {
if (source instanceof JMXAddressable) {
final JMXServiceURL address =
((JMXAddressable)source).getAddress();
if (address != null)
return address.toString();
}
return source.toString();
}
}
/**
* The name space connector can do 'cd'
**/
static class JMXNamespaceConnector extends JMXCachingConnector {
// private static final long serialVersionUID = -4813611540843020867L;
private final String toDir;
private final boolean closeable;
public JMXNamespaceConnector(JMXConnector source, String toDir,
boolean closeable) {
super(source);
this.toDir = toDir;
this.closeable = closeable;
}
@Override
public void close() throws IOException {
if (!closeable)
throw new UnsupportedOperationException("close");
else super.close();
}
@Override
protected MBeanServerConnection wrap(MBeanServerConnection wrapped)
throws IOException {
if (LOG.isLoggable(Level.FINER))
LOG.finer("Creating name space proxy connection for source: "+
"namespace="+toDir);
return JMXNamespaces.narrowToNamespace(wrapped,toDir);
}
@Override
public String toString() {
return "JMXNamespaces.narrowToNamespace("+
super.toString()+
", \""+toDir+"\")";
}
}
static class JMXEventConnector extends JMXCachingConnector {
// private static final long serialVersionUID = 4742659236340242785L;
JMXEventConnector(JMXConnector wrapped) {
super(wrapped);
}
@Override
protected MBeanServerConnection wrap(MBeanServerConnection inner)
throws IOException {
return EventClient.getEventClientConnection(inner);
}
@Override
public String toString() {
return "EventClient.withEventClient("+super.toString()+")";
}
}
static class JMXAddressableEventConnector extends JMXEventConnector
implements JMXAddressable {
// private static final long serialVersionUID = -9128520234812124712L;
JMXAddressableEventConnector(JMXConnector wrapped) {
super(wrapped);
}
public JMXServiceURL getAddress() {
return ((JMXAddressable)source).getAddress();
}
}
/**
* Creates a connector whose MBeamServerConnection will point to the
* given sub name space inside the source connector.
* @see JMXNamespace
**/
public static JMXConnector cd(final JMXConnector source,
final String toNamespace,
final boolean closeable)
throws IOException {
checkNonNull(source, "JMXConnector");
if (toNamespace == null || toNamespace.equals(""))
return source;
return new JMXNamespaceConnector(source,toNamespace,closeable);
}
/**
* Returns a JMX Connector that will use an {@link EventClient}
* to subscribe for notifications. If the server doesn't have
* an {@link EventClientDelegateMBean}, then the connector will
* use the legacy notification mechanism instead.
*
* @param source The underlying JMX Connector wrapped by the returned
* connector.
* @return A JMX Connector that will uses an {@link EventClient}, if
* available.
* @see EventClient#getEventClientConnection(MBeanServerConnection)
*/
public static JMXConnector withEventClient(final JMXConnector source) {
checkNonNull(source, "JMXConnector");
if (source instanceof JMXAddressable)
return new JMXAddressableEventConnector(source);
else
return new JMXEventConnector(source);
}
public static <T> T checkNonNull(T parameter, String name) {
if (parameter == null)
throw new IllegalArgumentException(name+" must not be null");
return parameter;
}
}

View File

@ -49,11 +49,6 @@ public class ObjectNameRouter {
final int tlen;
final boolean identity;
public ObjectNameRouter(String targetDirName) {
this(targetDirName,null);
}
/** Creates a new instance of ObjectNameRouter */
public ObjectNameRouter(final String remove, final String add) {
this.targetPrefix = (remove==null?"":remove);
@ -186,6 +181,4 @@ public class ObjectNameRouter {
b.append(NAMESPACE_SEPARATOR);
return b.toString();
}
}

View File

@ -31,7 +31,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServerConnection;
import javax.management.namespace.JMXNamespaces;
/**
@ -57,22 +56,14 @@ public class RoutingConnectionProxy
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
/**
* Creates a new instance of RoutingConnectionProxy
*/
public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir) {
this(source,sourceDir,"",false);
}
/**
* Creates a new instance of RoutingConnectionProxy
*/
public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir,
String targetDir,
boolean forwardsContext) {
super(source,sourceDir,targetDir,forwardsContext);
boolean probe) {
super(source, sourceDir, targetDir, probe);
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
@ -85,15 +76,13 @@ public class RoutingConnectionProxy
final String sourceNs = getSourceNamespace();
String wrapped = String.valueOf(source());
if ("".equals(targetNs)) {
if (forwardsContext)
wrapped = "ClientContext.withDynamicContext("+wrapped+")";
return "JMXNamespaces.narrowToNamespace("+
wrapped+", \""+
sourceNs+"\")";
}
return this.getClass().getSimpleName()+"("+wrapped+", \""+
sourceNs+"\", \""+
targetNs+"\", "+forwardsContext+")";
targetNs+"\")";
}
static final RoutingProxyFactory
@ -102,22 +91,16 @@ public class RoutingConnectionProxy
<MBeanServerConnection,RoutingConnectionProxy>() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source,
String sourcePath, String targetPath,
boolean forwardsContext) {
String sourcePath, String targetPath, boolean probe) {
return new RoutingConnectionProxy(source,sourcePath,
targetPath,forwardsContext);
}
public RoutingConnectionProxy newInstance(
MBeanServerConnection source, String sourcePath) {
return new RoutingConnectionProxy(source,sourcePath);
targetPath, probe);
}
};
public static MBeanServerConnection cd(MBeanServerConnection source,
String sourcePath) {
public static MBeanServerConnection cd(
MBeanServerConnection source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
source, sourcePath);
source, sourcePath, probe);
}
}

View File

@ -30,6 +30,7 @@ import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
@ -90,17 +91,9 @@ import javax.management.namespace.JMXNamespaces;
// targetNs=<encoded-context> // context must be removed from object name
// sourceNs="" // nothing to add...
//
// RoutingProxies can also be used on the client side to implement
// "withClientContext" operations. In that case, the boolean parameter
// 'forwards context' is set to true, targetNs is "", and sourceNS may
// also be "". When forwardsContext is true, the RoutingProxy dynamically
// creates an ObjectNameRouter for each operation - in order to dynamically add
// the context attached to the thread to the routing ObjectName. This is
// performed in the getObjectNameRouter() method.
//
// Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a
// factory method that can concatenate namespace pathes in order to
// factory method that can concatenate namespace paths in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
@ -146,25 +139,27 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
private final T source;
// The name space we're narrowing to (usually some name space in
// the source MBeanServerConnection
// the source MBeanServerConnection), e.g. "a" for the namespace
// "a//". This is empty in the case of ClientContext described above.
private final String sourceNs;
// The name space we pretend to be mounted in (usually "")
// The name space we pretend to be mounted in. This is empty except
// in the case of ClientContext described above (where it will be
// something like "jmx.context//foo=bar".
private final String targetNs;
// The name of the JMXNamespace that handles the source name space
private final ObjectName handlerName;
private final ObjectNameRouter router;
final boolean forwardsContext;
private volatile String defaultDomain = null;
/**
* Creates a new instance of RoutingProxy
*/
protected RoutingProxy(T source,
String sourceNs,
String targetNs,
boolean forwardsContext) {
String sourceNs,
String targetNs,
boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
@ -177,13 +172,17 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// System.err.println("sourceNs: "+sourceNs);
this.handlerName =
JMXNamespaces.getNamespaceObjectName(this.sourceNs);
try {
// System.err.println("handlerName: "+handlerName);
if (!source.isRegistered(handlerName))
throw new IllegalArgumentException(sourceNs +
": no such name space");
} catch (IOException x) {
throw new IllegalArgumentException("source stale: "+x,x);
if (probe) {
try {
if (!source.isRegistered(handlerName)) {
InstanceNotFoundException infe =
new InstanceNotFoundException(handlerName);
throw new IllegalArgumentException(sourceNs +
": no such name space", infe);
}
} catch (IOException x) {
throw new IllegalArgumentException("source stale: "+x,x);
}
}
}
this.source = source;
@ -191,7 +190,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
JMXNamespaces.normalizeNamespaceName(targetNs));
this.router =
new ObjectNameRouter(this.targetNs,this.sourceNs);
this.forwardsContext = forwardsContext;
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingProxy for " + this.sourceNs + " created");
@ -200,14 +198,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
@Override
public T source() { return source; }
ObjectNameRouter getObjectNameRouter() {
// TODO: uncomment this when contexts are added
// if (forwardsContext)
// return ObjectNameRouter.wrapWithContext(router);
// else
return router;
}
@Override
public ObjectName toSource(ObjectName targetName)
throws MalformedObjectNameException {
@ -222,8 +212,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
if (defaultDomain != null)
targetName = targetName.withDomain(defaultDomain);
}
final ObjectNameRouter r = getObjectNameRouter();
return r.toSourceContext(targetName,true);
return router.toSourceContext(targetName,true);
}
@Override
@ -243,8 +232,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
public ObjectName toTarget(ObjectName sourceName)
throws MalformedObjectNameException {
if (sourceName == null) return null;
final ObjectNameRouter r = getObjectNameRouter();
return r.toTargetContext(sourceName,false);
return router.toTargetContext(sourceName,false);
}
private Object getAttributeFromHandler(String attributeName)
@ -357,11 +345,8 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// instance.
static interface RoutingProxyFactory<T extends MBeanServerConnection,
R extends RoutingProxy<T>> {
R newInstance(T source,
String sourcePath, String targetPath,
boolean forwardsContext);
R newInstance(T source,
String sourcePath);
public R newInstance(
T source, String sourcePath, String targetPath, boolean probe);
}
// Performs a narrowDownToNamespace operation.
@ -377,7 +362,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
R cd(Class<R> routingProxyClass,
RoutingProxyFactory<T,R> factory,
T source, String sourcePath) {
T source, String sourcePath, boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast
@ -400,14 +385,13 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
return factory.newInstance(other.source(),path,"",
other.forwardsContext);
return factory.newInstance(other.source(), path, "", probe);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
return factory.newInstance(source,sourcePath);
return factory.newInstance(source, sourcePath, "", probe);
}
}

View File

@ -54,7 +54,6 @@ import javax.management.OperationsException;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
import javax.management.namespace.JMXNamespaces;
/**
* A RoutingServerProxy is an MBeanServer proxy that proxies a
@ -76,19 +75,11 @@ public class RoutingServerProxy
extends RoutingProxy<MBeanServer>
implements MBeanServer {
/**
* Creates a new instance of RoutingServerProxy
*/
public RoutingServerProxy(MBeanServer source,
String sourceNs) {
this(source,sourceNs,"",false);
}
public RoutingServerProxy(MBeanServer source,
String sourceNs,
String targetNs,
boolean forwardsContext) {
super(source,sourceNs,targetNs,forwardsContext);
boolean probe) {
super(source, sourceNs, targetNs, probe);
}
/**
@ -571,20 +562,15 @@ public class RoutingServerProxy
FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() {
public RoutingServerProxy newInstance(MBeanServer source,
String sourcePath, String targetPath,
boolean forwardsContext) {
return new RoutingServerProxy(source,sourcePath,
targetPath,forwardsContext);
}
public RoutingServerProxy newInstance(
MBeanServer source, String sourcePath) {
return new RoutingServerProxy(source,sourcePath);
String sourcePath, String targetPath, boolean probe) {
return new RoutingServerProxy(
source, sourcePath, targetPath, probe);
}
};
public static MBeanServer cd(MBeanServer source, String sourcePath) {
public static MBeanServer cd(
MBeanServer source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
source, sourcePath);
source, sourcePath, probe);
}
}

View File

@ -430,13 +430,11 @@ public class EventClientConnection implements InvocationHandler,
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
* @return the
* @return the MBeanServerConnection.
**/
public static MBeanServerConnection getEventConnectionFor(
MBeanServerConnection connection,
Callable<EventClient> eventClientFactory) {
// if c already uses an EventClient no need to create a new one.
//
if (connection instanceof EventClientFactory
&& eventClientFactory != null)
throw new IllegalArgumentException("connection already uses EventClient");

View File

@ -497,6 +497,10 @@ public class HttpsURLConnectionOldImpl
delegate.setFixedLengthStreamingMode(contentLength);
}
public void setFixedLengthStreamingMode(long contentLength) {
delegate.setFixedLengthStreamingMode(contentLength);
}
public void setChunkedStreamingMode (int chunklen) {
delegate.setChunkedStreamingMode(chunklen);
}

View File

@ -86,6 +86,8 @@ import sun.misc.HexDumpEncoder;
* the principal name from the configuration is used. In the
* case where the principal property is not set and the principal
* entry also does not exist, the user is prompted for the name.
* When this property of entry is set, and <code>useTicketCache</code>
* is set to true, only TGT belonging to this principal is used.
*
* <p> The following is a list of configuration options supported
* for <code>Krb5LoginModule</code>:
@ -101,18 +103,19 @@ import sun.misc.HexDumpEncoder;
* to false if you do not want this module to use the ticket cache.
* (Default is False).
* This module will
* search for the tickect
* search for the ticket
* cache in the following locations:
* For Windows 2000, it will use Local Security Authority (LSA) API
* to get the TGT. On Solaris and Linux
* On Solaris and Linux
* it will look for the ticket cache in /tmp/krb5cc_<code>uid</code>
* where the uid is numeric user
* identifier. If the ticket cache is
* not available in either of the above locations, or if we are on a
* different Windows platform, it will look for the cache as
* not available in the above location, or if we are on a
* Windows platform, it will look for the cache as
* {user.home}{file.separator}krb5cc_{user.name}.
* You can override the ticket cache location by using
* <code>ticketCache</code>
* <code>ticketCache</code>.
* For Windows, if a ticket cannot be retrieved from the file ticket cache,
* it will use Local Security Authority (LSA) API to get the TGT.
* <P>
* <dt><b><code>ticketCache</code></b>:</dt>
* <dd>Set this to the name of the ticket
@ -129,20 +132,20 @@ import sun.misc.HexDumpEncoder;
* <dt><b><code>doNotPrompt</code></b>:</dt>
* <dd>Set this to true if you do not want to be
* prompted for the password
* if credentials can
* not be obtained from the cache or keytab.(Default is false)
* If set to true authentication will fail if credentials can
* not be obtained from the cache or keytab.</dd>
* if credentials can not be obtained from the cache, the keytab,
* or through shared state.(Default is false)
* If set to true, credential must be obtained through cache, keytab,
* or shared state. Otherwise, authentication will fail.</dd>
* <P>
* <dt><b><code>useKeyTab</code></b>:</dt>
* <dd>Set this to true if you
* want the module to get the principal's key from the
* the keytab.(default value is False)
* If <code>keyatb</code>
* If <code>keytab</code>
* is not set then
* the module will locate the keytab from the
* Kerberos configuration file.</dd>
* If it is not specifed in the Kerberos configuration file
* Kerberos configuration file.
* If it is not specified in the Kerberos configuration file
* then it will look for the file
* <code>{user.home}{file.separator}</code>krb5.keytab.</dd>
* <P>
@ -210,20 +213,34 @@ import sun.misc.HexDumpEncoder;
* exist for the username and password in the shared
* state, or if authentication fails.
*
* clearPass if, true, this <code>LoginModule</code> clears the
* username and password stored in the module's shared
* state after both phases of authentication
* (login and commit) have completed.
* clearPass if, true, this LoginModule clears the
* username and password stored in the module's shared
* state after both phases of authentication
* (login and commit) have completed.
* </pre>
* <p>If the principal system property or key is already provided, the value of
* "javax.security.auth.login.name" in the shared state is ignored.
* <p>When multiple mechanisms to retrieve a ticket or key is provided, the
* preference order looks like this:
* <ol>
* <li>ticket cache
* <li>keytab
* <li>shared state
* <li>user prompt
* </ol>
* <p>Note that if any step fails, it will fallback to the next step.
* There's only one exception, it the shared state step fails and
* <code>useFirstPass</code>=true, no user prompt is made.
* <p>Examples of some configuration values for Krb5LoginModule in
* JAAS config file and the results are:
* <ul>
* <p> <code>doNotPrompt</code>=true;
* </ul>
* <p> This is an illegal combination since <code>useTicketCache</code>
* is not set and the user can not be prompted for the password.
* <p> This is an illegal combination since none of <code>useTicketCache</code>,
* <code>useKeyTab</code>, <code>useFirstPass</code> and <code>tryFirstPass</code>
* is set and the user can not be prompted for the password.
*<ul>
* <p> <code>ticketCache</code> = < filename >;
* <p> <code>ticketCache</code> = &lt;filename&gt;;
*</ul>
* <p> This is an illegal combination since <code>useTicketCache</code>
* is not set to true and the ticketCache is set. A configuration error
@ -240,9 +257,9 @@ import sun.misc.HexDumpEncoder;
*</ul>
* <p> This is an illegal combination since <code>storeKey</code> is set to
* true but the key can not be obtained either by prompting the user or from
* the keytab.A configuration error will occur.
* the keytab, or from the shared state. A configuration error will occur.
* <ul>
* <p> <code>keyTab</code> = < filename > <code>doNotPrompt</code>=true ;
* <p> <code>keyTab</code> = &lt;filename&gt; <code>doNotPrompt</code>=true ;
* </ul>
* <p>This is an illegal combination since useKeyTab is not set to true and
* the keyTab is set. A configuration error will occur.
@ -260,7 +277,7 @@ import sun.misc.HexDumpEncoder;
* with the principal and TGT. If the TGT is not available,
* do not prompt the user, instead fail the authentication.
* <ul>
* <p><code>principal</code>=< name ><code>useTicketCache</code> = true
* <p><code>principal</code>=&lt;name&gt;<code>useTicketCache</code> = true
* <code>doNotPrompt</code>=true;
*</ul>
* <p> Get the TGT from the default cache for the principal and populate the
@ -269,9 +286,9 @@ import sun.misc.HexDumpEncoder;
* authentication will fail.
* <ul>
* <p> <code>useTicketCache</code> = true
* <code>ticketCache</code>=< file name ><code>useKeyTab</code> = true
* <code> keyTab</code>=< keytab filename >
* <code>principal</code> = < principal name >
* <code>ticketCache</code>=&lt;file name&gt;<code>useKeyTab</code> = true
* <code> keyTab</code>=&lt;keytab filename&gt;
* <code>principal</code> = &lt;principal name&gt;
* <code>doNotPrompt</code>=true;
*</ul>
* <p> Search the cache for the principal's TGT. If it is not available
@ -281,7 +298,7 @@ import sun.misc.HexDumpEncoder;
* If the key is not available or valid then authentication will fail.
* <ul>
* <p><code>useTicketCache</code> = true
* <code>ticketCache</code>=< file name >
* <code>ticketCache</code>=&lt;file name&gt;
*</ul>
* <p> The TGT will be obtained from the cache specified.
* The Kerberos principal name used will be the principal name in
@ -292,8 +309,8 @@ import sun.misc.HexDumpEncoder;
* The Subject will be populated with the TGT.
*<ul>
* <p> <code>useKeyTab</code> = true
* <code>keyTab</code>=< keytab filename >
* <code>principal</code>= < principal name >
* <code>keyTab</code>=&lt;keytab filename&gt;
* <code>principal</code>= &lt;principal name&gt;
* <code>storeKey</code>=true;
*</ul>
* <p> The key for the principal will be retrieved from the keytab.
@ -303,7 +320,7 @@ import sun.misc.HexDumpEncoder;
* password entered.
* <ul>
* <p> <code>useKeyTab</code> = true
* <code>keyTab</code>=< keytabname >
* <code>keyTab</code>=&lt;keytabname&gt;
* <code>storeKey</code>=true
* <code>doNotPrompt</code>=true;
*</ul>
@ -316,21 +333,23 @@ import sun.misc.HexDumpEncoder;
* Subject's private credentials set. Otherwise the authentication will
* fail.
*<ul>
* <p><code>useKeyTab</code> = true
* <code>keyTab</code>=< file name > <code>storeKey</code>=true
* <code>principal</code>= < principal name >
* <p>
* <code>useTicketCache</code>=true
* <code>ticketCache</code>=< file name >;
* <code>ticketCache</code>=&lt;file name&gt;;
* <code>useKeyTab</code> = true
* <code>keyTab</code>=&lt;file name&gt; <code>storeKey</code>=true
* <code>principal</code>= &lt;principal name&gt;
*</ul>
* <p>The principal's key will be retrieved from the keytab and added
* to the <code>Subject</code>'s private credentials. If the key
* is not available, the
* user will be prompted for the password; the key derived from the password
* will be added to the Subject's private credentials set. The
* client's TGT will be retrieved from the ticket cache and added to the
* <p>
* The client's TGT will be retrieved from the ticket cache and added to the
* <code>Subject</code>'s private credentials. If the TGT is not available
* in the ticket cache, it will be obtained using the authentication
* in the ticket cache, or the TGT's client name does not match the principal
* name, Java will use a secret key to obtain the TGT using the authentication
* exchange and added to the Subject's private credentials.
* This secret key will be first retrieved from the keytab. If the key
* is not available, the user will be prompted for the password. In either
* case, the key derived from the password will be added to the
* Subject's private credentials set.
* <ul>
* <p><code>isInitiator</code> = false
*</ul>
@ -856,11 +875,13 @@ public class Krb5LoginModule implements LoginModule {
}
private void validateConfiguration() throws LoginException {
if (doNotPrompt && !useTicketCache && !useKeyTab)
if (doNotPrompt && !useTicketCache && !useKeyTab
&& !tryFirstPass && !useFirstPass)
throw new LoginException
("Configuration Error"
+ " - either doNotPrompt should be "
+ " false or useTicketCache/useKeyTab "
+ " false or at least one of useTicketCache, "
+ " useKeyTab, tryFirstPass and useFirstPass"
+ " should be true");
if (ticketCacheName != null && !useTicketCache)
throw new LoginException
@ -872,11 +893,12 @@ public class Krb5LoginModule implements LoginModule {
throw new LoginException
("Configuration Error - useKeyTab should be set to true "
+ "to use the keytab" + keyTabName);
if (storeKey && doNotPrompt && !useKeyTab)
if (storeKey && doNotPrompt && !useKeyTab
&& !tryFirstPass && !useFirstPass)
throw new LoginException
("Configuration Error - either doNotPrompt "
+ "should be set to false or "
+ "useKeyTab must be set to true for storeKey option");
("Configuration Error - either doNotPrompt should be set to "
+ " false or at least one of tryFirstPass, useFirstPass "
+ "or useKeyTab must be set to true for storeKey option");
if (renewTGT && !useTicketCache)
throw new LoginException
("Configuration Error"

View File

@ -73,10 +73,23 @@ abstract public class HttpURLConnection extends URLConnection {
* The fixed content-length when using fixed-length streaming mode.
* A value of <code>-1</code> means fixed-length streaming mode is disabled
* for output.
*
* <P> <B>NOTE:</B> {@link #fixedContentLengthLong} is recommended instead
* of this field, as it allows larger content lengths to be set.
*
* @since 1.5
*/
protected int fixedContentLength = -1;
/**
* The fixed content-length when using fixed-length streaming mode.
* A value of {@code -1} means fixed-length streaming mode is disabled
* for output.
*
* @since 1.7
*/
protected long fixedContentLengthLong = -1;
/**
* Returns the key for the <code>n</code><sup>th</sup> header field.
* Some implementations may treat the <code>0</code><sup>th</sup>
@ -109,6 +122,9 @@ abstract public class HttpURLConnection extends URLConnection {
* This exception can be queried for the details of the error.
* <p>
* This method must be called before the URLConnection is connected.
* <p>
* <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended
* instead of this method as it allows larger content lengths to be set.
*
* @param contentLength The number of bytes which will be written
* to the OutputStream.
@ -135,6 +151,52 @@ abstract public class HttpURLConnection extends URLConnection {
fixedContentLength = contentLength;
}
/**
* This method is used to enable streaming of a HTTP request body
* without internal buffering, when the content length is known in
* advance.
*
* <P> An exception will be thrown if the application attempts to write
* more data than the indicated content-length, or if the application
* closes the OutputStream before writing the indicated amount.
*
* <P> When output streaming is enabled, authentication and redirection
* cannot be handled automatically. A {@linkplain HttpRetryException} will
* be thrown when reading the response if authentication or redirection
* are required. This exception can be queried for the details of the
* error.
*
* <P> This method must be called before the URLConnection is connected.
*
* <P> The content length set by invoking this method takes precedence
* over any value set by {@link #setFixedLengthStreamingMode(int)}.
*
* @param contentLength
* The number of bytes which will be written to the OutputStream.
*
* @throws IllegalStateException
* if URLConnection is already connected or if a different
* streaming mode is already enabled.
*
* @throws IllegalArgumentException
* if a content length less than zero is specified.
*
* @since 1.7
*/
public void setFixedLengthStreamingMode(long contentLength) {
if (connected) {
throw new IllegalStateException("Already connected");
}
if (chunkLength != -1) {
throw new IllegalStateException(
"Chunked encoding streaming mode set");
}
if (contentLength < 0) {
throw new IllegalArgumentException("invalid content length");
}
fixedContentLengthLong = contentLength;
}
/* Default chunk size (including chunk header) if not specified;
* we want to keep this in sync with the one defined in
* sun.net.www.http.ChunkedOutputStream
@ -170,7 +232,7 @@ abstract public class HttpURLConnection extends URLConnection {
if (connected) {
throw new IllegalStateException ("Can't set streaming mode: already connected");
}
if (fixedContentLength != -1) {
if (fixedContentLength != -1 || fixedContentLengthLong != -1) {
throw new IllegalStateException ("Fixed length streaming mode set");
}
chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;

View File

@ -113,7 +113,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
public CertPathValidatorException(Throwable cause) {
this(null, cause);
this((cause == null ? null : cause.toString()), cause);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2008 Sun Microsystems, Inc. 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,17 +27,23 @@ package javax.management;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Represents a list of values for attributes of an MBean. The methods
* used for the insertion of {@link javax.management.Attribute
* Attribute} objects in the <CODE>AttributeList</CODE> overrides the
* corresponding methods in the superclass
* <CODE>ArrayList</CODE>. This is needed in order to insure that the
* objects contained in the <CODE>AttributeList</CODE> are only
* <CODE>Attribute</CODE> objects. This avoids getting an exception
* when retrieving elements from the <CODE>AttributeList</CODE>.
* <p>Represents a list of values for attributes of an MBean. See the
* {@link MBeanServerConnection#getAttributes getAttributes} and
* {@link MBeanServerConnection#setAttributes setAttributes} methods of
* {@link MBeanServer} and {@link MBeanServerConnection}.</p>
*
* <p id="type-safe">For compatibility reasons, it is possible, though
* highly discouraged, to add objects to an {@code AttributeList} that are
* not instances of {@code Attribute}. However, an {@code AttributeList}
* can be made <em>type-safe</em>, which means that an attempt to add
* an object that is not an {@code Attribute} will produce an {@code
* IllegalArgumentException}. An {@code AttributeList} becomes type-safe
* when the method {@link #asList()} is called on it.</p>
*
* @since 1.5
*/
@ -58,8 +64,8 @@ import java.util.List;
*/
public class AttributeList extends ArrayList<Object> {
private transient boolean typeSafe;
private transient boolean tainted;
private transient volatile boolean typeSafe;
private transient volatile boolean tainted;
/* Serial version */
private static final long serialVersionUID = -4077085769279709076L;
@ -124,13 +130,63 @@ public class AttributeList extends ArrayList<Object> {
// Check for non-Attribute objects
//
checkTypeSafe(list);
adding(list);
// Build the List<Attribute>
//
super.addAll(list);
}
/**
* <p>Constructs an {@code AttributeList} containing the elements of
* the {@code Map} specified, in the order in which they appear in the
* {@code Map}'s {@link Map#entrySet entrySet}. For each <em>{@code
* key}</em> and <em>{@code value}</em> in the {@code Map}, the constructed
* {@code AttributeList} will contain {@link Attribute#Attribute
* Attribute(<em>key</em>, <em>value</em>)}.</p>
*
* @param map the {@code Map} defining the elements of the new
* {@code AttributeList}.
*/
public AttributeList(Map<String, ?> map) {
for (Map.Entry<String, ?> entry : map.entrySet())
add(new Attribute(entry.getKey(), entry.getValue()));
typeSafe = true;
}
/**
* <p>Return a {@code Map} that is a snapshot of the values in this
* {@code AttributeList}. Each key in the {@code Map} is the {@linkplain
* Attribute#getName() name} of an {@code Attribute} in the list, and each
* value is the corresponding {@linkplain Attribute#getValue() value} of
* that {@code Attribute}. The {@code AttributeList} and the {@code Map}
* are unrelated after the call, that is, changes to one do not affect the
* other.</p>
*
* <p>If the {@code AttributeList} contains more than one {@code Attribute}
* with the same name, then the {@code Map} will contain an entry
* for that name where the value is that of the last of those {@code
* Attribute}s.</p>
*
* @return the new {@code Map}.
*
* @throws IllegalArgumentException if this {@code AttributeList} contains
* an element that is not an {@code Attribute}.
*/
public Map<String, Object> toMap() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
// We can't call adding(this) because we're not necessarily typeSafe
if (tainted)
throw new IllegalArgumentException("AttributeList contains non-Attribute");
for (Object x : this) {
Attribute a = (Attribute) x;
map.put(a.getName(), a.getValue());
}
return map;
}
/**
* Return a view of this list as a {@code List<Attribute>}.
* Changes to the returned value are reflected by changes
@ -154,11 +210,9 @@ public class AttributeList extends ArrayList<Object> {
*/
@SuppressWarnings("unchecked")
public List<Attribute> asList() {
if (!typeSafe) {
if (tainted)
checkTypeSafe(this);
typeSafe = true;
}
typeSafe = true;
if (tainted)
adding((Collection<?>) this); // will throw IllegalArgumentException
return (List<Attribute>) (List<?>) this;
}
@ -175,7 +229,7 @@ public class AttributeList extends ArrayList<Object> {
* Inserts the attribute specified as an element at the position specified.
* Elements with an index greater than or equal to the current position are
* shifted up. If the index is out of range (index < 0 || index >
* size() a RuntimeOperationsException should be raised, wrapping the
* size()) a RuntimeOperationsException should be raised, wrapping the
* java.lang.IndexOutOfBoundsException thrown.
*
* @param object The <CODE>Attribute</CODE> object to be inserted.
@ -245,8 +299,7 @@ public class AttributeList extends ArrayList<Object> {
public boolean addAll(int index, AttributeList list) {
try {
return super.addAll(index, list);
}
catch (IndexOutOfBoundsException e) {
} catch (IndexOutOfBoundsException e) {
throw new RuntimeOperationsException(e,
"The specified index is out of range");
}
@ -258,96 +311,77 @@ public class AttributeList extends ArrayList<Object> {
* been called on this instance.
*/
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
public boolean add(Object o) {
if (!tainted)
tainted = isTainted(o);
if (typeSafe)
checkTypeSafe(o);
return super.add(o);
public boolean add(Object element) {
adding(element);
return super.add(element);
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
public void add(int index, Object element) {
if (!tainted)
tainted = isTainted(element);
if (typeSafe)
checkTypeSafe(element);
adding(element);
super.add(index, element);
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code c} contains an
* element that is not an {@code Attribute}.
*/
@Override
public boolean addAll(Collection<?> c) {
if (!tainted)
tainted = isTainted(c);
if (typeSafe)
checkTypeSafe(c);
adding(c);
return super.addAll(c);
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code c} contains an
* element that is not an {@code Attribute}.
*/
@Override
public boolean addAll(int index, Collection<?> c) {
if (!tainted)
tainted = isTainted(c);
if (typeSafe)
checkTypeSafe(c);
adding(c);
return super.addAll(index, c);
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
public Object set(int index, Object element) {
if (!tainted)
tainted = isTainted(element);
if (typeSafe)
checkTypeSafe(element);
adding(element);
return super.set(index, element);
}
/**
* IllegalArgumentException if o is a non-Attribute object.
*/
private static void checkTypeSafe(Object o) {
try {
o = (Attribute) o;
} catch (ClassCastException e) {
throw new IllegalArgumentException(e);
}
private void adding(Object x) {
if (x == null || x instanceof Attribute)
return;
if (typeSafe)
throw new IllegalArgumentException("Not an Attribute: " + x);
else
tainted = true;
}
/**
* IllegalArgumentException if c contains any non-Attribute objects.
*/
private static void checkTypeSafe(Collection<?> c) {
try {
Attribute a;
for (Object o : c)
a = (Attribute) o;
} catch (ClassCastException e) {
throw new IllegalArgumentException(e);
}
}
/**
* Returns true if o is a non-Attribute object.
*/
private static boolean isTainted(Object o) {
try {
checkTypeSafe(o);
} catch (IllegalArgumentException e) {
return true;
}
return false;
}
/**
* Returns true if c contains any non-Attribute objects.
*/
private static boolean isTainted(Collection<?> c) {
try {
checkTypeSafe(c);
} catch (IllegalArgumentException e) {
return true;
}
return false;
private void adding(Collection<?> c) {
for (Object x : c)
adding(x);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -35,8 +35,8 @@ import java.io.Serializable;
// Javadoc imports:
import java.lang.management.MemoryUsage;
import java.util.Arrays;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
@ -118,19 +118,22 @@ import javax.management.openmbean.OpenType;
* deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td>
*
* <tr id="descriptionResourceBundleBaseName">
* <td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
* <tr><td id="descriptionResourceBundleBaseName"><i>descriptionResource<br>
* BundleBaseName</i></td><td>String</td><td>Any</td>
*
* <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}.</td>
* {@code "com.example.myapp.MBeanResources"}. See
* {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.</td>
*
* <tr id="descriptionResourceKey">
* <td>descriptionResourceKey</td><td>String</td><td>Any</td>
* <tr><td id="descriptionResourceKey"><i>descriptionResourceKey</i></td>
* <td>String</td><td>Any</td>
*
* <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName},
* this can be used to find a localized version of the description.</td>
* this can be used to find a localized version of the description.
* See {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.
* </td>
*
* <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
@ -157,11 +160,11 @@ import javax.management.openmbean.OpenType;
* href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a>
* notification.</td>
*
* <tr><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
* <tr id="infoTimeout"><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
*
* <td id="infoTimeout">The time in milli-seconds that the MBeanInfo can
* reasonably be expected to be unchanged. The value can be a {@code Long}
* or a decimal string. This provides a hint from a DynamicMBean or any
* <td>The time in milli-seconds that the MBeanInfo can reasonably be
* expected to be unchanged. The value can be a {@code Long} or a
* decimal string. This provides a hint from a DynamicMBean or any
* MBean that does not define {@code immutableInfo} as {@code true}
* that the MBeanInfo is not likely to change within this period and
* therefore can be cached. When this field is missing or has the
@ -185,6 +188,13 @@ import javax.management.openmbean.OpenType;
* <td>Legal values for an attribute or parameter. See
* {@link javax.management.openmbean}.</td>
*
* <tr id="locale"><td><i>locale</i></td>
* <td>String</td><td>Any</td>
*
* <td>The {@linkplain Locale locale} of the description in this
* {@code MBeanInfo}, {@code MBeanAttributeInfo}, etc, as returned
* by {@link Locale#toString()}.</td>
*
* <tr id="maxValue"><td><i>maxValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*

View File

@ -30,6 +30,7 @@ import com.sun.jmx.mbeanserver.MBeanInjector;
import com.sun.jmx.remote.util.ClassLogger;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@ -37,6 +38,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.TreeMap;
import javax.management.namespace.JMXNamespaces;
import javax.management.openmbean.MXBeanMappingFactory;
/**
@ -60,6 +62,21 @@ public class JMX {
*/
public static final String DEFAULT_VALUE_FIELD = "defaultValue";
/**
* The name of the <a
* href="Descriptor.html#descriptionResourceBundleBaseName">{@code
* descriptionResourceBundleBaseName}</a> field.
*/
public static final String DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD =
"descriptionResourceBundleBaseName";
/**
* The name of the <a href="Descriptor.html#descriptionResourceKey">{@code
* descriptionResourceKey}</a> field.
*/
public static final String DESCRIPTION_RESOURCE_KEY_FIELD =
"descriptionResourceKey";
/**
* The name of the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field.
@ -78,6 +95,12 @@ public class JMX {
*/
public static final String LEGAL_VALUES_FIELD = "legalValues";
/**
* The name of the <a href="Descriptor.html#locale">{@code locale}</a>
* field.
*/
public static final String LOCALE_FIELD = "locale";
/**
* The name of the <a href="Descriptor.html#maxValue">{@code
* maxValue}</a> field.
@ -120,13 +143,12 @@ public class JMX {
* <p>Options to apply to an MBean proxy or to an instance of {@link
* StandardMBean}.</p>
*
* <p>For example, to specify a custom {@link MXBeanMappingFactory}
* for a {@code StandardMBean}, you might write this:</p>
* <p>For example, to specify the "wrapped object visible" option for a
* {@code StandardMBean}, you might write this:</p>
*
* <pre>
* MXBeanMappingFactory factory = new MyMXBeanMappingFactory();
* JMX.MBeanOptions opts = new JMX.MBeanOptions();
* opts.setMXBeanMappingFactory(factory);
* StandardMBean.Options opts = new StandardMBean.Options();
* opts.setWrappedObjectVisible(true);
* StandardMBean mbean = new StandardMBean(impl, intf, opts);
* </pre>
*
@ -808,4 +830,80 @@ public class JMX {
((DynamicWrapperMBean) mbean).getWrappedObject() : mbean;
return (MBeanInjector.injectsSendNotification(resource));
}
/**
* <p>Return the version of the JMX specification that a (possibly remote)
* MBean Server is using. The JMX specification described in this
* documentation is version 2.0. The earlier versions that might be
* reported by this method are 1.0, 1.1, 1.2, and 1.4. (There is no 1.3.)
* All of these versions and all future versions can be compared using
* {@link String#compareTo(String)}. So, for example, to tell if
* {@code mbsc} is running at least version 2.0 you can write:</p>
*
* <pre>
* String version = JMX.getSpecificationVersion(mbsc, null);
* boolean atLeast2dot0 = (version.compareTo("2.0") >= 0);
* </pre>
*
* <p>A remote MBean Server might be running an earlier version of the
* JMX API, and in that case <a href="package-summary.html#interop">certain
* features</a> might not be available in it.</p>
*
* <p>The version of the MBean Server {@code mbsc} is not necessarily
* the version of all namespaces within that MBean Server, for example
* if some of them use {@link javax.management.namespace.JMXRemoteNamespace
* JMXRemoteNamespace}. To determine the version of the namespace
* that a particular MBean is in, give its name as the {@code mbeanName}
* parameter.</p>
*
* @param mbsc a connection to an MBean Server.
*
* @param mbeanName the name of an MBean within that MBean Server, or null.
* If non-null, the namespace of this name, as determined by
* {@link JMXNamespaces#getContainingNamespace
* JMXNamespaces.getContainingNamespace}, is the one whose specification
* version will be returned.
*
* @return the JMX specification version reported by that MBean Server.
*
* @throws IllegalArgumentException if {@code mbsc} is null, or if
* {@code mbeanName} includes a wildcard character ({@code *} or {@code ?})
* in its namespace.
*
* @throws IOException if the version cannot be obtained, either because
* there is a communication problem or because the remote MBean Server
* does not have the appropriate {@linkplain
* MBeanServerDelegateMBean#getSpecificationVersion() attribute}.
*
* @see <a href="package-summary.html#interop">Interoperability between
* versions of the JMX specification</a>
* @see MBeanServerDelegateMBean#getSpecificationVersion
*/
public static String getSpecificationVersion(
MBeanServerConnection mbsc, ObjectName mbeanName)
throws IOException {
if (mbsc == null)
throw new IllegalArgumentException("Null MBeanServerConnection");
String namespace;
if (mbeanName == null)
namespace = "";
else
namespace = JMXNamespaces.getContainingNamespace(mbeanName);
if (namespace.contains("*") || namespace.contains("?")) {
throw new IllegalArgumentException(
"ObjectName contains namespace wildcard: " + mbeanName);
}
try {
if (namespace.length() > 0)
mbsc = JMXNamespaces.narrowToNamespace(mbsc, namespace);
return (String) mbsc.getAttribute(
MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion");
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
}
}

View File

@ -25,6 +25,7 @@
package javax.management;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.io.Serializable;
@ -37,6 +38,12 @@ import java.util.WeakHashMap;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import static javax.management.ImmutableDescriptor.nonNullDescriptor;
/**
@ -290,6 +297,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
* <p>Since this class is immutable, the clone method is chiefly of
* interest to subclasses.</p>
*/
@Override
public Object clone () {
try {
return super.clone() ;
@ -474,6 +482,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
return (Descriptor) nonNullDescriptor(descriptor).clone();
}
@Override
public String toString() {
return
getClass().getName() + "[" +
@ -505,6 +514,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
* @return true if and only if <code>o</code> is an MBeanInfo that is equal
* to this one according to the rules above.
*/
@Override
public boolean equals(Object o) {
if (o == this)
return true;
@ -524,6 +534,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
Arrays.equals(p.fastGetNotifications(), fastGetNotifications()));
}
@Override
public int hashCode() {
/* Since computing the hashCode is quite expensive, we cache it.
If by some terrible misfortune the computed value is 0, the
@ -747,4 +758,377 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
throw new StreamCorruptedException("Got unexpected byte.");
}
}
/**
* <p>Return an {@code MBeanInfo} object that is the same as this one
* except that its descriptions are localized in the given locale.
* This means the text returned by {@link MBeanInfo#getDescription}
* (the description of the MBean itself), and the text returned by the
* {@link MBeanFeatureInfo#getDescription getDescription()} method
* for every {@linkplain MBeanAttributeInfo attribute}, {@linkplain
* MBeanOperationInfo operation}, {@linkplain MBeanConstructorInfo
* constructor}, and {@linkplain MBeanNotificationInfo notification}
* contained in the {@code MBeanInfo}.</p>
*
* <p>Here is how the description {@code this.getDescription()} is
* localized.</p>
*
* <p>First, if the {@linkplain #getDescriptor() descriptor}
* of this {@code MBeanInfo} contains a field <code><a
* href="Descriptor.html#locale">"locale"</a></code>, and the value of
* the field is the same as {@code locale.toString()}, then this {@code
* MBeanInfo} is returned. Otherwise, localization proceeds as follows,
* and the {@code "locale"} field in the returned {@code MBeanInfo} will
* be {@code locale.toString()}.
*
* <p>A <em>{@code className}</em> is determined. If this
* {@code MBeanInfo} contains a descriptor with the field
* <a href="Descriptor.html#interfaceClassName">{@code
* "interfaceClassName"}</a>, then the value of that field is the
* {@code className}. Otherwise, it is {@link #getClassName()}.
* Everything before the last period (.) in the {@code className} is
* the <em>{@code package}</em>, and everything after is the <em>{@code
* simpleClassName}</em>. (If there is no period, then the {@code package}
* is empty and the {@code simpleClassName} is the same as the {@code
* className}.)</p>
*
* <p>A <em>{@code resourceKey}</em> is determined. If this {@code
* MBeanInfo} contains a {@linkplain MBeanInfo#getDescriptor() descriptor}
* with a field {@link JMX#DESCRIPTION_RESOURCE_KEY_FIELD
* "descriptionResourceKey"}, the value of the field is
* the {@code resourceKey}. Otherwise, the {@code resourceKey} is {@code
* simpleClassName + ".mbean"}.</p>
*
* <p>A <em>{@code resourceBundleBaseName}</em> is determined. If
* this {@code MBeanInfo} contains a descriptor with a field {@link
* JMX#DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
* "descriptionResourceBundleBaseName"}, the value of the field
* is the {@code resourceBundleBaseName}. Otherwise, the {@code
* resourceBundleBaseName} is {@code package + ".MBeanDescriptions"}.
*
* <p>Then, a {@link java.util.ResourceBundle ResourceBundle} is
* determined, using<br> {@link java.util.ResourceBundle#getBundle(String,
* Locale, ClassLoader) ResourceBundle.getBundle(resourceBundleBaseName,
* locale, loader)}. If this succeeds, and if {@link
* java.util.ResourceBundle#getString(String) getString(resourceKey)}
* returns a string, then that string is the localized description.
* Otherwise, the original description is unchanged.</p>
*
* <p>A localized description for an {@code MBeanAttributeInfo} is
* obtained similarly. The default {@code resourceBundleBaseName}
* is the same as above. The default description and the
* descriptor fields {@code "descriptionResourceKey"} and {@code
* "descriptionResourceBundleBaseName"} come from the {@code
* MBeanAttributeInfo} rather than the {@code MBeanInfo}. If the
* attribute's {@linkplain MBeanFeatureInfo#getName() name} is {@code
* Foo} then its default {@code resourceKey} is {@code simpleClassName +
* ".attribute.Foo"}.</p>
*
* <p>Similar rules apply for operations, constructors, and notifications.
* If the name of the operation, constructor, or notification is {@code
* Foo} then the default {@code resourceKey} is respectively {@code
* simpleClassName + ".operation.Foo"}, {@code simpleClassName +
* ".constructor.Foo"}, or {@code simpleClassName + ".notification.Foo"}.
* If two operations or constructors have the same name (overloading) then
* they have the same default {@code resourceKey}; if different localized
* descriptions are needed then a non-default key must be supplied using
* {@code "descriptionResourceKey"}.</p>
*
* <p>Similar rules also apply for descriptions of parameters ({@link
* MBeanParameterInfo}). The default {@code resourceKey} for a parameter
* whose {@linkplain MBeanFeatureInfo#getName() name} is {@code
* Bar} in an operation or constructor called {@code Foo} is {@code
* simpleClassName + ".operation.Foo.Bar"} or {@code simpleClassName +
* ".constructor.Foo.Bar"} respectively.</p>
*
* <h4>Example</h4>
*
* <p>Suppose you have an MBean defined by these two Java source files:</p>
*
* <pre>
* // ConfigurationMBean.java
* package com.example;
* public interface ConfigurationMBean {
* public String getName();
* public void save(String fileName);
* }
*
* // Configuration.java
* package com.example;
* public class Configuration implements ConfigurationMBean {
* public Configuration(String defaultName) {
* ...
* }
* ...
* }
* </pre>
*
* <p>Then you could define the default descriptions for the MBean, by
* including a resource bundle called {@code com/example/MBeanDescriptions}
* with the compiled classes. Most often this is done by creating a file
* {@code MBeanDescriptions.properties} in the same directory as {@code
* ConfigurationMBean.java}. Make sure that this file is copied into the
* same place as the compiled classes; in typical build environments that
* will be true by default.</p>
*
* <p>The file {@code com/example/MBeanDescriptions.properties} might
* look like this:</p>
*
* <pre>
* # Description of the MBean
* ConfigurationMBean.mbean = Configuration manager
*
* # Description of the Name attribute
* ConfigurationMBean.attribute.Name = The name of the configuration
*
* # Description of the save operation
* ConfigurationMBean.operation.save = Save the configuration to a file
*
* # Description of the parameter to the save operation.
* # Parameter names from the original Java source are not available,
* # so the default names are p1, p2, etc. If the names were available,
* # this would be ConfigurationMBean.operation.save.fileName
* ConfigurationMBean.operation.save.p1 = The name of the file
*
* # Description of the constructor. The default name of a constructor is
* # its fully-qualified class name.
* ConfigurationMBean.constructor.com.example.Configuration = <!--
* -->Constructor with name of default file
* # Description of the constructor parameter.
* ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
* -->Name of the default file
* </pre>
*
* <p>Starting with this file, you could create descriptions for the French
* locale by creating {@code com/example/MBeanDescriptions_fr.properties}.
* The keys in this file are the same as before but the text has been
* translated:
*
* <pre>
* ConfigurationMBean.mbean = Gestionnaire de configuration
*
* ConfigurationMBean.attribute.Name = Le nom de la configuration
*
* ConfigurationMBean.operation.save = Sauvegarder la configuration <!--
* -->dans un fichier
*
* ConfigurationMBean.operation.save.p1 = Le nom du fichier
*
* ConfigurationMBean.constructor.com.example.Configuration = <!--
* -->Constructeur avec nom du fichier par d&eacute;faut
* ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
* -->Nom du fichier par d&eacute;faut
* </pre>
*
* <p>The descriptions in {@code MBeanDescriptions.properties} and
* {@code MBeanDescriptions_fr.properties} will only be consulted if
* {@code localizeDescriptions} is called, perhaps because the
* MBean Server has been wrapped by {@link
* ClientContext#newLocalizeMBeanInfoForwarder} or because the
* connector server has been created with the {@link
* javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
* LOCALIZE_MBEAN_INFO_FORWARDER} option. If you want descriptions
* even when there is no localization step, then you should consider
* using {@link Description &#64;Description} annotations. Annotations
* provide descriptions by default but are overridden if {@code
* localizeDescriptions} is called.</p>
*
* @param locale the target locale for descriptions. Cannot be null.
*
* @param loader the {@code ClassLoader} to use for looking up resource
* bundles.
*
* @return an {@code MBeanInfo} with descriptions appropriately localized.
*
* @throws NullPointerException if {@code locale} is null.
*/
public MBeanInfo localizeDescriptions(Locale locale, ClassLoader loader) {
if (locale == null)
throw new NullPointerException("locale");
Descriptor d = getDescriptor();
String mbiLocaleString = (String) d.getFieldValue(JMX.LOCALE_FIELD);
if (locale.toString().equals(mbiLocaleString))
return this;
return new Rewriter(this, locale, loader).getMBeanInfo();
}
private static class Rewriter {
private final MBeanInfo mbi;
private final ClassLoader loader;
private final Locale locale;
private final String packageName;
private final String simpleClassNamePlusDot;
private ResourceBundle defaultBundle;
private boolean defaultBundleLoaded;
// ResourceBundle.getBundle throws NullPointerException
// if the loader is null, even though that is perfectly
// valid and means the bootstrap loader. So we work
// around with a ClassLoader that is equivalent to the
// bootstrap loader but is not null.
private static final ClassLoader bootstrapLoader =
new ClassLoader(null) {};
Rewriter(MBeanInfo mbi, Locale locale, ClassLoader loader) {
this.mbi = mbi;
this.locale = locale;
if (loader == null)
loader = bootstrapLoader;
this.loader = loader;
String intfName = (String)
mbi.getDescriptor().getFieldValue("interfaceClassName");
if (intfName == null)
intfName = mbi.getClassName();
int lastDot = intfName.lastIndexOf('.');
this.packageName = intfName.substring(0, lastDot + 1);
this.simpleClassNamePlusDot = intfName.substring(lastDot + 1) + ".";
// Inner classes show up as Outer$Inner so won't match the dot.
// When there is no dot, lastDot is -1,
// packageName is empty, and simpleClassNamePlusDot is intfName.
}
MBeanInfo getMBeanInfo() {
MBeanAttributeInfo[] mbais =
rewrite(mbi.getAttributes(), "attribute.");
MBeanOperationInfo[] mbois =
rewrite(mbi.getOperations(), "operation.");
MBeanConstructorInfo[] mbcis =
rewrite(mbi.getConstructors(), "constructor.");
MBeanNotificationInfo[] mbnis =
rewrite(mbi.getNotifications(), "notification.");
Descriptor d = mbi.getDescriptor();
d = changeLocale(d);
String description = getDescription(d, "mbean", "");
if (description == null)
description = mbi.getDescription();
return new MBeanInfo(
mbi.getClassName(), description,
mbais, mbcis, mbois, mbnis, d);
}
private Descriptor changeLocale(Descriptor d) {
if (d.getFieldValue(JMX.LOCALE_FIELD) != null) {
Map<String, Object> map = new HashMap<String, Object>();
for (String field : d.getFieldNames())
map.put(field, d.getFieldValue(field));
map.remove(JMX.LOCALE_FIELD);
d = new ImmutableDescriptor(map);
}
return ImmutableDescriptor.union(
d, new ImmutableDescriptor(JMX.LOCALE_FIELD + "=" + locale));
}
private String getDescription(
Descriptor d, String defaultPrefix, String defaultSuffix) {
ResourceBundle bundle = bundleFromDescriptor(d);
if (bundle == null)
return null;
String key =
(String) d.getFieldValue(JMX.DESCRIPTION_RESOURCE_KEY_FIELD);
if (key == null)
key = simpleClassNamePlusDot + defaultPrefix + defaultSuffix;
return descriptionFromResource(bundle, key);
}
private <T extends MBeanFeatureInfo> T[] rewrite(
T[] features, String resourcePrefix) {
for (int i = 0; i < features.length; i++) {
T feature = features[i];
Descriptor d = feature.getDescriptor();
String description =
getDescription(d, resourcePrefix, feature.getName());
if (description != null &&
!description.equals(feature.getDescription())) {
features[i] = setDescription(feature, description);
}
}
return features;
}
private <T extends MBeanFeatureInfo> T setDescription(
T feature, String description) {
Object newf;
String name = feature.getName();
Descriptor d = feature.getDescriptor();
if (feature instanceof MBeanAttributeInfo) {
MBeanAttributeInfo mbai = (MBeanAttributeInfo) feature;
newf = new MBeanAttributeInfo(
name, mbai.getType(), description,
mbai.isReadable(), mbai.isWritable(), mbai.isIs(),
d);
} else if (feature instanceof MBeanOperationInfo) {
MBeanOperationInfo mboi = (MBeanOperationInfo) feature;
MBeanParameterInfo[] sig = rewrite(
mboi.getSignature(), "operation." + name + ".");
newf = new MBeanOperationInfo(
name, description, sig,
mboi.getReturnType(), mboi.getImpact(), d);
} else if (feature instanceof MBeanConstructorInfo) {
MBeanConstructorInfo mbci = (MBeanConstructorInfo) feature;
MBeanParameterInfo[] sig = rewrite(
mbci.getSignature(), "constructor." + name + ".");
newf = new MBeanConstructorInfo(
name, description, sig, d);
} else if (feature instanceof MBeanNotificationInfo) {
MBeanNotificationInfo mbni = (MBeanNotificationInfo) feature;
newf = new MBeanNotificationInfo(
mbni.getNotifTypes(), name, description, d);
} else if (feature instanceof MBeanParameterInfo) {
MBeanParameterInfo mbpi = (MBeanParameterInfo) feature;
newf = new MBeanParameterInfo(
name, mbpi.getType(), description, d);
} else {
logger().log(Level.FINE, "Unknown feature type: " +
feature.getClass());
newf = feature;
}
return Util.<T>cast(newf);
}
private ResourceBundle bundleFromDescriptor(Descriptor d) {
String bundleName = (String) d.getFieldValue(
JMX.DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD);
if (bundleName != null)
return getBundle(bundleName);
if (defaultBundleLoaded)
return defaultBundle;
bundleName = packageName + "MBeanDescriptions";
defaultBundle = getBundle(bundleName);
defaultBundleLoaded = true;
return defaultBundle;
}
private String descriptionFromResource(
ResourceBundle bundle, String key) {
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
logger().log(Level.FINEST, "No resource for " + key, e);
} catch (Exception e) {
logger().log(Level.FINE, "Bad resource for " + key, e);
}
return null;
}
private ResourceBundle getBundle(String name) {
try {
return ResourceBundle.getBundle(name, locale, loader);
} catch (Exception e) {
logger().log(Level.FINE,
"Could not load ResourceBundle " + name, e);
return null;
}
}
private Logger logger() {
return Logger.getLogger("javax.management.locale");
}
}
}

View File

@ -532,8 +532,30 @@ public interface MBeanServerConnection extends NotificationManager {
/**
* Enables the values of several attributes of a named MBean. The MBean
* is identified by its object name.
* <p>Retrieves the values of several attributes of a named MBean. The MBean
* is identified by its object name.</p>
*
* <p>If one or more attributes cannot be retrieved for some reason, they
* will be omitted from the returned {@code AttributeList}. The caller
* should check that the list is the same size as the {@code attributes}
* array. To discover what problem prevented a given attribute from being
* retrieved, call {@link #getAttribute getAttribute} for that attribute.</p>
*
* <p>Here is an example of calling this method and checking that it
* succeeded in retrieving all the requested attributes:</p>
*
* <pre>
* String[] attrNames = ...;
* AttributeList list = mbeanServerConnection.getAttributes(objectName, attrNames);
* if (list.size() == attrNames.length)
* System.out.println("All attributes were retrieved successfully");
* else {
* {@code List<String>} missing = new {@code ArrayList<String>}(<!--
* -->{@link java.util.Arrays#asList Arrays.asList}(attrNames));
* missing.removeAll(list.toMap().keySet());
* System.out.println("Did not retrieve: " + missing);
* }
* </pre>
*
* @param name The object name of the MBean from which the
* attributes are retrieved.
@ -557,6 +579,7 @@ public interface MBeanServerConnection extends NotificationManager {
throws InstanceNotFoundException, ReflectionException,
IOException;
/**
* Sets the value of a specific attribute of a named MBean. The MBean
* is identified by its object name.
@ -592,10 +615,36 @@ public interface MBeanServerConnection extends NotificationManager {
ReflectionException, IOException;
/**
* Sets the values of several attributes of a named MBean. The MBean is
* identified by its object name.
* <p>Sets the values of several attributes of a named MBean. The MBean is
* identified by its object name.</p>
*
* <p>If one or more attributes cannot be set for some reason, they will be
* omitted from the returned {@code AttributeList}. The caller should check
* that the input {@code AttributeList} is the same size as the output one.
* To discover what problem prevented a given attribute from being retrieved,
* it will usually be possible to call {@link #setAttribute setAttribute}
* for that attribute, although this is not guaranteed to work. (For
* example, the values of two attributes may have been rejected because
* they were inconsistent with each other. Setting one of them alone might
* be allowed.)<p>
*
* <p>Here is an example of calling this method and checking that it
* succeeded in setting all the requested attributes:</p>
*
* <pre>
* AttributeList inputAttrs = ...;
* AttributeList outputAttrs = mbeanServerConnection.setAttributes(<!--
* -->objectName, inputAttrs);
* if (inputAttrs.size() == outputAttrs.size())
* System.out.println("All attributes were set successfully");
* else {
* {@code List<String>} missing = new {@code ArrayList<String>}(<!--
* -->inputAttrs.toMap().keySet());
* missing.removeAll(outputAttrs.toMap().keySet());
* System.out.println("Did not set: " + missing);
* }
* </pre>
*
* @param name The object name of the MBean within which the
* attributes are to be set.
@ -622,7 +671,39 @@ public interface MBeanServerConnection extends NotificationManager {
throws InstanceNotFoundException, ReflectionException, IOException;
/**
* Invokes an operation on an MBean.
* <p>Invokes an operation on an MBean.</p>
*
* <p>Because of the need for a {@code signature} to differentiate
* possibly-overloaded operations, it is much simpler to invoke operations
* through an {@linkplain JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
* Class) MBean proxy} where possible. For example, suppose you have a
* Standard MBean interface like this:</p>
*
* <pre>
* public interface FooMBean {
* public int countMatches(String[] patterns, boolean ignoreCase);
* }
* </pre>
*
* <p>The {@code countMatches} operation can be invoked as follows:</p>
*
* <pre>
* String[] myPatterns = ...;
* int count = (Integer) mbeanServerConnection.invoke(
* objectName,
* "countMatches",
* new Object[] {myPatterns, true},
* new String[] {String[].class.getName(), boolean.class.getName()});
* </pre>
*
* <p>Alternatively, it can be invoked through a proxy as follows:</p>
*
* <pre>
* String[] myPatterns = ...;
* FooMBean fooProxy = JMX.newMBeanProxy(
* mbeanServerConnection, objectName, FooMBean.class);
* int count = fooProxy.countMatches(myPatterns, true);
* </pre>
*
* @param name The object name of the MBean on which the method is
* to be invoked.
@ -630,7 +711,8 @@ public interface MBeanServerConnection extends NotificationManager {
* @param params An array containing the parameters to be set when
* the operation is invoked
* @param signature An array containing the signature of the
* operation. The class objects will be loaded using the same
* operation, an array of class names in the format returned by
* {@link Class#getName()}. The class objects will be loaded using the same
* class loader as the one used for loading the MBean on which the
* operation was invoked.
*

View File

@ -27,15 +27,70 @@ package javax.management;
/**
* Represents a notification emitted by the MBean server through the MBeanServerDelegate MBean.
* Represents a notification emitted by the MBean Server through the MBeanServerDelegate MBean.
* The MBean Server emits the following types of notifications: MBean registration, MBean
* de-registration.
* unregistration.
* <P>
* To receive to MBeanServerNotifications, you need to be declared as listener to
* the {@link javax.management.MBeanServerDelegate javax.management.MBeanServerDelegate} MBean
* that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is:
* To receive MBeanServerNotifications, you need to register a listener with
* the {@link MBeanServerDelegate MBeanServerDelegate} MBean
* that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is
* {@link MBeanServerDelegate#DELEGATE_NAME}, which is
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
*
* <p>The following code prints a message every time an MBean is registered
* or unregistered in the MBean Server {@code mbeanServer}:</p>
*
* <pre>
* private static final NotificationListener printListener = new NotificationListener() {
* public void handleNotification(Notification n, Object handback) {
* if (!(n instanceof MBeanServerNotification)) {
* System.out.println("Ignored notification of class " + n.getClass().getName());
* return;
* }
* MBeanServerNotification mbsn = (MBeanServerNotification) n;
* String what;
* if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
* what = "MBean registered";
* else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
* what = "MBean unregistered";
* else
* what = "Unknown type " + n.getType();
* System.out.println("Received MBean Server notification: " + what + ": " +
* mbsn.getMBeanName());
* };
*
* ...
* mbeanServer.addNotificationListener(
* MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
* </pre>
*
* <p>The following code prints a message every time an MBean is registered
* or unregistered in the MBean Server {@code mbeanServer}:</p>
*
* <pre>
* private static final NotificationListener printListener = new NotificationListener() {
* public void handleNotification(Notification n, Object handback) {
* if (!(n instanceof MBeanServerNotification)) {
* System.out.println("Ignored notification of class " + n.getClass().getName());
* return;
* }
* MBeanServerNotification mbsn = (MBeanServerNotification) n;
* String what;
* if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
* what = "MBean registered";
* else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
* what = "MBean unregistered";
* else
* what = "Unknown type " + n.getType();
* System.out.println("Received MBean Server notification: " + what + ": " +
* mbsn.getMBeanName());
* };
*
* ...
* mbeanServer.addNotificationListener(
* MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
* </pre>
*
* @since 1.5
*/
public class MBeanServerNotification extends Notification {

View File

@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetPropertyAction;
* @since 1.5
*/
@SuppressWarnings("serial") // serialVersionUID is not constant
public class Notification extends EventObject {
public class Notification extends EventObject implements Cloneable {
// Serialization compatibility stuff:
// Two serial forms are supported in this class. The selected form depends
@ -243,6 +243,26 @@ public class Notification extends EventObject {
this.message = message ;
}
/**
* <p>Creates and returns a copy of this object. The copy is created as
* described for {@link Object#clone()}. This means, first, that the
* class of the object will be the same as the class of this object, and,
* second, that the copy is a "shallow copy". Fields of this notification
* are not themselves copied. In particular, the {@linkplain
* #getUserData user data} of the copy is the same object as the
* original.</p>
*
* @return a copy of this object.
*/
@Override
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(e);
}
}
/**
* Sets the source.
*
@ -285,8 +305,10 @@ public class Notification extends EventObject {
/**
* Get the notification type.
*
* @return The notification type. It's a string expressed in a dot notation similar
* to Java properties. An example of a notification type is network.alarm.router .
* @return The notification type. It's a string expressed in a dot notation
* similar to Java properties. It is recommended that the notification type
* should follow the reverse-domain-name convention used by Java package
* names. An example of a notification type is com.example.alarm.router.
*/
public String getType() {
return type ;
@ -317,14 +339,25 @@ public class Notification extends EventObject {
/**
* Get the notification message.
*
* @return The message string of this notification object. It contains in a string,
* which could be the explanation of the notification for displaying to a user
* @return The message string of this notification object.
*
* @see #setMessage
*/
public String getMessage() {
return message ;
}
/**
* Set the notification message.
*
* @param message the new notification message.
*
* @see #getMessage
*/
public void setMessage(String message) {
this.message = message;
}
/**
* Get the user data.
*
@ -355,6 +388,7 @@ public class Notification extends EventObject {
*
* @return A String representation of this notification.
*/
@Override
public String toString() {
return super.toString()+"[type="+type+"][message="+message+"]";
}

View File

@ -26,7 +26,6 @@
package javax.management;
import com.sun.jmx.mbeanserver.NotificationMBeanSupport;
import com.sun.jmx.mbeanserver.Util;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -43,6 +42,11 @@ import java.util.Set;
* on both the client and the server in the remote case, so using this class
* instead is recommended where possible.</p>
*
* <p>Because this class was introduced in version 2.0 of the JMX API,
* it may not be present on a remote JMX agent that is running an earlier
* version. The method {@link JMX#getSpecificationVersion
* JMX.getSpecificationVersion} can be used to determine the remote version.</p>
*
* <p>This class uses the {@linkplain Query Query API} to specify the
* filtering logic. For example, to select only notifications where the
* {@linkplain Notification#getType() type} is {@code "com.example.mytype"},

View File

@ -29,7 +29,6 @@ import com.sun.jmx.event.DaemonThreadFactory;
import com.sun.jmx.event.LeaseRenewer;
import com.sun.jmx.event.ReceiverBuffer;
import com.sun.jmx.event.RepeatedSingletonJob;
import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.mbeanserver.PerThreadGroupPool;
import com.sun.jmx.remote.util.ClassLogger;
@ -58,7 +57,6 @@ import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification;
@ -129,11 +127,12 @@ public class EventClient implements EventConsumer, NotificationManager {
public static final String NOTIFS_LOST = "jmx.event.service.notifs.lost";
/**
* The default lease time, {@value}, in milliseconds.
* The default lease time that EventClient instances will request, in
* milliseconds. This value is {@value}.
*
* @see EventClientDelegateMBean#lease
*/
public static final long DEFAULT_LEASE_TIMEOUT = 300000;
public static final long DEFAULT_REQUESTED_LEASE_TIME = 300000;
/**
* <p>Constructs a default {@code EventClient} object.</p>
@ -173,7 +172,7 @@ public class EventClient implements EventConsumer, NotificationManager {
*/
public EventClient(EventClientDelegateMBean delegate)
throws IOException {
this(delegate, null, null, null, DEFAULT_LEASE_TIMEOUT);
this(delegate, null, null, null, DEFAULT_REQUESTED_LEASE_TIME);
}
/**
@ -196,7 +195,7 @@ public class EventClient implements EventConsumer, NotificationManager {
* If {@code null}, a default scheduler will be used.
* @param requestedLeaseTime The lease time used to keep this client alive
* in the {@link EventClientDelegateMBean}. A value of zero is equivalent
* to the {@linkplain #DEFAULT_LEASE_TIMEOUT default value}.
* to the {@linkplain #DEFAULT_REQUESTED_LEASE_TIME default value}.
*
* @throws IllegalArgumentException If {@code delegate} is null.
* @throws IOException If an I/O error occurs when communicating with the
@ -213,7 +212,7 @@ public class EventClient implements EventConsumer, NotificationManager {
}
if (requestedLeaseTime == 0)
requestedLeaseTime = DEFAULT_LEASE_TIMEOUT;
requestedLeaseTime = DEFAULT_REQUESTED_LEASE_TIME;
else if (requestedLeaseTime < 0) {
throw new IllegalArgumentException(
"Negative lease time: " + requestedLeaseTime);
@ -269,7 +268,13 @@ public class EventClient implements EventConsumer, NotificationManager {
new ScheduledThreadPoolExecutor(20, daemonThreadFactory);
executor.setKeepAliveTime(1, TimeUnit.SECONDS);
executor.allowCoreThreadTimeOut(true);
executor.setRemoveOnCancelPolicy(true);
if (setRemoveOnCancelPolicy != null) {
try {
setRemoveOnCancelPolicy.invoke(executor, true);
} catch (Exception e) {
logger.trace("setRemoveOnCancelPolicy", e);
}
}
// By default, a ScheduledThreadPoolExecutor will keep jobs
// in its queue even after they have been cancelled. They
// will only be removed when their scheduled time arrives.
@ -277,12 +282,25 @@ public class EventClient implements EventConsumer, NotificationManager {
// this EventClient, this can lead to a moderately large number
// of objects remaining referenced until the renewal time
// arrives. Hence the above call, which removes the job from
// the queue as soon as it is cancelled.
// the queue as soon as it is cancelled. Since the call is
// new with JDK 7, we invoke it via reflection to make it
// easier to use this code on JDK 6.
return executor;
}
};
return leaseRenewerThreadPool.getThreadPoolExecutor(create);
}
private static final Method setRemoveOnCancelPolicy;
static {
Method m;
try {
m = ScheduledThreadPoolExecutor.class.getMethod(
"setRemoveOnCancelPolicy", boolean.class);
} catch (Exception e) {
m = null;
}
setRemoveOnCancelPolicy = m;
}
/**
@ -1042,7 +1060,7 @@ public class EventClient implements EventConsumer, NotificationManager {
final public EventClient call() throws Exception {
EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn);
return new EventClient(ecd, eventRelay, null, null,
DEFAULT_LEASE_TIMEOUT);
DEFAULT_REQUESTED_LEASE_TIME);
}
};
@ -1080,24 +1098,6 @@ public class EventClient implements EventConsumer, NotificationManager {
return clientId;
}
/**
* Returns a JMX Connector that will use an {@link EventClient}
* to subscribe for notifications. If the server doesn't have
* an {@link EventClientDelegateMBean}, then the connector will
* use the legacy notification mechanism instead.
*
* @param wrapped The underlying JMX Connector wrapped by the returned
* connector.
*
* @return A JMX Connector that will uses an {@link EventClient}, if
* available.
*
* @see EventClient#getEventClientConnection(MBeanServerConnection)
*/
public static JMXConnector withEventClient(final JMXConnector wrapped) {
return JMXNamespaceUtils.withEventClient(wrapped);
}
private static final PerThreadGroupPool<ScheduledThreadPoolExecutor>
leaseRenewerThreadPool = PerThreadGroupPool.make();
}

View File

@ -149,6 +149,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
// of a setMBeanServer on some other forwarder later in the chain.
private static class Forwarder extends SingleMBeanForwarder {
private MBeanServer loopMBS;
private static class UnsupportedInvocationHandler
implements InvocationHandler {
@ -173,7 +174,11 @@ public class EventClientDelegate implements EventClientDelegateMBean {
private volatile boolean madeECD;
Forwarder() {
super(OBJECT_NAME, makeUnsupportedECD());
super(OBJECT_NAME, makeUnsupportedECD(), true);
}
synchronized void setLoopMBS(MBeanServer loopMBS) {
this.loopMBS = loopMBS;
}
@Override
@ -186,7 +191,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
AccessController.doPrivileged(
new PrivilegedAction<EventClientDelegate>() {
public EventClientDelegate run() {
return getEventClientDelegate(Forwarder.this);
return getEventClientDelegate(loopMBS);
}
});
DynamicMBean mbean = new StandardMBean(
@ -208,11 +213,46 @@ public class EventClientDelegate implements EventClientDelegateMBean {
* that are targeted for that MBean and handles them itself. All other
* requests are forwarded to the next element in the forwarder chain.</p>
*
* @param nextMBS the next {@code MBeanServer} in the chain of forwarders,
* which might be another {@code MBeanServerForwarder} or a plain {@code
* MBeanServer}. This is the object to which {@code MBeanServer} requests
* that do not concern the {@code EventClientDelegateMBean} are sent.
* It will be the value of {@link MBeanServerForwarder#getMBeanServer()
* getMBeanServer()} on the returned object, and can be changed with {@link
* MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
* must be set to a non-null value before any {@code MBeanServer} requests
* arrive.
*
* @param loopMBS the {@code MBeanServer} to which requests from the
* {@code EventClientDelegateMBean} should be sent. For example,
* when you invoke the {@link EventClientDelegateMBean#addListener
* addListener} operation on the {@code EventClientDelegateMBean}, it will
* result in a call to {@link
* MBeanServer#addNotificationListener(ObjectName, NotificationListener,
* NotificationFilter, Object) addNotificationListener} on this object.
* If this parameter is null, then these requests will be sent to the
* newly-created {@code MBeanServerForwarder}. Usually the parameter will
* either be null or will be the result of {@link
* javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder()
* getSystemMBeanServerForwarder()} for the connector server in which
* this forwarder will be installed.
*
* @return a new {@code MBeanServerForwarder} that simulates the existence
* of an {@code EventClientDelegateMBean}.
*
* @see javax.management.remote.JMXConnectorServer#installStandardForwarders
*/
public static MBeanServerForwarder newForwarder() {
return new Forwarder();
public static MBeanServerForwarder newForwarder(
MBeanServer nextMBS, MBeanServer loopMBS) {
Forwarder mbsf = new Forwarder();
// We must setLoopMBS before setMBeanServer, because when we
// setMBeanServer that will call getEventClientDelegate(loopMBS).
if (loopMBS == null)
loopMBS = mbsf;
mbsf.setLoopMBS(loopMBS);
if (nextMBS != null)
mbsf.setMBeanServer(nextMBS);
return mbsf;
}
/**
@ -437,10 +477,9 @@ public class EventClientDelegate implements EventClientDelegateMBean {
// private classes
// ------------------------------------
private class ClientInfo {
String clientId;
EventBuffer buffer;
NotificationListener clientListener;
Map<Integer, AddedListener> listenerInfoMap =
final String clientId;
final NotificationListener clientListener;
final Map<Integer, AddedListener> listenerInfoMap =
new HashMap<Integer, AddedListener>();
ClientInfo(String clientId, EventForwarder forwarder) {
@ -703,7 +742,8 @@ public class EventClientDelegate implements EventClientDelegateMBean {
clientInfo = clientInfoMap.get(clientId);
if (clientInfo == null) {
throw new EventClientNotFoundException("The client is not found.");
throw new EventClientNotFoundException(
"Client not found (id " + clientId + ")");
}
return clientInfo;

View File

@ -51,7 +51,8 @@ import javax.management.remote.NotificationResult;
* and the MBean Server, that will intercept accesses to the Event Client
* Delegate MBean and treat them as the real MBean would. This forwarder is
* inserted by default with the standard RMI Connector Server, and can also
* be created explicitly using {@link EventClientDelegate#newForwarder()}.
* be created explicitly using {@link EventClientDelegate#newForwarder
* EventClientDelegate.newForwarder}.
*
* <li><p>A variant on the above is to replace the MBean Server that is
* used locally with a forwarder as described above. Since
@ -61,9 +62,7 @@ import javax.management.remote.NotificationResult;
*
* <pre>
* MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
* MBeanServerForwarder mbsf = EventClientDelegate.newForwarder();
* mbsf.setMBeanServer(mbs);
* mbs = mbsf;
* mbs = EventClientDelegate.newForwarder(mbs, null);
* // now use mbs just as you did before, but it will have an EventClientDelegate
* </pre>
*

View File

@ -27,7 +27,6 @@ package javax.management.event;
import java.io.IOException;
import java.util.concurrent.Executors; // for javadoc
import java.util.concurrent.ScheduledFuture;
/**
* This interface is used to specify a way to receive

View File

@ -83,8 +83,8 @@
* javax.management.event.EventClientDelegateMBean EventClientDelegateMBean}
* must be registered in the MBean Server, or the connector server must
* be configured to simulate the existence of this MBean, for example
* using {@link javax.management.event.EventClientDelegate#newForwarder()
* EventClientDelegate.newForwarder()}. The standard RMI connector is so
* using {@link javax.management.event.EventClientDelegate#newForwarder
* EventClientDelegate.newForwarder}. The standard RMI connector is so
* configured by default. The {@code EventClientDelegateMBean} documentation
* has further details.</p>
*

View File

@ -265,6 +265,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
* @return The derived gauge of the specified object.
*
*/
@Override
public synchronized Number getDerivedGauge(ObjectName object) {
return (Number) super.getDerivedGauge(object);
}
@ -280,6 +281,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
* @return The derived gauge timestamp of the specified object.
*
*/
@Override
public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
return super.getDerivedGaugeTimeStamp(object);
}
@ -595,6 +597,7 @@ public class CounterMonitor extends Monitor implements CounterMonitorMBean {
* name of the Java class of the notification and the notification
* types sent by the counter monitor.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo;
}

View File

@ -258,6 +258,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
* @return The derived gauge of the specified object.
*
*/
@Override
public synchronized Number getDerivedGauge(ObjectName object) {
return (Number) super.getDerivedGauge(object);
}
@ -273,6 +274,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
* @return The derived gauge timestamp of the specified object.
*
*/
@Override
public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
return super.getDerivedGaugeTimeStamp(object);
}
@ -477,6 +479,7 @@ public class GaugeMonitor extends Monitor implements GaugeMonitorMBean {
* name of the Java class of the notification and the notification
* types sent by the gauge monitor.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return notifsInfo;
}

View File

@ -34,7 +34,6 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
@ -517,7 +516,7 @@ public abstract class Monitor
//
ObservedObject o = createObservedObject(object);
o.setAlreadyNotified(RESET_FLAGS_ALREADY_NOTIFIED);
o.setDerivedGauge(null);
o.setDerivedGauge(INTEGER_ZERO);
o.setDerivedGaugeTimeStamp(System.currentTimeMillis());
observedObjects.add(o);

View File

@ -26,21 +26,19 @@
package javax.management.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.namespace.ObjectNameRouter;
import com.sun.jmx.namespace.serial.RewritingProcessor;
import com.sun.jmx.namespace.RoutingConnectionProxy;
import com.sun.jmx.namespace.RoutingServerProxy;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
/**
* Static constants and utility methods to help work with
@ -68,23 +66,6 @@ public class JMXNamespaces {
NAMESPACE_SEPARATOR.length();
/**
* Returns a connector connected to a sub name space exposed through
* the parent connector.
* @param parent the parent connector.
* @param namespace the {@linkplain javax.management.namespace name space}
* to which the returned connector is
* connected.
* @return A connector connected to a sub name space exposed through
* the parent connector.
**/
public static JMXConnector narrowToNamespace(final JMXConnector parent,
final String namespace)
throws IOException {
return JMXNamespaceUtils.cd(parent,namespace,true);
}
/**
* Creates a new {@code MBeanServerConnection} proxy on a
* {@linkplain javax.management.namespace sub name space}
@ -96,15 +77,18 @@ public class JMXNamespaces {
* name space} in which to narrow.
* @return A new {@code MBeanServerConnection} proxy that shows the content
* of that name space.
* @throws IllegalArgumentException if the name space does not exist, or
* if a proxy for that name space cannot be created.
* @throws IllegalArgumentException if either argument is null,
* or the name space does not exist, or if a proxy for that name space
* cannot be created. The {@linkplain Throwable#getCause() cause} of
* this exception will be an {@link InstanceNotFoundException} if and only
* if the name space is found not to exist.
*/
public static MBeanServerConnection narrowToNamespace(
MBeanServerConnection parent,
String namespace) {
if (LOG.isLoggable(Level.FINER))
LOG.finer("Making MBeanServerConnection for: " +namespace);
return RoutingConnectionProxy.cd(parent,namespace);
return RoutingConnectionProxy.cd(parent, namespace, true);
}
/**
@ -120,13 +104,15 @@ public class JMXNamespaces {
* of that name space.
* @throws IllegalArgumentException if either argument is null,
* or the name space does not exist, or if a proxy for that name space
* cannot be created.
* cannot be created. The {@linkplain Throwable#getCause() cause} of
* this exception will be an {@link InstanceNotFoundException} if and only
* if the name space is found not to exist.
*/
public static MBeanServer narrowToNamespace(MBeanServer parent,
String namespace) {
if (LOG.isLoggable(Level.FINER))
LOG.finer("Making NamespaceServerProxy for: " +namespace);
return RoutingServerProxy.cd(parent,namespace);
LOG.finer("Making MBeanServer for: " +namespace);
return RoutingServerProxy.cd(parent, namespace, true);
}
/**
@ -266,7 +252,7 @@ public class JMXNamespaces {
ObjectNameRouter.normalizeNamespacePath(namespace,false,
true,false);
try {
// We could use Util.newObjectName here - but throwing an
// We could use ObjectName.valueOf here - but throwing an
// IllegalArgumentException that contains just the supplied
// namespace instead of the whole ObjectName seems preferable.
return ObjectName.getInstance(sourcePath+

View File

@ -27,10 +27,10 @@ package javax.management.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
@ -39,6 +39,7 @@ import java.util.logging.Logger;
import javax.management.AttributeChangeNotification;
import javax.management.ClientContext;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
@ -220,17 +221,26 @@ public class JMXRemoteNamespace
initParentOnce(this);
// URL must not be null.
this.jmxURL = JMXNamespaceUtils.checkNonNull(sourceURL,"url");
if (sourceURL == null)
throw new IllegalArgumentException("Null URL");
this.jmxURL = sourceURL;
this.broadcaster =
new NotificationBroadcasterSupport(connectNotification);
// handles options
this.optionsMap = JMXNamespaceUtils.unmodifiableMap(optionsMap);
this.optionsMap = unmodifiableMap(optionsMap);
// handles (dis)connection events
this.listener = new ConnectionListener();
}
// returns un unmodifiable view of a map.
private static <K,V> Map<K,V> unmodifiableMap(Map<K,V> aMap) {
if (aMap == null || aMap.isEmpty())
return Collections.emptyMap();
return Collections.unmodifiableMap(aMap);
}
/**
* Returns the {@code JMXServiceURL} that is (or will be) used to
* connect to the remote name space. <p>
@ -483,106 +493,171 @@ public class JMXRemoteNamespace
}
}
JMXConnector connect(JMXServiceURL url, Map<String,?> env)
private JMXConnector connect(JMXServiceURL url, Map<String,?> env)
throws IOException {
final JMXConnector c = newJMXConnector(jmxURL, env);
final JMXConnector c = newJMXConnector(url, env);
c.connect(env);
return c;
}
/**
* Creates a new JMXConnector with the specified {@code url} and
* {@code env} options map.
* <p>
* This method first calls {@link JMXConnectorFactory#newJMXConnector
* JMXConnectorFactory.newJMXConnector(jmxURL, env)} to obtain a new
* JMX connector, and returns that.
* </p>
* <p>
* A subclass of {@link JMXRemoteNamespace} can provide an implementation
* that connects to a sub namespace of the remote server by subclassing
* this class in the following way:
* <pre>
* class JMXRemoteSubNamespace extends JMXRemoteNamespace {
* private final String subnamespace;
* JMXRemoteSubNamespace(JMXServiceURL url,
* Map{@code <String,?>} env, String subnamespace) {
* super(url,options);
* this.subnamespace = subnamespace;
* }
* protected JMXConnector newJMXConnector(JMXServiceURL url,
* Map<String,?> env) throws IOException {
* final JMXConnector inner = super.newJMXConnector(url,env);
* return {@link JMXNamespaces#narrowToNamespace(JMXConnector,String)
* JMXNamespaces.narrowToNamespace(inner,subnamespace)};
* }
* }
* </pre>
* </p>
* <p>
* Some connectors, like the JMXMP connector server defined by the
* version 1.2 of the JMX API may not have been upgraded to use the
* new {@linkplain javax.management.event Event Service} defined in this
* version of the JMX API.
* <p>
* In that case, and if the remote server to which this JMXRemoteNamespace
* connects also contains namespaces, it may be necessary to configure
* explicitly an {@linkplain
* javax.management.event.EventClientDelegate#newForwarder()
* Event Client Forwarder} on the remote server side, and to force the use
* of an {@link EventClient} on this client side.
* <br>
* A subclass of {@link JMXRemoteNamespace} can provide an implementation
* of {@code newJMXConnector} that will force notification subscriptions
* to flow through an {@link EventClient} over a legacy protocol by
* overriding this method in the following way:
* </p>
* <pre>
* class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
* JMXRemoteSubNamespaceConnector(JMXServiceURL url,
* Map<String,?> env) {
* super(url,options);
* }
* protected JMXConnector newJMXConnector(JMXServiceURL url,
* Map<String,?> env) throws IOException {
* final JMXConnector inner = super.newJMXConnector(url,env);
* return {@link EventClient#withEventClient(
* JMXConnector) EventClient.withEventClient(inner)};
* }
* }
* </pre>
* <p>
* Note that the remote server also needs to provide an {@link
* javax.management.event.EventClientDelegateMBean}: only configuring
* the client side (this object) is not enough.<br>
* In summary, this technique should be used if the remote server
* supports JMX namespaces, but uses a JMX Connector Server whose
* implementation does not transparently use the new Event Service
* (as would be the case with the JMXMPConnectorServer implementation
* from the reference implementation of the JMX Remote API 1.0
* specification).
* </p>
* <p>Creates a new JMXConnector with the specified {@code url} and
* {@code env} options map. The default implementation of this method
* returns {@link JMXConnectorFactory#newJMXConnector
* JMXConnectorFactory.newJMXConnector(jmxURL, env)}. Subclasses can
* override this method to customize behavior.</p>
*
* @param url The JMXServiceURL of the remote server.
* @param optionsMap An unmodifiable options map that will be passed to the
* @param optionsMap An options map that will be passed to the
* {@link JMXConnectorFactory} when {@linkplain
* JMXConnectorFactory#newJMXConnector creating} the
* {@link JMXConnector} that can connect to the remote source
* MBean Server.
* @return An unconnected JMXConnector to use to connect to the remote
* server
* @throws java.io.IOException if the connector could not be created.
* @return A JMXConnector to use to connect to the remote server
* @throws IOException if the connector could not be created.
* @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
* @see #JMXRemoteNamespace
*/
protected JMXConnector newJMXConnector(JMXServiceURL url,
Map<String,?> optionsMap) throws IOException {
final JMXConnector c =
JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
// TODO: uncomment this when contexts are added
// return ClientContext.withDynamicContext(c);
return c;
return JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
}
/**
* <p>Called when a new connection is established using {@link #connect}
* so that subclasses can customize the connection. The default
* implementation of this method effectively does the following:</p>
*
* <pre>
* MBeanServerConnection mbsc = {@link JMXConnector#getMBeanServerConnection()
* jmxc.getMBeanServerConnection()};
* try {
* return {@link ClientContext#withDynamicContext
* ClientContext.withDynamicContext(mbsc)};
* } catch (IllegalArgumentException e) {
* return mbsc;
* }
* </pre>
*
* <p>In other words, it arranges for the client context to be forwarded
* to the remote MBean Server if the remote MBean Server supports contexts;
* otherwise it ignores the client context.</p>
*
* <h4>Example: connecting to a remote namespace</h4>
*
* <p>A subclass that wanted to narrow into a namespace of
* the remote MBeanServer might look like this:</p>
*
* <pre>
* class JMXRemoteSubNamespace extends JMXRemoteNamespace {
* private final String subnamespace;
*
* JMXRemoteSubNamespace(
* JMXServiceURL url, Map{@code <String, ?>} env, String subnamespace) {
* super(url, env);
* this.subnamespace = subnamespace;
* }
*
* {@code @Override}
* protected MBeanServerConnection getMBeanServerConnection(
* JMXConnector jmxc) throws IOException {
* MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
* return {@link JMXNamespaces#narrowToNamespace(MBeanServerConnection,String)
* JMXNamespaces.narrowToNamespace(mbsc, subnamespace)};
* }
* }
* </pre>
*
* <h4>Example: using the Event Service for notifications</h4>
*
* <p>Some connectors may have been designed to work with an earlier
* version of the JMX API, and may not have been upgraded to use
* the {@linkplain javax.management.event Event Service} defined in
* this version of the JMX API. In that case, and if the remote
* server to which this JMXRemoteNamespace connects also contains
* namespaces, it may be necessary to configure explicitly an {@linkplain
* javax.management.event.EventClientDelegate#newForwarder Event Client
* Forwarder} on the remote server side, and to force the use of an {@link
* EventClient} on this client side.</p>
*
* <p>A subclass of {@link JMXRemoteNamespace} can provide an
* implementation of {@code getMBeanServerConnection} that will force
* notification subscriptions to flow through an {@link EventClient} over
* a legacy protocol. It can do so by overriding this method in the
* following way:</p>
*
* <pre>
* class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
* JMXRemoteEventClientNamespace(JMXServiceURL url, {@code Map<String,?>} env) {
* super(url, env);
* }
*
* {@code @Override}
* protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
* throws IOException {
* MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
* return EventClient.getEventClientConnection(mbsc);
* }
* }
* </pre>
*
* <p>
* Note that the remote server also needs to provide an {@link
* javax.management.event.EventClientDelegateMBean}: configuring only
* the client side (this object) is not enough.</p>
*
* <p>In summary, this technique should be used if the remote server
* supports JMX namespaces, but uses a JMX Connector Server whose
* implementation does not transparently use the new Event Service
* (as would be the case with the JMXMPConnectorServer implementation
* from the reference implementation of the JMX Remote API 1.0
* specification).</p>
*
* @param jmxc the newly-created {@code JMXConnector}.
*
* @return an {@code MBeanServerConnection} connected to the remote
* MBeanServer.
*
* @throws IOException if the connection cannot be made. If this method
* throws {@code IOException} then the calling {@link #connect()} method
* will also fail with an {@code IOException}.
*
* @see #connect
*/
protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
throws IOException {
final MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
try {
return ClientContext.withDynamicContext(mbsc);
} catch (IllegalArgumentException e) {
LOG.log(Level.FINER, "ClientContext.withDynamicContext", e);
return mbsc;
}
}
/**
* {@inheritDoc}
*
* <p>The sequence of events when this method is called includes,
* effectively, the following code:</p>
*
* <pre>
* JMXServiceURL url = {@link #getJMXServiceURL getJMXServiceURL}();
* JMXConnector jmxc = {@link #newJMXConnector newJMXConnector}(url, env);
* jmxc.connect();
* MBeanServerConnection mbsc = {@link #getMBeanServerConnection(JMXConnector)
* getMBeanServerConnection}(jmxc);
* </pre>
*
* <p>Here, {@code env} is a {@code Map} containing the entries from the
* {@code optionsMap} that was passed to the {@linkplain #JMXRemoteNamespace
* constructor} or to the {@link #newJMXRemoteNamespace newJMXRemoteNamespace}
* factory method.</p>
*
* <p>Subclasses can customize connection behavior by overriding the
* {@code getJMXServiceURL}, {@code newJMXConnector}, or
* {@code getMBeanServerConnection} methods.</p>
*/
public void connect() throws IOException {
LOG.fine("connecting...");
final Map<String,Object> env =
@ -590,7 +665,7 @@ public class JMXRemoteNamespace
try {
// XXX: We should probably document this...
// This allows to specify a loader name - which will be
// retrieved from the paret MBeanServer.
// retrieved from the parent MBeanServer.
defaultClassLoader =
EnvHelp.resolveServerClassLoader(env,getMBeanServer());
} catch (InstanceNotFoundException x) {
@ -604,7 +679,7 @@ public class JMXRemoteNamespace
final JMXConnector aconn = connect(url,env);
final MBeanServerConnection msc;
try {
msc = aconn.getMBeanServerConnection();
msc = getMBeanServerConnection(aconn);
aconn.addConnectionNotificationListener(listener,null,aconn);
} catch (IOException io) {
close(aconn);

View File

@ -33,12 +33,14 @@ import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
// jmx import
import java.util.TreeSet;
//
@ -60,16 +62,15 @@ public class CompositeDataSupport
* respective values.
* A {@link SortedMap} is used for faster retrieval of elements.
*/
private SortedMap<String, Object> contents = new TreeMap<String, Object>();
private final SortedMap<String, Object> contents;
/**
* @serial The <i>composite type </i> of this <i>composite data</i> instance.
*/
private CompositeType compositeType;
private final CompositeType compositeType;
/**
* <p>
* Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* <p>Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* <tt>compositeType</tt>, whose item values
* are specified by <tt>itemValues[]</tt>, in the same order as in
* <tt>itemNames[]</tt>.
@ -79,103 +80,67 @@ public class CompositeDataSupport
* The items contained in this <tt>CompositeDataSupport</tt> instance are
* internally stored in a <tt>TreeMap</tt>,
* thus sorted in ascending lexicographic order of their names, for faster
* retrieval of individual item values.
* <p>
* The constructor checks that all the constraints listed below for each
* retrieval of individual item values.</p>
*
* <p>The constructor checks that all the constraints listed below for each
* parameter are satisfied,
* and throws the appropriate exception if they are not.
* <p>
* @param compositeType the <i>composite type </i> of this <i>composite
* data</i> instance;
* must not be null.
* <p>
* @param itemNames <tt>itemNames</tt> must list, in any order, all the
* item names defined in <tt>compositeType</tt>;
* the order in which the names are listed, is used to
* match values in <tt>itemValues[]</tt>;
* must not be null or empty.
* <p>
* @param itemValues the values of the items, listed in the same order as
* their respective names in <tt>itemNames</tt>;
* each item value can be null, but if it is non-null it must be
* a valid value for the open type defined in <tt>compositeType</tt> for the corresponding item;
* must be of the same size as <tt>itemNames</tt>; must not be null or empty.
* <p>
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty,
* or one of the elements in <tt>itemNames[]</tt> is a null or empty string,
* or <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
* <p>
* @throws OpenDataException <tt>itemNames[]</tt> or <tt>itemValues[]</tt>'s size differs from
* the number of items defined in <tt>compositeType</tt>,
* or one of the elements in <tt>itemNames[]</tt> does not exist as an item name defined in <tt>compositeType</tt>,
* or one of the elements in <tt>itemValues[]</tt> is not a valid value for the corresponding item
* as defined in <tt>compositeType</tt>.
* <p>
* and throws the appropriate exception if they are not.</p>
*
* @param compositeType the <i>composite type </i> of this <i>composite
* data</i> instance; must not be null.
*
* @param itemNames <tt>itemNames</tt> must list, in any order, all the
* item names defined in <tt>compositeType</tt>; the order in which the
* names are listed, is used to match values in <tt>itemValues[]</tt>; must
* not be null.
*
* @param itemValues the values of the items, listed in the same order as
* their respective names in <tt>itemNames</tt>; each item value can be
* null, but if it is non-null it must be a valid value for the open type
* defined in <tt>compositeType</tt> for the corresponding item; must be of
* the same size as <tt>itemNames</tt>; must not be null.
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
* of the elements in <tt>itemNames[]</tt> is a null or empty string, or
* <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
*
* @throws OpenDataException <tt>itemNames[]</tt> or
* <tt>itemValues[]</tt>'s size differs from the number of items defined in
* <tt>compositeType</tt>, or one of the elements in <tt>itemNames[]</tt>
* does not exist as an item name defined in <tt>compositeType</tt>, or one
* of the elements in <tt>itemValues[]</tt> is not a valid value for the
* corresponding item as defined in <tt>compositeType</tt>.
*/
public CompositeDataSupport(CompositeType compositeType, String[] itemNames, Object[] itemValues)
throws OpenDataException {
public CompositeDataSupport(
CompositeType compositeType, String[] itemNames, Object[] itemValues)
throws OpenDataException {
this(makeMap(itemNames, itemValues), compositeType);
}
// Check compositeType is not null
//
if (compositeType == null) {
throw new IllegalArgumentException("Argument compositeType cannot be null.");
}
private static SortedMap<String, Object> makeMap(
String[] itemNames, Object[] itemValues)
throws OpenDataException {
// item names defined in compositeType:
Set<String> namesSet = compositeType.keySet();
// Check the array itemNames is not null or empty (length!=0) and
// that there is no null element or empty string in it
//
checkForNullElement(itemNames, "itemNames");
checkForEmptyString(itemNames, "itemNames");
// Check the array itemValues is not null or empty (length!=0)
// (NOTE: we allow null values as array elements)
//
if ( (itemValues == null) || (itemValues.length == 0) ) {
throw new IllegalArgumentException("Argument itemValues[] cannot be null or empty.");
}
// Check that the sizes of the 2 arrays itemNames and itemValues are the same
//
if (itemNames == null || itemValues == null)
throw new IllegalArgumentException("Null itemNames or itemValues");
if (itemNames.length != itemValues.length) {
throw new IllegalArgumentException("Array arguments itemNames[] and itemValues[] "+
"should be of same length (got "+ itemNames.length +
" and "+ itemValues.length +").");
throw new IllegalArgumentException(
"Different lengths: itemNames[" + itemNames.length +
"], itemValues[" + itemValues.length + "]");
}
// Check the size of the 2 arrays is equal to the number of items defined in compositeType
//
if (itemNames.length != namesSet.size()) {
throw new OpenDataException("The size of array arguments itemNames[] and itemValues[] should be equal to the number of items defined"+
" in argument compositeType (found "+ itemNames.length +" elements in itemNames[] and itemValues[],"+
" expecting "+ namesSet.size() +" elements according to compositeType.");
SortedMap<String, Object> map = new TreeMap<String, Object>();
for (int i = 0; i < itemNames.length; i++) {
String name = itemNames[i];
if (name == null || name.equals(""))
throw new IllegalArgumentException("Null or empty item name");
if (map.containsKey(name))
throw new OpenDataException("Duplicate item name " + name);
map.put(itemNames[i], itemValues[i]);
}
// Check parameter itemNames[] contains all names defined in the compositeType of this instance
//
if ( ! Arrays.asList(itemNames).containsAll(namesSet) ) {
throw new OpenDataException("Argument itemNames[] does not contain all names defined in the compositeType of this instance.");
}
// Check each element of itemValues[], if not null, is of the open type defined for the corresponding item
//
OpenType<?> itemType;
for (int i=0; i<itemValues.length; i++) {
itemType = compositeType.getType(itemNames[i]);
if ( (itemValues[i] != null) && (! itemType.isValue(itemValues[i])) ) {
throw new OpenDataException("Argument's element itemValues["+ i +"]=\""+ itemValues[i] +"\" is not a valid value for"+
" this item (itemName="+ itemNames[i] +",itemType="+ itemType +").");
}
}
// Initialize internal fields: compositeType and contents
//
this.compositeType = compositeType;
for (int i=0; i<itemNames.length; i++) {
this.contents.put(itemNames[i], itemValues[i]);
}
return map;
}
/**
@ -184,64 +149,99 @@ public class CompositeDataSupport
* are given by the mappings in the map <tt>items</tt>.
* This constructor converts the keys to a string array and the values to an object array and calls
* <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
* <p>
*
* @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
* must not be null.
* <p>
* @param items the mappings of all the item names to their values;
* <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
* must not be null or empty.
* <p>
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>items</tt> is null or empty,
* or one of the keys in <tt>items</tt> is a null or empty string,
* or one of the values in <tt>items</tt> is null.
* <p>
* @throws OpenDataException <tt>items</tt>' size differs from the number of items defined in <tt>compositeType</tt>,
* or one of the keys in <tt>items</tt> does not exist as an item name defined in <tt>compositeType</tt>,
* or one of the values in <tt>items</tt> is not a valid value for the corresponding item
* as defined in <tt>compositeType</tt>.
* <p>
* @throws ArrayStoreException one or more keys in <tt>items</tt> is not of the class <tt>java.lang.String</tt>.
* <p>
* must not be null.
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* <tt>items</tt> is null, or one of the keys in <tt>items</tt> is a null
* or empty string.
* @throws OpenDataException <tt>items</tt>' size differs from the
* number of items defined in <tt>compositeType</tt>, or one of the
* keys in <tt>items</tt> does not exist as an item name defined in
* <tt>compositeType</tt>, or one of the values in <tt>items</tt>
* is not a valid value for the corresponding item as defined in
* <tt>compositeType</tt>.
* @throws ArrayStoreException one or more keys in <tt>items</tt> is not of
* the class <tt>java.lang.String</tt>.
*
* @see #toMap
*/
public CompositeDataSupport(CompositeType compositeType,
Map<String,?> items)
throws OpenDataException {
this(makeMap(items), compositeType);
}
private static SortedMap<String, Object> makeMap(Map<String, ?> items) {
if (items == null)
throw new IllegalArgumentException("Null items map");
if (items.containsKey(null) || items.containsKey(""))
throw new IllegalArgumentException("Null or empty item name");
// Let the other constructor do the job, as the call to another constructor must be the first call
SortedMap<String, Object> map = new TreeMap<String, Object>();
for (Object key : items.keySet()) {
if (!(key instanceof String)) {
throw new ArrayStoreException("Item name is not string: " + key);
// This can happen because of erasure. The particular
// exception is a historical artifact - an implementation
// detail that leaked into the API.
}
map.put((String) key, items.get(key));
}
return map;
}
private CompositeDataSupport(
SortedMap<String, Object> items, CompositeType compositeType)
throws OpenDataException {
// Check compositeType is not null
//
this( compositeType,
(items==null ? null : items.keySet().toArray(new String[items.size()])), // may raise an ArrayStoreException
(items==null ? null : items.values().toArray()) );
}
/**
*
*/
private static void checkForNullElement(Object[] arg, String argName) {
if ( (arg == null) || (arg.length == 0) ) {
throw new IllegalArgumentException(
"Argument "+ argName +"[] cannot be null or empty.");
if (compositeType == null) {
throw new IllegalArgumentException("Argument compositeType cannot be null.");
}
for (int i=0; i<arg.length; i++) {
if (arg[i] == null) {
throw new IllegalArgumentException(
"Argument's element "+ argName +"["+ i +"] cannot be null.");
// item names defined in compositeType:
Set<String> namesFromType = compositeType.keySet();
Set<String> namesFromItems = items.keySet();
// This is just a comparison, but we do it this way for a better
// exception message.
if (!namesFromType.equals(namesFromItems)) {
Set<String> extraFromType = new TreeSet<String>(namesFromType);
extraFromType.removeAll(namesFromItems);
Set<String> extraFromItems = new TreeSet<String>(namesFromItems);
extraFromItems.removeAll(namesFromType);
if (!extraFromType.isEmpty() || !extraFromItems.isEmpty()) {
throw new OpenDataException(
"Item names do not match CompositeType: " +
"names in items but not in CompositeType: " + extraFromItems +
"; names in CompositeType but not in items: " + extraFromType);
}
}
}
/**
*
*/
private static void checkForEmptyString(String[] arg, String argName) {
for (int i=0; i<arg.length; i++) {
if (arg[i].trim().equals("")) {
throw new IllegalArgumentException(
"Argument's element "+ argName +"["+ i +"] cannot be an empty string.");
// Check each value, if not null, is of the open type defined for the
// corresponding item
for (String name : namesFromType) {
Object value = items.get(name);
if (value != null) {
OpenType<?> itemType = compositeType.getType(name);
if (!itemType.isValue(value)) {
throw new OpenDataException(
"Argument value of wrong type for item " + name +
": value " + value + ", type " + itemType);
}
}
}
// Initialize internal fields: compositeType and contents
//
this.compositeType = compositeType;
this.contents = items;
}
/**
@ -328,6 +328,54 @@ public class CompositeDataSupport
return Collections.unmodifiableCollection(contents.values());
}
/**
* <p>Returns a Map representing the contents of the given CompositeData.
* Each item in the CompositeData is represented by an entry in the map,
* where the name and value of the item are the key and value of the entry.
* The returned value is modifiable but modifications to it have no effect
* on the original CompositeData.</p>
*
* <p>For example, if you have a CompositeData {@code cd1} and you want
* to produce another CompositeData {@code cd2} which is the same except
* that the value of its {@code id} item has been changed to 253, you
* could write:</p>
*
* <pre>
* CompositeData cd1 = ...;
* {@code Map<String, Object>} map = CompositeDataSupport.toMap(cd1);
* assert(map.get("id") instanceof Integer);
* map.put("id", 253);
* CompositeData cd2 = {@link #CompositeDataSupport(CompositeType, Map)
* new CompositeDataSupport}(cd1.getCompositeType(), map);
* </pre>
*
* <p>Logically, this method would be a method in the {@link CompositeData}
* interface, but cannot be for compatibility reasons.</p>
*
* @param cd the CompositeData to convert to a Map.
*
* @return a Map that is a copy of the contents of {@code cd}.
*
* @throws IllegalArgumentException if {@code cd} is null.
*
* @see #CompositeDataSupport(CompositeType, Map)
*/
public static Map<String, Object> toMap(CompositeData cd) {
if (cd == null)
throw new IllegalArgumentException("Null argument");
// If we really wanted, we could check whether cd is a
// CompositeDataSupport and return a copy of cd.contents if so,
// but I don't think that would be substantially faster.
Map<String, Object> map = new LinkedHashMap<String, Object>();
CompositeType ct = cd.getCompositeType();
for (String key : ct.keySet()) {
Object value = cd.get(key);
map.put(key, value);
}
return map;
}
/**
* Compares the specified <var>obj</var> parameter with this
* <code>CompositeDataSupport</code> instance for equality.

View File

@ -1,7 +1,7 @@
<html>
<head>
<title>javax.management package</title>
<!--
<head>
<title>javax.management package</title>
<!--
Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -24,37 +24,37 @@ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
CA 95054 USA or visit www.sun.com if you need additional information or
have any questions.
-->
</head>
<body bgcolor="white">
<p>Provides the core classes for the Java Management Extensions.</p>
-->
</head>
<body bgcolor="white">
<p>Provides the core classes for the Java Management Extensions.</p>
<p>The Java Management Extensions
(JMX<sup><font size="-1">TM</font></sup>) API is a standard
API for management and monitoring. Typical uses include:</p>
<p>The Java Management Extensions
(JMX<sup><font size="-1">TM</font></sup>) API is a standard
API for management and monitoring. Typical uses include:</p>
<ul>
<li>consulting and changing application configuration</li>
<ul>
<li>consulting and changing application configuration</li>
<li>accumulating statistics about application behavior and
making them available</li>
<li>accumulating statistics about application behavior and
making them available</li>
<li>notifying of state changes and erroneous conditions.</li>
</ul>
<li>notifying of state changes and erroneous conditions.</li>
</ul>
<p>The JMX API can also be used as part of a solution for
managing systems, networks, and so on.</p>
<p>The JMX API can also be used as part of a solution for
managing systems, networks, and so on.</p>
<p>The API includes remote access, so a remote management
program can interact with a running application for these
purposes.</p>
<p>The API includes remote access, so a remote management
program can interact with a running application for these
purposes.</p>
<h2>MBeans</h2>
<h2>MBeans</h2>
<p>The fundamental notion of the JMX API is the <em>MBean</em>.
An MBean is a named <em>managed object</em> representing a
resource. It has a <em>management interface</em> consisting
of:</p>
<p>The fundamental notion of the JMX API is the <em>MBean</em>.
An MBean is a named <em>managed object</em> representing a
resource. It has a <em>management interface</em> consisting
of:</p>
<ul>
<li>named and typed attributes that can be read and/or
@ -92,40 +92,40 @@ have any questions.
<pre>
public interface ConfigurationMBean {
public int getCacheSize();
public void setCacheSize(int size);
public long getLastChangedTime();
public void save();
public int getCacheSize();
public void setCacheSize(int size);
public long getLastChangedTime();
public void save();
}
</pre>
</pre>
<p>The methods <code>getCacheSize</code> and
<code>setCacheSize</code> define a read-write attribute of
type <code>int</code> called <code>CacheSize</code> (with an
initial capital, unlike the JavaBeans convention).</p>
<p>The methods <code>getCacheSize</code> and
<code>setCacheSize</code> define a read-write attribute of
type <code>int</code> called <code>CacheSize</code> (with an
initial capital, unlike the JavaBeans convention).</p>
<p>The method <code>getLastChangedTime</code> defines an
attribute of type <code>long</code> called
<code>LastChangedTime</code>. This is a read-only attribute,
since there is no method <code>setLastChangedTime</code>.</p>
<p>The method <code>getLastChangedTime</code> defines an
attribute of type <code>long</code> called
<code>LastChangedTime</code>. This is a read-only attribute,
since there is no method <code>setLastChangedTime</code>.</p>
<p>The method <code>save</code> defines an operation called
<code>save</code>. It is not an attribute, since its name
does not begin with <code>get</code>, <code>set</code>, or
<code>is</code>.</p>
<p>The method <code>save</code> defines an operation called
<code>save</code>. It is not an attribute, since its name
does not begin with <code>get</code>, <code>set</code>, or
<code>is</code>.</p>
<p>The exact naming patterns for Standard MBeans are detailed in
the <a href="#spec">JMX Specification</a>.</p>
<p>The exact naming patterns for Standard MBeans are detailed in
the <a href="#spec">JMX Specification</a>.</p>
<p>There are two ways to make a Java object that is an MBean
with this management interface. One is for the object to be
of a class that has exactly the same name as the Java
interface but without the <code>MBean</code> suffix. So in
the example the object would be of the class
<code>Configuration</code>, in the same Java package as
<code>ConfigurationMBean</code>. The second way is to use the
{@link javax.management.StandardMBean StandardMBean}
class.</p>
<p>There are two ways to make a Java object that is an MBean
with this management interface. One is for the object to be
of a class that has exactly the same name as the Java
interface but without the <code>MBean</code> suffix. So in
the example the object would be of the class
<code>Configuration</code>, in the same Java package as
<code>ConfigurationMBean</code>. The second way is to use the
{@link javax.management.StandardMBean StandardMBean}
class.</p>
<h3 id="stdannot">Defining Standard MBeans with annotations</h3>
@ -272,37 +272,37 @@ have any questions.
<pre>
int cacheSize = mbs.getAttribute(name, "CacheSize");
{@link javax.management.Attribute Attribute} newCacheSize =
new Attribute("CacheSize", new Integer(2000));
new Attribute("CacheSize", new Integer(2000));
mbs.setAttribute(name, newCacheSize);
mbs.invoke(name, "save", new Object[0], new Class[0]);
</pre>
</pre>
<p id="proxy">Alternatively, if you have a Java interface that
corresponds to the management interface for the MBean, you can use an
<em>MBean proxy</em> like this:</p>
<pre>
<pre>
ConfigurationMBean conf =
{@link javax.management.JMX#newMBeanProxy
JMX.newMBeanProxy}(mbs, name, ConfigurationMBean.class);
int cacheSize = conf.getCacheSize();
conf.setCacheSize(2000);
conf.save();
</pre>
</pre>
<p>Using an MBean proxy is just a convenience. The second
example ends up calling the same <code>MBeanServer</code>
operations as the first one.</p>
<p>Using an MBean proxy is just a convenience. The second
example ends up calling the same <code>MBeanServer</code>
operations as the first one.</p>
<p>An MBean Server can be queried for MBeans whose names match
certain patterns and/or whose attributes meet certain
constraints. Name patterns are constructed using the {@link
javax.management.ObjectName ObjectName} class and constraints
are constructed using the {@link javax.management.Query Query}
class. The methods {@link
javax.management.MBeanServer#queryNames queryNames} and {@link
javax.management.MBeanServer#queryMBeans queryMBeans} then
perform the query.</p>
<p>An MBean Server can be queried for MBeans whose names match
certain patterns and/or whose attributes meet certain
constraints. Name patterns are constructed using the {@link
javax.management.ObjectName ObjectName} class and constraints
are constructed using the {@link javax.management.Query Query}
class. The methods {@link
javax.management.MBeanServer#queryNames queryNames} and {@link
javax.management.MBeanServer#queryMBeans queryMBeans} then
perform the query.</p>
<h3>MBean lifecycle and resource injection</h3>
@ -407,6 +407,92 @@ have any questions.
So for example an SNMP GET operation might result in a
<code>getAttribute</code> on the MBean Server.</p>
<h3 id="interop">Interoperability between versions of the JMX
specification</h3>
<p>When a client connects to a server using the JMX Remote
API, it is possible that they do not have the same version
of the JMX specification. The version of the JMX
specification described here is version 2.0. Previous
versions were 1.0, 1.1, 1.2, and 1.4. (There was no 1.3.)
The standard JMX Remote API is defined to work with version
1.2 onwards, so in standards-based deployment the only
interoperability questions that arise concern version 1.2
onwards.</p>
<p>Every version of the JMX specification continues to
implement the features of previous versions. So when the
client is running an earlier version than the server, there
should not be any interoperability concerns. The only
exception is the unlikely one where a pre-2.0 client used
the string {@code //} in the domain part of an {@link
javax.management.ObjectName ObjectName}.</p>
<p>When the client is running a later version than the server,
certain newer features may not be available, as detailed in
the next sections. The method {@link
javax.management.JMX#getSpecificationVersion
JMX.getSpecificationVersion} can be used to determine the
server version to check if required features are
available.</p>
<h4 id="interop-1.4">If the remote MBean Server is 1.4</h4>
<ul>
<li><p>You cannot use {@link
javax.management.QueryNotificationFilter
QueryNotificationFilter} in {@link
javax.management.MBeanServerConnection#addNotificationListener
addNotificationListener} since this class did not exist
in 1.4.</p>
<li><p>In an attribute in a query, you cannot access values
inside complex types using dot syntax, for example
{@link javax.management.Query#attr Query.attr}{@code
("HeapMemoryUsage.used")}.</p>
<li><p>The packages {@link javax.management.event} and
{@link javax.management.namespace} did not exist in 1.4,
so you cannot remotely create instances of the MBeans
they define.</p>
<li><p>Even if the remote MBean Server is 2.0, you cannot in
general suppose that {@link
javax.management.event.EventClient EventClient} or
{@link javax.management.ClientContext ClientContext}
will work there without first checking. If the remote
MBean Server is 1.4 then those checks will return false.
An attempt to use these features without checking will
fail in the same way as for a remote 2.0 that is not
configured to support them.</p>
</ul>
<h4 id="interop-1.2">If the remote MBean Server is 1.2</h4>
<p><b>In addition to the above</b>,</p>
<ul>
<li><p>You cannot use wildcards in a key property of an
{@link javax.management.ObjectName ObjectName}, for
example {@code domain:type=Foo,name=*}. Wildcards that
match whole properties are still allowed, for example
{@code *:*} or {@code *:type=Foo,*}.</p>
<li><p>You cannot use {@link
javax.management.Query#isInstanceOf Query.isInstanceOf}
in a query.</p>
<li><p>You cannot use dot syntax such as {@code
HeapMemoryUsage.used} in the {@linkplain
javax.management.monitor.Monitor#setObservedAttribute
observed attribute} of a monitor, as described in the
documentation for the {@link javax.management.monitor}
package.</p>
</ul>
<p id="spec">
@see <a href="{@docRoot}/../technotes/guides/jmx/index.html">
Java SE 6 Platform documentation on JMX technology</a>

View File

@ -322,10 +322,12 @@ public class JMXConnectorFactory {
JMXConnectorProvider.class;
final String protocol = serviceURL.getProtocol();
final String providerClassName = "ClientProvider";
final JMXServiceURL providerURL = serviceURL;
JMXConnectorProvider provider =
getProvider(serviceURL, envcopy, providerClassName,
targetInterface, loader);
JMXConnectorProvider provider = getProvider(providerURL, envcopy,
providerClassName,
targetInterface,
loader);
IOException exception = null;
if (provider == null) {
@ -336,7 +338,7 @@ public class JMXConnectorFactory {
if (loader != null) {
try {
JMXConnector connection =
getConnectorAsService(loader, serviceURL, envcopy);
getConnectorAsService(loader, providerURL, envcopy);
if (connection != null)
return connection;
} catch (JMXProviderException e) {
@ -345,8 +347,7 @@ public class JMXConnectorFactory {
exception = e;
}
}
provider =
getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
provider = getProvider(protocol, PROTOCOL_PROVIDER_DEFAULT_PACKAGE,
JMXConnectorFactory.class.getClassLoader(),
providerClassName, targetInterface);
}
@ -448,9 +449,10 @@ public class JMXConnectorFactory {
getProviderIterator(JMXConnectorProvider.class, loader);
JMXConnector connection;
IOException exception = null;
while(providers.hasNext()) {
while (providers.hasNext()) {
JMXConnectorProvider provider = providers.next();
try {
connection = providers.next().newJMXConnector(url, map);
connection = provider.newJMXConnector(url, map);
return connection;
} catch (JMXProviderException e) {
throw e;
@ -553,4 +555,5 @@ public class JMXConnectorFactory {
private static String protocol2package(String protocol) {
return protocol.replace('+', '.').replace('-', '_');
}
}

View File

@ -33,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.management.ClientContext;
import javax.management.MBeanInfo; // for javadoc
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
@ -101,6 +102,56 @@ public abstract class JMXConnectorServer
public static final String DELEGATE_TO_EVENT_SERVICE =
"jmx.remote.delegate.event.service";
/**
* <p>Name of the attribute that specifies whether this connector
* server allows clients to communicate a context with each request.
* The value associated with this attribute, if any, must be a string
* that is equal to {@code "true"} or {@code "false"}, ignoring case.
* If it is {@code "true"}, then the connector server will simulate
* a namespace {@code jmx.context//}, as described in
* {@link ClientContext#newContextForwarder}. This namespace is needed
* for {@link ClientContext#withContext ClientContext.withContext} to
* function correctly.</p>
*
* <p>Not all connector servers will understand this attribute, but the
* standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
* RMI Connector Server} does. For a connector server that understands
* this attribute, the default value is {@code "true"}.</p>
*
* @since 1.7
*/
public static final String CONTEXT_FORWARDER =
"jmx.remote.context.forwarder";
/**
* <p>Name of the attribute that specifies whether this connector server
* localizes the descriptions in the {@link MBeanInfo} object returned by
* {@link MBeanServer#getMBeanInfo MBeanServer.getMBeanInfo}, based on the
* locale communicated by the client.</p>
*
* <p>The value associated with this attribute, if any, must be a string
* that is equal to {@code "true"} or {@code "false"}, ignoring case.
* If it is {@code "true"}, then the connector server will localize
* {@code MBeanInfo} descriptions as specified in {@link
* ClientContext#newLocalizeMBeanInfoForwarder}.</p>
*
* <p>Not all connector servers will understand this attribute, but the
* standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
* RMI Connector Server} does. For a connector server that understands
* this attribute, the default value is {@code "false"}.</p>
*
* <p>Because localization requires the client to be able to communicate
* its locale, it does not make sense to specify this attribute as
* {@code "true"} if {@link #CONTEXT_FORWARDER} is not also {@code "true"}.
* For a connector server that understands these attributes, specifying
* this inconsistent combination will result in an {@link
* IllegalArgumentException}.</p>
*
* @since 1.7
*/
public static final String LOCALIZE_MBEAN_INFO_FORWARDER =
"jmx.remote.localize.mbean.info";
/**
* <p>Name of the attribute that specifies whether this connector
* server simulates the existence of the {@link EventClientDelegate}
@ -155,7 +206,7 @@ public abstract class JMXConnectorServer
* to, or null if it is not yet attached to an MBean server.
*
* @see #setMBeanServerForwarder
* @see #getSystemMBeanServer
* @see #getSystemMBeanServerForwarder
*/
public synchronized MBeanServer getMBeanServer() {
return userMBeanServer;
@ -176,30 +227,36 @@ public abstract class JMXConnectorServer
* this method, the first occurrence in the chain of an object that is
* {@linkplain Object#equals equal} to {@code mbsf} will have been
* removed.</p>
*
* @param mbsf the forwarder to remove
*
* @throws NoSuchElementException if there is no occurrence of {@code mbsf}
* in the chain.
* @throws IllegalArgumentException if {@code mbsf} is null.
* @throws IllegalArgumentException if {@code mbsf} is null or is the
* {@linkplain #getSystemMBeanServerForwarder() system forwarder}.
*
* @since 1.7
*/
public synchronized void removeMBeanServerForwarder(MBeanServerForwarder mbsf) {
if (mbsf == null)
throw new IllegalArgumentException("Invalid null argument: mbsf");
if (systemMBeanServerForwarder.equals(mbsf))
throw new IllegalArgumentException("Cannot remove system forwarder");
MBeanServerForwarder prev = null;
MBeanServer curr = systemMBeanServer;
while (curr instanceof MBeanServerForwarder && !mbsf.equals(curr)) {
prev = (MBeanServerForwarder) curr;
MBeanServerForwarder prev = systemMBeanServerForwarder;
MBeanServer curr;
while (true) {
curr = prev.getMBeanServer();
if (mbsf.equals(curr))
break;
if (curr instanceof MBeanServerForwarder)
prev = (MBeanServerForwarder) curr;
else
throw new NoSuchElementException("MBeanServerForwarder not in chain");
}
if (!(curr instanceof MBeanServerForwarder))
throw new NoSuchElementException("MBeanServerForwarder not in chain");
MBeanServerForwarder deleted = (MBeanServerForwarder) curr;
MBeanServer next = deleted.getMBeanServer();
if (prev != null)
prev.setMBeanServer(next);
if (systemMBeanServer == deleted)
systemMBeanServer = next;
if (userMBeanServer == deleted)
MBeanServer next = mbsf.getMBeanServer();
prev.setMBeanServer(next);
if (userMBeanServer == mbsf)
userMBeanServer = next;
}
@ -209,66 +266,63 @@ public abstract class JMXConnectorServer
* the systemMBeanServer and userMBeanServer field declarations.
*/
private void insertUserMBeanServer(MBeanServer mbs) {
MBeanServerForwarder lastSystemMBSF = null;
for (MBeanServer mbsi = systemMBeanServer;
mbsi != userMBeanServer;
mbsi = lastSystemMBSF.getMBeanServer()) {
MBeanServerForwarder lastSystemMBSF = systemMBeanServerForwarder;
while (true) {
MBeanServer mbsi = lastSystemMBSF.getMBeanServer();
if (mbsi == userMBeanServer)
break;
lastSystemMBSF = (MBeanServerForwarder) mbsi;
}
userMBeanServer = mbs;
if (lastSystemMBSF == null)
systemMBeanServer = mbs;
else
lastSystemMBSF.setMBeanServer(mbs);
lastSystemMBSF.setMBeanServer(mbs);
}
/**
* <p>Returns the first item in the chain of system and then user
* forwarders. In the simplest case, a {@code JMXConnectorServer}
* is connected directly to an {@code MBeanServer}. But there can
* also be a chain of {@link MBeanServerForwarder}s between the two.
* This chain consists of two sub-chains: first the <em>system chain</em>
* and then the <em>user chain</em>. Incoming requests are given to the
* first forwarder in the system chain. Each forwarder can handle
* a request itself, or more usually forward it to the next forwarder,
* perhaps with some extra behavior such as logging or security
* checking before or after the forwarding. The last forwarder in
* the system chain is followed by the first forwarder in the user
* chain.</p>
* forwarders. There is a chain of {@link MBeanServerForwarder}s between
* a {@code JMXConnectorServer} and its {@code MBeanServer}. This chain
* consists of two sub-chains: first the <em>system chain</em> and then
* the <em>user chain</em>. Incoming requests are given to the first
* forwarder in the system chain. Each forwarder can handle a request
* itself, or more usually forward it to the next forwarder, perhaps with
* some extra behavior such as logging or security checking before or after
* the forwarding. The last forwarder in the system chain is followed by
* the first forwarder in the user chain.</p>
*
* <p>The <em>system chain</em> is usually
* defined by a connector server based on the environment Map;
* see {@link JMXConnectorServerFactory#newJMXConnectorServer}. Allowing the
* connector server to define its forwarders in this way ensures that
* they are in the correct order - some forwarders need to be inserted
* before others for correct behavior. It is possible to modify the
* system chain, for example using {@link #setSystemMBeanServerForwarder} or
* {@link #removeMBeanServerForwarder}, but in that case the system
* chain is no longer guaranteed to be correct.</p>
* <p>The object returned by this method is the first forwarder in the
* system chain. For a given {@code JMXConnectorServer}, this method
* always returns the same object, which simply forwards every request
* to the next object in the chain.</p>
*
* <p>Not all connector servers support a system chain of forwarders,
* although the standard {@linkplain
* javax.management.remote.rmi.RMIConnectorServer RMI connector
* server} does. For those that do not, this method will throw {@code
* UnsupportedOperationException}. All
* connector servers do support a user chain of forwarders.</p>
*
* <p>The <em>system chain</em> is usually defined by a
* connector server based on the environment Map; see {@link
* JMXConnectorServerFactory#newJMXConnectorServer
* JMXConnectorServerFactory.newJMXConnectorServer}. Allowing
* the connector server to define its forwarders in this way
* ensures that they are in the correct order - some forwarders
* need to be inserted before others for correct behavior. It is
* possible to modify the system chain, for example using {@code
* connectorServer.getSystemMBeanServerForwarder().setMBeanServer(mbsf)} or
* {@link #removeMBeanServerForwarder removeMBeanServerForwarder}, but in
* that case the system chain is no longer guaranteed to be correct.</p>
*
* <p>The <em>user chain</em> is defined by calling {@link
* #setMBeanServerForwarder} to insert forwarders at the head of the user
* chain.</p>
*
* <p>If there are no forwarders in either chain, then both
* {@link #getMBeanServer()} and {@code getSystemMBeanServer()} will
* return the {@code MBeanServer} for this connector server. If there
* are forwarders in the user chain but not the system chain, then
* both methods will return the first forwarder in the user chain.
* If there are forwarders in the system chain but not the user chain,
* then {@code getSystemMBeanServer()} will return the first forwarder
* in the system chain, and {@code getMBeanServer()} will return the
* {@code MBeanServer} for this connector server. Finally, if there
* are forwarders in each chain then {@code getSystemMBeanServer()}
* will return the first forwarder in the system chain, and {@code
* getMBeanServer()} will return the first forwarder in the user chain.</p>
* #setMBeanServerForwarder setMBeanServerForwarder} to insert forwarders
* at the head of the user chain.</p>
*
* <p>This code illustrates how the chains can be traversed:</p>
*
* <pre>
* JMXConnectorServer cs;
* System.out.println("system chain:");
* MBeanServer mbs = cs.getSystemMBeanServer();
* MBeanServer mbs = cs.getSystemMBeanServerForwarder();
* while (true) {
* if (mbs == cs.getMBeanServer())
* System.out.println("user chain:");
@ -281,65 +335,40 @@ public abstract class JMXConnectorServer
* System.out.println("--MBean Server");
* </pre>
*
* <h4>Note for connector server implementors</h4>
*
* <p>Existing connector server implementations can be updated to support
* a system chain of forwarders as follows:</p>
*
* <ul>
* <li><p>Override the {@link #supportsSystemMBeanServerForwarder()}
* method so that it returns true.</p>
*
* <li><p>Call {@link #installStandardForwarders} from the constructor of
* the connector server.</p>
*
* <li><p>Direct incoming requests to the result of {@link
* #getSystemMBeanServerForwarder()} instead of the result of {@link
* #getMBeanServer()}.</p>
* </ul>
*
* @return the first item in the system chain of forwarders.
*
* @see #setSystemMBeanServerForwarder
* @throws UnsupportedOperationException if {@link
* #supportsSystemMBeanServerForwarder} returns false.
*
* @see #supportsSystemMBeanServerForwarder
* @see #setMBeanServerForwarder
*
* @since 1.7
*/
public synchronized MBeanServer getSystemMBeanServer() {
return systemMBeanServer;
}
/**
* <p>Inserts an object that intercepts requests for the MBean server
* that arrive through this connector server. This object will be
* supplied as the <code>MBeanServer</code> for any new connection
* created by this connector server. Existing connections are
* unaffected.</p>
*
* <p>This method can be called more than once with different
* {@link MBeanServerForwarder} objects. The result is a chain
* of forwarders. The last forwarder added is the first in the chain.</p>
*
* <p>This method modifies the system chain of {@link MBeanServerForwarder}s.
* Usually user code should change the user chain instead, via
* {@link #setMBeanServerForwarder}.</p>
*
* <p>Not all connector servers support a system chain of forwarders.
* Calling this method on a connector server that does not will produce an
* {@link UnsupportedOperationException}.</p>
*
* <p>Suppose {@code mbs} is the result of {@link #getSystemMBeanServer()}
* before calling this method. If {@code mbs} is not null, then
* {@code mbsf.setMBeanServer(mbs)} will be called. If doing so
* produces an exception, this method throws the same exception without
* any other effect. If {@code mbs} is null, or if the call to
* {@code mbsf.setMBeanServer(mbs)} succeeds, then this method will
* return normally and {@code getSystemMBeanServer()} will then return
* {@code mbsf}.</p>
*
* <p>The result of {@link #getMBeanServer()} is unchanged by this method.</p>
*
* @param mbsf the new <code>MBeanServerForwarder</code>.
*
* @throws IllegalArgumentException if the call to {@link
* MBeanServerForwarder#setMBeanServer mbsf.setMBeanServer} fails
* with <code>IllegalArgumentException</code>, or if
* <code>mbsf</code> is null.
*
* @throws UnsupportedOperationException if
* {@link #supportsSystemMBeanServerForwarder} returns false.
*
* @see #getSystemMBeanServer()
*/
public synchronized void setSystemMBeanServerForwarder(
MBeanServerForwarder mbsf) {
if (mbsf == null)
throw new IllegalArgumentException("Invalid null argument: mbsf");
mustSupportSystemMBSF();
if (systemMBeanServer != null)
mbsf.setMBeanServer(systemMBeanServer);
systemMBeanServer = mbsf;
public MBeanServerForwarder getSystemMBeanServerForwarder() {
if (!supportsSystemMBeanServerForwarder()) {
throw new UnsupportedOperationException(
"System MBeanServerForwarder not supported by this " +
"connector server");
}
return systemMBeanServerForwarder;
}
/**
@ -350,19 +379,13 @@ public abstract class JMXConnectorServer
*
* @return true if this connector server supports the system chain of
* forwarders.
*
* @since 1.7
*/
public boolean supportsSystemMBeanServerForwarder() {
return false;
}
private void mustSupportSystemMBSF() {
if (!supportsSystemMBeanServerForwarder()) {
throw new UnsupportedOperationException(
"System MBeanServerForwarder not supported by this " +
"connector server");
}
}
/**
* <p>Install {@link MBeanServerForwarder}s in the system chain
* based on the attributes in the given {@code Map}. A connector
@ -374,34 +397,90 @@ public abstract class JMXConnectorServer
* <ul>
*
* <li>If {@link #EVENT_CLIENT_DELEGATE_FORWARDER} is absent, or is
* present with the value {@code "true"}, then a forwarder with the
* functionality of {@link EventClientDelegate#newForwarder} is inserted
* at the start of the system chain.</li>
* present with the value {@code "true"}, then a forwarder
* equivalent to {@link EventClientDelegate#newForwarder
* EventClientDelegate.newForwarder}{@code (sysMBSF.getMBeanServer(),
* sysMBSF)} is inserted at the start of the system chain,
* where {@code sysMBSF} is the object returned by {@link
* #getSystemMBeanServerForwarder()}. </li>
*
* <li>If {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is present with the
* value {@code "true"}, then a forwarder equivalent to
* {@link ClientContext#newLocalizeMBeanInfoForwarder
* ClientContext.newLocalizeMBeanInfoForwarder}{@code
* (sysMBSF.getMBeanServer())} is inserted at the start of the system
* chain.</li>
*
* <li>If {@link #CONTEXT_FORWARDER} is absent, or is present with
* the value {@code "true"}, then a forwarder equivalent to
* {@link ClientContext#newContextForwarder
* ClientContext.newContextForwarder}{@code (sysMSBF.getMBeanServer(),
* sysMBSF)} is inserted at the tart of the system chain.</li>
*
* </ul>
*
* <p>For {@code EVENT_CLIENT_DELEGATE_FORWARDER}, if the
* attribute is absent from the {@code Map} and a system property
* of the same name is defined, then the value of the system
* property is used as if it were in the {@code Map}.
* <p>For {@code EVENT_CLIENT_DELEGATE_FORWARDER} and {@code
* CONTEXT_FORWARDER}, if the attribute is absent from the {@code
* Map} and a system property of the same name is defined, then
* the value of the system property is used as if it were in the
* {@code Map}.
*
* <p>Since each forwarder is inserted at the start of the chain,
* the final order of the forwarders is the <b>reverse</b> of the order
* above. This is important, because the {@code
* LOCALIZE_MBEAN_INFO_FORWARDER} can only work if the {@code
* CONTEXT_FORWARDER} has already installed the remote client's locale
* in the {@linkplain ClientContext#getContext context} of the current
* thread.</p>
*
* <p>Attributes in {@code env} that are not listed above are ignored
* by this method.</p>
*
* @throws UnsupportedOperationException if {@link
* #supportsSystemMBeanServerForwarder} is false.
*
* @throws IllegalArgumentException if the relevant attributes in {@code env} are
* inconsistent, for example if {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is
* {@code "true"} but {@link #CONTEXT_FORWARDER} is {@code "false"}; or
* if one of the attributes has an illegal value.
*
* @since 1.7
*/
protected void installStandardForwarders(Map<String, ?> env) {
mustSupportSystemMBSF();
MBeanServerForwarder sysMBSF = getSystemMBeanServerForwarder();
// Remember that forwarders must be added in reverse order!
boolean ecd = EnvHelp.computeBooleanFromString(
env, EVENT_CLIENT_DELEGATE_FORWARDER, false, true);
boolean localize = EnvHelp.computeBooleanFromString(
env, LOCALIZE_MBEAN_INFO_FORWARDER, false, false);
boolean context = EnvHelp.computeBooleanFromString(
env, CONTEXT_FORWARDER, false, true);
if (localize && !context) {
throw new IllegalArgumentException(
"Inconsistent environment parameters: " +
LOCALIZE_MBEAN_INFO_FORWARDER + "=\"true\" requires " +
CONTEXT_FORWARDER + "=\"true\"");
}
if (ecd) {
MBeanServerForwarder mbsf = EventClientDelegate.newForwarder();
setSystemMBeanServerForwarder(mbsf);
MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(
sysMBSF.getMBeanServer(), sysMBSF);
sysMBSF.setMBeanServer(mbsf);
}
if (localize) {
MBeanServerForwarder mbsf = ClientContext.newLocalizeMBeanInfoForwarder(
sysMBSF.getMBeanServer());
sysMBSF.setMBeanServer(mbsf);
}
if (context) {
MBeanServerForwarder mbsf = ClientContext.newContextForwarder(
sysMBSF.getMBeanServer(), sysMBSF);
sysMBSF.setMBeanServer(mbsf);
}
}
@ -473,6 +552,7 @@ public abstract class JMXConnectorServer
*
* @return the array of possible notifications.
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
final String[] types = {
JMXConnectionNotification.OPENED,
@ -684,30 +764,29 @@ public abstract class JMXConnectorServer
* Fields describing the chains of forwarders (MBeanServerForwarders).
* In the general case, the forwarders look something like this:
*
* systemMBeanServer userMBeanServer
* | |
* v v
* mbsf1 -> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs
* userMBeanServer
* |
* v
* systemMBeanServerForwarder -> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs
*
* Here, each mbsfi is an MBeanServerForwarder, and the arrows
* illustrate its getMBeanServer() method. The last MBeanServerForwarder
* can point to an MBeanServer that is not instanceof MBeanServerForwarder,
* here mbs.
*
* Initially, the chain can be empty if this JMXConnectorServer was
* constructed without an MBeanServer. In this case, both systemMBS
* and userMBS will be null. If there is initially an MBeanServer,
* then both systemMBS and userMBS will point to it.
* The system chain is never empty because it always has at least
* systemMBeanServerForwarder. Initially, the user chain can be empty if
* this JMXConnectorServer was constructed without an MBeanServer. In
* this case, userMBS will be null. If there is initially an MBeanServer,
* userMBS will point to it.
*
* Whenever userMBS is changed, the system chain must be updated. If there
* are forwarders in the system chain (between systemMBS and userMBS in the
* picture above), then the last one must point to the old value of userMBS
* (possibly null). It must be updated to point to the new value. If there
* are no forwarders in the system chain, then systemMBS must be updated to
* the new value of userMBS. The invariant is that starting from systemMBS
* and repeatedly calling MBSF.getMBeanServer() you will end up at
* userMBS. The implication is that you will not see any MBeanServer
* object on the way that is not also an MBeanServerForwarder.
* Whenever userMBS is changed, the system chain must be updated. Before
* the update, the last forwarder in the system chain points to the old
* value of userMBS (possibly null). It must be updated to point to
* the new value. The invariant is that starting from systemMBSF and
* repeatedly calling MBSF.getMBeanServer() you will end up at userMBS.
* The implication is that you will not see any MBeanServer object on the
* way that is not also an MBeanServerForwarder.
*
* The method insertUserMBeanServer contains the logic to change userMBS
* and adjust the system chain appropriately.
@ -716,7 +795,7 @@ public abstract class JMXConnectorServer
* MBeanServer, then userMBS becomes that MBeanServer, and the system
* chain must be updated as just described.
*
* When systemMBS is updated, there is no effect on userMBS. The system
* When systemMBSF is updated, there is no effect on userMBS. The system
* chain may contain forwarders even though the user chain is empty
* (there is no MBeanServer). In that case an attempt to forward an
* incoming request through the chain will fall off the end and fail with a
@ -726,7 +805,8 @@ public abstract class JMXConnectorServer
private MBeanServer userMBeanServer;
private MBeanServer systemMBeanServer;
private final MBeanServerForwarder systemMBeanServerForwarder =
new IdentityMBeanServerForwarder();
/**
* The name used to registered this server in an MBeanServer.

View File

@ -132,7 +132,7 @@ public interface JMXConnectorServerMBean {
*
* <p>A connector server may support two chains of forwarders,
* a system chain and a user chain. See {@link
* JMXConnectorServer#setSystemMBeanServerForwarder} for details.</p>
* JMXConnectorServer#getSystemMBeanServerForwarder} for details.</p>
*
* @param mbsf the new <code>MBeanServerForwarder</code>.
*
@ -141,7 +141,7 @@ public interface JMXConnectorServerMBean {
* with <code>IllegalArgumentException</code>. This includes the
* case where <code>mbsf</code> is null.
*
* @see JMXConnectorServer#setSystemMBeanServerForwarder
* @see JMXConnectorServer#getSystemMBeanServerForwarder
*/
public void setMBeanServerForwarder(MBeanServerForwarder mbsf);

View File

@ -383,7 +383,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
try {
if (tracing) logger.trace("start", "setting default class loader");
defaultClassLoader = EnvHelp.resolveServerClassLoader(
attributes, getSystemMBeanServer());
attributes, getSystemMBeanServerForwarder());
} catch (InstanceNotFoundException infc) {
IllegalArgumentException x = new
IllegalArgumentException("ClassLoader not found: "+infc);
@ -398,7 +398,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
else
rmiServer = newServer();
rmiServer.setMBeanServer(getSystemMBeanServer());
rmiServer.setMBeanServer(getSystemMBeanServerForwarder());
rmiServer.setDefaultClassLoader(defaultClassLoader);
rmiServer.setRMIConnectorServer(this);
rmiServer.export();
@ -592,31 +592,6 @@ public class RMIConnectorServer extends JMXConnectorServer {
return Collections.unmodifiableMap(map);
}
@Override
public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
MBeanServer oldSMBS = getSystemMBeanServer();
super.setMBeanServerForwarder(mbsf);
if (oldSMBS != getSystemMBeanServer())
updateMBeanServer();
// If the system chain of MBeanServerForwarders is not empty, then
// there is no need to call rmiServerImpl.setMBeanServer, because
// it is pointing to the head of the system chain and that has not
// changed. (The *end* of the system chain will have been changed
// to point to mbsf.)
}
private void updateMBeanServer() {
if (rmiServerImpl != null)
rmiServerImpl.setMBeanServer(getSystemMBeanServer());
}
@Override
public synchronized void setSystemMBeanServerForwarder(
MBeanServerForwarder mbsf) {
super.setSystemMBeanServerForwarder(mbsf);
updateMBeanServer();
}
/**
* {@inheritDoc}
* @return true, since this connector server does support a system chain
@ -631,16 +606,19 @@ public class RMIConnectorServer extends JMXConnectorServer {
here so that they are accessible to other classes in this package
even though they have protected access. */
@Override
protected void connectionOpened(String connectionId, String message,
Object userData) {
super.connectionOpened(connectionId, message, userData);
}
@Override
protected void connectionClosed(String connectionId, String message,
Object userData) {
super.connectionClosed(connectionId, message, userData);
}
@Override
protected void connectionFailed(String connectionId, String message,
Object userData) {
super.connectionFailed(connectionId, message, userData);

View File

@ -435,8 +435,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (streaming()) {
if (chunkLength != -1) {
requests.set ("Transfer-Encoding", "chunked");
} else {
requests.set ("Content-Length", String.valueOf(fixedContentLength));
} else { /* fixed content length */
if (fixedContentLengthLong != -1) {
requests.set ("Content-Length",
String.valueOf(fixedContentLengthLong));
} else if (fixedContentLength != -1) {
requests.set ("Content-Length",
String.valueOf(fixedContentLength));
}
}
} else if (poster != null) {
/* add Content-Length & POST/PUT data */
@ -871,11 +877,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
ps = (PrintStream)http.getOutputStream();
if (streaming()) {
if (strOutputStream == null) {
if (fixedContentLength != -1) {
strOutputStream = new StreamingOutputStream (ps, fixedContentLength);
} else if (chunkLength != -1) {
strOutputStream =
new StreamingOutputStream (new ChunkedOutputStream (ps, chunkLength), -1);
if (chunkLength != -1) { /* chunked */
strOutputStream = new StreamingOutputStream(
new ChunkedOutputStream(ps, chunkLength), -1L);
} else { /* must be fixed content length */
long length = 0L;
if (fixedContentLengthLong != -1) {
length = fixedContentLengthLong;
} else if (fixedContentLength != -1) {
length = fixedContentLength;
}
strOutputStream = new StreamingOutputStream(ps, length);
}
}
return strOutputStream;
@ -895,7 +907,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
private boolean streaming () {
return (fixedContentLength != -1) || (chunkLength != -1);
return (fixedContentLength != -1) || (fixedContentLengthLong != -1) ||
(chunkLength != -1);
}
/*
@ -2619,8 +2632,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
class StreamingOutputStream extends FilterOutputStream {
int expected;
int written;
long expected;
long written;
boolean closed;
boolean error;
IOException errorExcp;
@ -2631,10 +2644,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* In the 2nd case, we make sure the expected number of
* of bytes are actually written
*/
StreamingOutputStream (OutputStream os, int expectedLength) {
StreamingOutputStream (OutputStream os, long expectedLength) {
super (os);
expected = expectedLength;
written = 0;
written = 0L;
closed = false;
error = false;
}
@ -2643,7 +2656,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public void write (int b) throws IOException {
checkError();
written ++;
if (expected != -1 && written > expected) {
if (expected != -1L && written > expected) {
throw new IOException ("too many bytes written");
}
out.write (b);
@ -2658,7 +2671,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public void write (byte[] b, int off, int len) throws IOException {
checkError();
written += len;
if (expected != -1 && written > expected) {
if (expected != -1L && written > expected) {
out.close ();
throw new IOException ("too many bytes written");
}
@ -2691,7 +2704,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return;
}
closed = true;
if (expected != -1) {
if (expected != -1L) {
/* not chunked */
if (written != expected) {
error = true;

View File

@ -527,6 +527,10 @@ public class HttpsURLConnectionImpl
delegate.setFixedLengthStreamingMode(contentLength);
}
public void setFixedLengthStreamingMode(long contentLength) {
delegate.setFixedLengthStreamingMode(contentLength);
}
public void setChunkedStreamingMode (int chunklen) {
delegate.setChunkedStreamingMode(chunklen);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2008 Sun Microsystems, Inc. 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
@ -284,7 +284,8 @@ class GSSContextImpl implements GSSContext {
ByteArrayOutputStream bos = new ByteArrayOutputStream(100);
acceptSecContext(new ByteArrayInputStream(inTok, offset, len),
bos);
return bos.toByteArray();
byte[] out = bos.toByteArray();
return (out.length == 0) ? null : out;
}
public void acceptSecContext(InputStream inStream,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2008 Sun Microsystems, Inc. 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
@ -413,13 +413,14 @@ public class SpNegoContext implements GSSContextSpi {
// pull out the mechanism token
byte[] accept_token = targToken.getResponseToken();
if (accept_token == null) {
// return wth failure
throw new GSSException(errorCode, -1,
"mechansim token from server is null");
if (!isMechContextEstablished()) {
// return with failure
throw new GSSException(errorCode, -1,
"mechanism token from server is null");
}
} else {
mechToken = GSS_initSecContext(accept_token);
}
mechToken = GSS_initSecContext(accept_token);
// verify MIC
if (!GSSUtil.useMSInterop()) {
byte[] micToken = targToken.getMechListMIC();
@ -428,7 +429,6 @@ public class SpNegoContext implements GSSContextSpi {
"verification of MIC on MechList Failed!");
}
}
if (isMechContextEstablished()) {
state = STATE_DONE;
retVal = mechToken;
@ -556,9 +556,6 @@ public class SpNegoContext implements GSSContextSpi {
// get the token for mechanism
byte[] accept_token = GSS_acceptSecContext(mechToken);
if (accept_token == null) {
valid = false;
}
// verify MIC
if (!GSSUtil.useMSInterop() && valid) {

View File

@ -151,6 +151,10 @@ class OCSPResponse {
private SingleResponse singleResponse;
// Maximum clock skew in milliseconds (10 minutes) allowed when checking
// validity of OCSP responses
private static final long MAX_CLOCK_SKEW = 600000;
// an array of all of the CRLReasons (used in SingleResponse)
private static CRLReason[] values = CRLReason.values();
@ -583,7 +587,9 @@ class OCSPResponse {
}
}
Date now = new Date();
long now = System.currentTimeMillis();
Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
if (DEBUG != null) {
String until = "";
if (nextUpdate != null) {
@ -593,8 +599,8 @@ class OCSPResponse {
thisUpdate + until);
}
// Check that the test date is within the validity interval
if ((thisUpdate != null && now.before(thisUpdate)) ||
(nextUpdate != null && now.after(nextUpdate))) {
if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) ||
(nextUpdate != null && nowMinusSkew.after(nextUpdate))) {
if (DEBUG != null) {
DEBUG.println("Response is unreliable: its validity " +

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