This commit is contained in:
J. Duke 2017-07-05 16:44:04 +02:00
commit a99f7bac50
165 changed files with 8440 additions and 2975 deletions

View file

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

View file

@ -98,7 +98,8 @@
<h2><a name="MBE">Minimum Build Environments</a></h2> <h2><a name="MBE">Minimum Build Environments</a></h2>
<blockquote> <blockquote>
This file often describes specific requirements for what we call the 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 Building with the MBE will generate the most compatible
bits that install on, and run correctly on, the most variations bits that install on, and run correctly on, the most variations
of the same base OS and hardware architecture. of the same base OS and hardware architecture.
@ -116,22 +117,22 @@
<tr> <tr>
<th>Base OS and Architecture</th> <th>Base OS and Architecture</th>
<th>OS</th> <th>OS</th>
<th>Compiler</th> <th>C/C++ Compiler</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>Linux X86 (32bit)</td> <td>Linux X86 (32-bit)</td>
<td>Red Hat Enterprise Linux 4 </td> <td>Fedora 9</td>
<td>gcc 4 </td> <td>gcc 4 </td>
</tr> </tr>
<tr> <tr>
<td>Linux X64 (64bit)</td> <td>Linux X64 (64-bit)</td>
<td>Red Hat Enterprise Linux 4 </td> <td>Fedora 9</td>
<td>gcc 4 </td> <td>gcc 4 </td>
</tr> </tr>
<tr> <tr>
<td>Solaris SPARC (32bit)</td> <td>Solaris SPARC (32-bit)</td>
<td>Solaris 10 + patches <td>Solaris 10 + patches
<br> <br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> 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> <td>Sun Studio 12</td>
</tr> </tr>
<tr> <tr>
<td>Solaris SPARCV9 (64bit)</td> <td>Solaris SPARCV9 (64-bit)</td>
<td>Solaris 10 + patches <td>Solaris 10 + patches
<br> <br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> 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> <td>Sun Studio 12</td>
</tr> </tr>
<tr> <tr>
<td>Solaris X86 (32bit)</td> <td>Solaris X86 (32-bit)</td>
<td>Solaris 10 + patches <td>Solaris 10 + patches
<br> <br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> 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> <td>Sun Studio 12</td>
</tr> </tr>
<tr> <tr>
<td>Solaris X64 (64bit)</td> <td>Solaris X64 (64-bit)</td>
<td>Solaris 10 + patches <td>Solaris 10 + patches
<br> <br>
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> 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> <td>Sun Studio 12</td>
</tr> </tr>
<tr> <tr>
<td>Windows X86 (32bit)</td> <td>Windows X86 (32-bit)</td>
<td>Windows XP</td> <td>Windows XP</td>
<td>Microsoft Visual Studio .NET 2003 Professional</td> <td>Microsoft Visual Studio C++ 2008 Standard Edition</td>
</tr> </tr>
<tr> <tr>
<td>Windows X64 (64bit)</td> <td>Windows X64 (64-bit)</td>
<td>Windows Server 2003 - Enterprise x64 Edition</td> <td>Windows Server 2003 - Enterprise x64 Edition</td>
<td>Microsoft Platform SDK - April 2005</td> <td>Microsoft Platform SDK - April 2005</td>
</tr> </tr>
</tbody> </tbody>
</table> </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> </blockquote>
<!-- ------------------------------------------------------ --> <!-- ------------------------------------------------------ -->
<hr> <hr>
@ -488,7 +500,7 @@
not work due to a lack of support for MS-DOS drive letter paths not work due to a lack of support for MS-DOS drive letter paths
like <tt>C:/</tt> or <tt>C:\</tt>. like <tt>C:/</tt> or <tt>C:\</tt>.
Use a 3.80 version, or find a newer 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 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"> <a href="http://cygwin.paracoda.com/release/make/make-3.80-1.tar.bz2" target="_blank">
link</a>. link</a>.
@ -575,8 +587,8 @@
</li> </li>
<li> <li>
Install Install
<a href="#ant">Ant</a>, set <a href="#ant">Ant</a>,
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>. make sure it is in your PATH.
</li> </li>
</ol> </ol>
</blockquote> </blockquote>
@ -592,7 +604,7 @@
Approximately 1.4 GB of free disk Approximately 1.4 GB of free disk
space is needed for a 32-bit build. space is needed for a 32-bit build.
<p> <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 run the command "isainfo -v" to verify that you have a
64-bit installation, it should say <tt>sparcv9</tt> or 64-bit installation, it should say <tt>sparcv9</tt> or
<tt>amd64</tt>. <tt>amd64</tt>.
@ -640,8 +652,8 @@
</li> </li>
<li> <li>
Install Install
<a href="#ant">Ant</a>, set <a href="#ant">Ant</a>,
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>. make sure it is in your PATH.
</li> </li>
</ol> </ol>
</blockquote> </blockquote>
@ -650,11 +662,11 @@
<h3><a name="windows">Basic Windows System Setup</a></h3> <h3><a name="windows">Basic Windows System Setup</a></h3>
<blockquote> <blockquote>
<strong>i586 only:</strong> <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 Windows version is an Pentium class processor or better, at least
512 MB of RAM, and approximately 600 MB of free disk space. 512 MB of RAM, and approximately 600 MB of free disk space.
<strong> <strong>
NOTE: The Windows 2000 build machines need to use the NOTE: The Windows build machines need to use the
file system NTFS. file system NTFS.
Build machines formatted to FAT32 will not work Build machines formatted to FAT32 will not work
because FAT32 doesn't support case-sensitivity in file names. because FAT32 doesn't support case-sensitivity in file names.
@ -719,8 +731,11 @@
</li> </li>
<li> <li>
Install the Install the
<a href="#msvc">Microsoft Visual Studio .NET 2003 Professional</a> (32bit) or the <a href="#msvc">Microsoft Visual Studio Compilers</a> (32-bit).
<a href="#mssdk">Microsoft Platform SDK</a> (64bit). </li>
<li>
Install the
<a href="#mssdk">Microsoft Platform SDK</a>.
</li> </li>
<li> <li>
Setup all environment variables for compilers Setup all environment variables for compilers
@ -732,7 +747,8 @@
</li> </li>
<li> <li>
Install 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>. <tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
</li> </li>
</ol> </ol>
@ -787,7 +803,9 @@
you must first download and install the appropriate you must first download and install the appropriate
binary plug bundles for the OpenJDK, go to the binary plug bundles for the OpenJDK, go to the
<a href="http://openjdk.java.net" target="_blank">OpenJDK</a> site and select <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. your particular platform.
The file downloaded is a jar file that must be extracted by running The file downloaded is a jar file that must be extracted by running
the jar file with: the jar file with:
@ -823,14 +841,12 @@
The Ant tool is available from the The Ant tool is available from the
<a href="http://ant.apache.org/antlibs/bindownload.cgi" target="_blank"> <a href="http://ant.apache.org/antlibs/bindownload.cgi" target="_blank">
Ant download site</a>. 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> <tt><a href="#ANT_HOME">ANT_HOME</a></tt>
to point to the location of to point to the location of
the Ant installation, this is the directory pathname the Ant installation, this is the directory pathname
that contains a <tt>bin and lib</tt>. 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> </blockquote>
<!-- ------------------------------------------------------ --> <!-- ------------------------------------------------------ -->
<h4><a name="cacerts">Certificate Authority File (cacert)</a></h4> <h4><a name="cacerts">Certificate Authority File (cacert)</a></h4>
@ -862,25 +878,9 @@
<blockquote> <blockquote>
<strong><a name="gcc">Linux gcc/binutils</a></strong> <strong><a name="gcc">Linux gcc/binutils</a></strong>
<blockquote> <blockquote>
The GNU gcc compiler version should be 3.2.2 or newer. The GNU gcc compiler version should be 4 or newer.
The binutils package should be 2.11.93.0.2-11 or newer.
The compiler used should be the default compiler installed The compiler used should be the default compiler installed
in <tt>/usr/bin</tt>. 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> </blockquote>
<strong><a name="studio">Solaris: Sun Studio</a></strong> <strong><a name="studio">Solaris: Sun Studio</a></strong>
<blockquote> <blockquote>
@ -903,19 +903,20 @@
are also an option, although these compilers have not are also an option, although these compilers have not
been extensively used yet. been extensively used yet.
</blockquote> </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> <blockquote>
The 32-bit OpenJDK Windows build The 32-bit OpenJDK Windows build
requires Microsoft Visual Studio .NET 2003 (VS2003) Professional requires
Microsoft Visual Studio C++ 2008 (VS2008) Standard
Edition compiler. Edition compiler.
The compiler and other tools are expected to reside The compiler and other tools are expected to reside
in the location defined by the variable <tt>VS71COMNTOOLS</tt> which in the location defined by the variable
is set by the Microsoft Visual Studio .NET installer. <tt>VS90COMNTOOLS</tt> which
is set by the Microsoft Visual Studio installer.
<p> <p>
Once the compiler is installed, Once the compiler is installed,
it is recommended that you run <tt>VCVARS32.BAT</tt> it is recommended that you run <tt>VCVARS32.BAT</tt>
to set the compiler environment variables to set the compiler environment variables
<tt>MSVCDIR</tt>,
<tt>INCLUDE</tt>, <tt>INCLUDE</tt>,
<tt>LIB</tt>, and <tt>LIB</tt>, and
<tt>PATH</tt> <tt>PATH</tt>
@ -923,16 +924,12 @@
OpenJDK. OpenJDK.
The above environment variables <b>MUST</b> be set. The above environment variables <b>MUST</b> be set.
<p> <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 <b>WARNING:</b> Make sure you check out the
<a href="#cygwin">CYGWIN link.exe WARNING</a>. <a href="#cygwin">CYGWIN link.exe WARNING</a>.
The path <tt>/usr/bin</tt> must be after the path to the The path <tt>/usr/bin</tt> must be after the path to the
Visual Studio product. Visual Studio product.
</blockquote> </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> <blockquote>
On <b>X64</b>, the Microsoft Platform Software On <b>X64</b>, the Microsoft Platform Software
Development Kit (SDK), April 2005 Edition compiler, Development Kit (SDK), April 2005 Edition compiler,
@ -953,10 +950,9 @@
OpenJDK. OpenJDK.
The above environment variables <b>MUST</b> be set. The above environment variables <b>MUST</b> be set.
<p> <p>
Note that this compiler may say it's version is a This Platform SDK compiler is only used on X64 builds
Microsoft Visual Studio .NET 2005 (VS2005), but be careful, but other parts of the Platform SDK may be used
it will not match the official VS2005 product. for the X86 builds.
This Platform SDK compiler is only used on X64 builds.
</blockquote> </blockquote>
</blockquote> </blockquote>
<!-- ------------------------------------------------------ --> <!-- ------------------------------------------------------ -->
@ -1241,37 +1237,37 @@
<strong><a name="msvcrt"><tt>MSVCRT.DLL</tt></a></strong> <strong><a name="msvcrt"><tt>MSVCRT.DLL</tt></a></strong>
<blockquote> <blockquote>
<strong>i586 only:</strong> <strong>i586 only:</strong>
The OpenJDK 32bit build requires access to The OpenJDK 32-bit build requires access to a redistributable
<tt>MSVCRT.DLL</tt> version 6.00.8337.0 or newer. <tt>MSVCRT.DLL</tt>.
If the <tt>MSVCRT.DLL</tt> is not installed in If the <tt>MSVCRT.DLL</tt> is not installed in
the system32 directory set the the system32 directory set the
<a href="#ALT_MSVCRT_DLL_PATH"><tt>ALT_MSVCRT_DLL_PATH</tt></a> <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> <p>
<strong>X64 only:</strong> <strong>X64 only:</strong>
The OpenJDK 64bit build requires access to The OpenJDK 64-bit build requires access to a redistributable
<tt>MSVCRT.DLL</tt> version 7.0.3790.0 or newer, which is <tt>MSVCRT.DLL</tt>, which is
usually supplied by the usually supplied by the
<a href="#mssdk">Platform SDK</a>. <a href="#mssdk">Platform SDK</a>.
If it is not available from the Platform SDK, If it is not available from the Platform SDK,
set the set the
<a href="#ALT_MSVCRT_DLL_PATH"><tt>ALT_MSVCRT_DLL_PATH</tt></a> <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> </blockquote>
<strong><tt><a name="msvcr71">MSVCR71.DLL</a></tt></strong> <strong><tt><a name="msvcr90">MSVCR90.DLL</a></tt></strong>
<blockquote> <blockquote>
<strong>i586 only:</strong> <strong>i586 only:</strong>
The The
OpenJDK OpenJDK
build requires access to build requires access to a redistributable
MSVCR71.DLL version 7.10.3052.4 or newer which should be <tt>MSVCR90.DLL</tt> which should be
supplied by the supplied by the
<a href="#msvc">Visual Studio product</a> <a href="#msvc">Visual Studio product</a>.
If the <tt>MSVCR71.DLL</tt> is not available from the If the <tt>MSVCR90.DLL</tt> is not available from the
Visual Studio product Visual Studio product
set the set the
<a href="#ALT_MSVCR71_DLL_PATH"><tt>ALT_MSVCR71_DLL_PATH</tt></a> <a href="#ALT_MSVCR90_DLL_PATH"><tt>ALT_MSVCR90_DLL_PATH</tt></a>
variable to the location. variable to the location of this file.
</blockquote> </blockquote>
</blockquote> </blockquote>
<!-- ------------------------------------------------------ --> <!-- ------------------------------------------------------ -->
@ -1359,13 +1355,38 @@
document) that can impact the build are: document) that can impact the build are:
<blockquote> <blockquote>
<dl> <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> <dd>
The location of the binary plugs installation. The milestone name for the build (<i>e.g.</i>"beta").
See <a href="#binaryplugs">Binary Plugs</a> for more information. The default value is "internal".
You should always have a local copy of a </dd>
recent Binary Plugs install image <dt><tt>BUILD_NUMBER</tt> </dt>
and set this variable to that location. <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> </dd>
<dt><a name="ALT_BOOTDIR"><tt>ALT_BOOTDIR</tt></a></dt> <dt><a name="ALT_BOOTDIR"><tt>ALT_BOOTDIR</tt></a></dt>
<dd> <dd>
@ -1374,25 +1395,89 @@
You should always install your own local Bootstrap JDK and You should always install your own local Bootstrap JDK and
always set <tt>ALT_BOOTDIR</tt> explicitly. always set <tt>ALT_BOOTDIR</tt> explicitly.
</dd> </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> <dd>
These are useful in managing builds on multiple platforms. The location of the binary plugs installation.
The default network location for all of the binary plug images See <a href="#binaryplugs">Binary Plugs</a> for more information.
for all platforms. You should always have a local copy of a
If <tt><a href="#ALT_BINARY_PLUGS_PATH">ALT_BINARY_PLUGS_PATH</a></tt> recent Binary Plugs install image
is not set, this directory will be used and should contain and set this variable to that location.
the following directories: </dd>
<tt>solaris-sparc</tt>, <dt><a name="ALT_JDK_IMPORT_PATH"><tt>ALT_JDK_IMPORT_PATH</tt></a></dt>
<tt>solaris-i586</tt>, <dd>
<tt>solaris-sparcv9</tt>, The location of a previously built JDK installation.
<tt>solaris-amd64</tt>, See <a href="#importjdk">Optional Import JDK</a> for more information.
<tt>linux-i586</tt>, </dd>
<tt>linux-amd64</tt>, <dt><a name="ALT_OUTPUTDIR"><tt>ALT_OUTPUTDIR</tt></a> </dt>
<tt>windows-i586</tt>, <dd>
and An override for specifying the (absolute) path of where the
<tt>windows-amd64</tt>. build output is to go.
Where each of these directories contain the binary plugs image The default output directory will be build/<i>platform</i>.
for that platform. </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> </dd>
<dt><a name="ALT_BUILD_JDK_IMPORT_PATH"><tt>ALT_BUILD_JDK_IMPORT_PATH</tt></a></dt> <dt><a name="ALT_BUILD_JDK_IMPORT_PATH"><tt>ALT_BUILD_JDK_IMPORT_PATH</tt></a></dt>
<dd> <dd>
@ -1414,166 +1499,57 @@
Where each of these directories contain the import JDK image Where each of these directories contain the import JDK image
for that platform. for that platform.
</dd> </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> <dd>
The location of the <a href="#cacerts">cacerts</a> file. These are useful in managing builds on multiple platforms.
The default will refer to The default network location for all of the binary plug images
<tt>jdk/src/share/lib/security/cacerts</tt>. 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> </dd>
<dt><a name="ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a> </dt> <dt><strong>Windows specific:</strong></dt>
<dd> <dd>
The location of the C/C++ compiler. <dl>
The default varies depending on the platform. <dt><a name="ALT_MSDEVTOOLS_PATH"><tt>ALT_MSDEVTOOLS_PATH</tt></a> </dt>
</dd> <dd>
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt> The location of the
<dd> Microsoft Visual Studio
The location of the CUPS header files. tools 'bin' directory.
See <a href="#cups">CUPS information</a> for more information. The default is usually derived from
If this path does not exist the fallback path is <a href="#ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a>.
<tt>/usr/include</tt>. </dd>
</dd> <dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt>
<dt><tt><a name="ALT_DEVTOOLS_PATH">ALT_DEVTOOLS_PATH</a></tt> </dt> <dd>
<dd> The location of the
The location of tools like the <a href="#dxsdk">Microsoft DirectX 9 SDK</a>.
<a href="#zip"><tt>zip</tt> and <tt>unzip</tt></a> The default will be to try and use the DirectX environment
binaries, but might also contain the GNU make utility variable <tt>DXSDK_DIR</tt>,
(<tt><i>gmake</i></tt>). failing that, look in <tt>C:/DXSDK</tt>.
So this area is a bit of a grab bag, especially on Windows. </dd>
The default value depends on the platform and <dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
Unix Commands being used. <dd>
On Linux the default will be The location of the
<tt>$(ALT_JDK_DEVTOOLS_PATH)/linux/bin</tt>, <a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
on Solaris </dd>
<tt>$(ALT_JDK_DEVTOOLS_PATH)/<i>{sparc,i386}</i>/bin</tt>, <dt><tt><a name="ALT_MSVCR90_DLL_PATH">ALT_MSVCR90_DLL_PATH</a></tt> </dt>
on Windows with MKS <dd>
<tt>%SYSTEMDRIVE%/UTILS</tt>, <strong>i586 only:</strong>
and on Windows with CYGWIN The location of the
<tt>/usr/bin</tt>. <a href="#msvcr90"><tt>MSVCR90.DLL</tt></a>.
</dd> </dd>
<dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt> </dl>
<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>
</dd> </dd>
</dl> </dl>
</blockquote> </blockquote>
@ -1661,8 +1637,8 @@
This is caused by a missing libstdc++.a library. This is caused by a missing libstdc++.a library.
This is installed as part of a specific package This is installed as part of a specific package
(e.g. libstdc++.so.devel.386). (e.g. libstdc++.so.devel.386).
By default some 64bit Linux versions (e.g. Fedora) By default some 64-bit Linux versions (e.g. Fedora)
only install the 64bit version of the libstdc++ package. only install the 64-bit version of the libstdc++ package.
Various parts of the JDK build require a static Various parts of the JDK build require a static
link of the C++ runtime libraries to allow for maximum link of the C++ runtime libraries to allow for maximum
portability of the built images. portability of the built images.

View file

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

View file

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

View file

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

View file

@ -85,9 +85,9 @@ Incremental_Lists = $(Cached_db)
AD_Dir = $(GENERATED)/adfiles AD_Dir = $(GENERATED)/adfiles
ADLC = $(AD_Dir)/adlc ADLC = $(AD_Dir)/adlc
AD_Spec = $(GAMMADIR)/src/cpu/$(Platform_arch)/vm/$(Platform_arch).ad AD_Spec = $(GAMMADIR)/src/cpu/$(Platform_arch)/vm/$(Platform_arch_model).ad
AD_Src = $(GAMMADIR)/src/share/vm/adlc AD_Src = $(GAMMADIR)/src/share/vm/adlc
AD_Names = ad_$(Platform_arch).hpp ad_$(Platform_arch).cpp AD_Names = ad_$(Platform_arch_model).hpp ad_$(Platform_arch_model).cpp
AD_Files = $(AD_Names:%=$(AD_Dir)/%) AD_Files = $(AD_Names:%=$(AD_Dir)/%)
# AD_Files_If_Required/COMPILER1 = ad_stuff # AD_Files_If_Required/COMPILER1 = ad_stuff

View file

@ -26,7 +26,6 @@
CFLAGS += -DVM_LITTLE_ENDIAN CFLAGS += -DVM_LITTLE_ENDIAN
# Not included in includeDB because it has no dependencies # Not included in includeDB because it has no dependencies
# Obj_Files += solaris_amd64.o
Obj_Files += solaris_x86_64.o Obj_Files += solaris_x86_64.o
# #
@ -38,8 +37,6 @@ ifeq ("${Platform_compiler}", "sparcWorks")
# _lwp_create_interpose must have a frame # _lwp_create_interpose must have a frame
OPT_CFLAGS/os_solaris_x86_64.o = -xO1 OPT_CFLAGS/os_solaris_x86_64.o = -xO1
# force C++ interpreter to be full optimization
#OPT_CFLAGS/interpret.o = -fast -O4
# Temporary until SS10 C++ compiler is fixed # Temporary until SS10 C++ compiler is fixed
OPT_CFLAGS/generateOptoStub.o = -xO2 OPT_CFLAGS/generateOptoStub.o = -xO2
@ -51,8 +48,6 @@ ifeq ("${Platform_compiler}", "gcc")
# gcc # gcc
# The serviceability agent relies on frame pointer (%rbp) to walk thread stack # The serviceability agent relies on frame pointer (%rbp) to walk thread stack
CFLAGS += -fno-omit-frame-pointer CFLAGS += -fno-omit-frame-pointer
# force C++ interpreter to be full optimization
#OPT_CFLAGS/interpret.o = -O3
else else
# error # error

View file

@ -30,7 +30,7 @@ DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(COMPILER_REV),5.8) ifeq ($(COMPILER_REV_NUMERIC),508)
# SS11 SEGV when compiling with -g and -xarch=v8, using different backend # SS11 SEGV when compiling with -g and -xarch=v8, using different backend
DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0 DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0
DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0 DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0

View file

@ -87,17 +87,16 @@ ifneq ("${ISA}","${BUILDARCH}")
XLIBJVM_DB = 64/$(LIBJVM_DB) XLIBJVM_DB = 64/$(LIBJVM_DB)
XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE) XLIBJVM_DTRACE = 64/$(LIBJVM_DTRACE)
XARCH = $(subst sparcv9,v9,$(shell echo $(ISA)))
$(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE) $(XLIBJVM_DB): $(DTRACE_SRCDIR)/$(JVM_DB).c $(JVMOFFS).h $(LIBJVM_DB_MAPFILE)
@echo Making $@ @echo Making $@
$(QUIETLY) mkdir -p 64/ ; \ $(QUIETLY) mkdir -p 64/ ; \
$(CC) $(SYMFLAG) $(ARCHFLAG/$(XARCH)) -D$(TYPE) -I. -I$(GENERATED) \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. -I$(GENERATED) \
$(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc $(SHARED_FLAG) $(LFLAGS_JVM_DB) -o $@ $(DTRACE_SRCDIR)/$(JVM_DB).c -lc
$(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE) $(XLIBJVM_DTRACE): $(DTRACE_SRCDIR)/$(JVM_DTRACE).c $(DTRACE_SRCDIR)/$(JVM_DTRACE).h $(LIBJVM_DTRACE_MAPFILE)
@echo Making $@ @echo Making $@
$(QUIETLY) mkdir -p 64/ ; \ $(QUIETLY) mkdir -p 64/ ; \
$(CC) $(SYMFLAG) $(ARCHFLAG/$(XARCH)) -D$(TYPE) -I. \ $(CC) $(SYMFLAG) $(ARCHFLAG/$(ISA)) -D$(TYPE) -I. \
$(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor $(SHARED_FLAG) $(LFLAGS_JVM_DTRACE) -o $@ $(DTRACE_SRCDIR)/$(JVM_DTRACE).c -lc -lthread -ldoor
endif # ifneq ("${ISA}","${BUILDARCH}") endif # ifneq ("${ISA}","${BUILDARCH}")
@ -116,27 +115,25 @@ $(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).so
$(QUIETLY) $(LINK.CC) -z nodefs -o $@ $(DTRACE_SRCDIR)/$(GENOFFS)Main.c \ $(QUIETLY) $(LINK.CC) -z nodefs -o $@ $(DTRACE_SRCDIR)/$(GENOFFS)Main.c \
./lib$(GENOFFS).so ./lib$(GENOFFS).so
# $@.tmp is created first. It's to avoid empty $(JVMOFFS).h produced in error case. CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
cmp -s $@ $@.tmp; \
case $$? in \
0) rm -f $@.tmp;; \
*) rm -f $@ && mv $@.tmp $@ && echo Updated $@;; \
esac
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS) $(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -header > $@.tmp ; \ $(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -header > $@.tmp
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
then rm -f $@; mv $@.tmp $@; echo Updated $@ ; \
else rm -f $@.tmp; \
fi
$(JVMOFFS)Index.h: $(GENOFFS) $(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -index > $@.tmp ; \ $(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -index > $@.tmp
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
then rm -f $@; mv $@.tmp $@; echo Updated $@ ; \
else rm -f $@.tmp; \
fi
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h $(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -table > $@.tmp ; \ $(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -table > $@.tmp
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
then rm -f $@; mv $@.tmp $@; echo Updated $@ ; \
else rm -f $@.tmp; \
fi
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp $(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp
$(QUIETLY) $(CCC) -c -I. -o $@ $(ARCHFLAG) -D$(TYPE) $(JVMOFFS).cpp $(QUIETLY) $(CCC) -c -I. -o $@ $(ARCHFLAG) -D$(TYPE) $(JVMOFFS).cpp

View file

@ -37,7 +37,7 @@ ifeq ("${Platform_compiler}", "sparcWorks")
OPT_CFLAGS/SLOWER = -xO2 OPT_CFLAGS/SLOWER = -xO2
# Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876) # Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876)
ifeq ($(COMPILER_REV), 5.9) ifeq ($(COMPILER_REV_NUMERIC), 509)
# To avoid jvm98 crash # To avoid jvm98 crash
OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER)
# Not clear this workaround could be skipped in some cases. # Not clear this workaround could be skipped in some cases.
@ -46,47 +46,41 @@ ifeq ($(COMPILER_REV), 5.9)
OPT_CFLAGS/jni.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/jni.o = $(OPT_CFLAGS/SLOWER)
endif endif
ifeq ($(COMPILER_REV), 5.5) ifeq ($(COMPILER_REV_NUMERIC), 505)
# CC 5.5 has bug 4908364 with -xO4 (Fixed in 5.6) # CC 5.5 has bug 4908364 with -xO4 (Fixed in 5.6)
OPT_CFLAGS/library_call.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/library_call.o = $(OPT_CFLAGS/SLOWER)
endif # COMPILER_REV == 5.5 endif # COMPILER_REV_NUMERIC == 505
ifeq ($(shell expr $(COMPILER_REV) \<= 5.4), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \<= 504), 1)
# Compilation of *_<arch>.cpp can take an hour or more at O3. Use O2 # Compilation of *_<arch>.cpp can take an hour or more at O3. Use O2
# See comments at top of sparc.make. # See comments at top of sparc.make.
OPT_CFLAGS/ad_$(Platform_arch).o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/ad_$(Platform_arch_model).o = $(OPT_CFLAGS/SLOWER)
OPT_CFLAGS/dfa_$(Platform_arch).o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/dfa_$(Platform_arch_model).o = $(OPT_CFLAGS/SLOWER)
endif # COMPILER_REV <= 5.4 endif # COMPILER_REV_NUMERIC <= 504
ifeq (${COMPILER_REV}, 5.0) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \< 505), 1)
# Avoid a compiler bug caused by using -xO<level> -g<level> # Same problem with Solaris/x86 compiler (both 5.0 and 5.2) on ad_x86_{32,64}.cpp.
# Since the bug also occurs with -xO0, use an innocuous value (must not be null) # CC build time is also too long for ad_$(Platform_arch_model)_{gen,misc}.o
OPT_CFLAGS/c1_LIROptimizer_i486.o = -c OPT_CFLAGS/ad_$(Platform_arch_model).o = -c
endif OPT_CFLAGS/ad_$(Platform_arch_model)_gen.o = -c
OPT_CFLAGS/ad_$(Platform_arch_model)_misc.o = -c
ifeq ($(shell expr $(COMPILER_REV) \< 5.5), 1) ifeq ($(Platform_arch), x86)
# Same problem with Solaris/x86 compiler (both 5.0 and 5.2) on ad_i486.cpp.
# CC build time is also too long for ad_i486_{gen,misc}.o
OPT_CFLAGS/ad_i486.o = -c
OPT_CFLAGS/ad_i486_gen.o = -c
OPT_CFLAGS/ad_i486_misc.o = -c
ifeq ($(Platform_arch), i486)
# Same problem for the wrapper roosts: jni.o jvm.o # Same problem for the wrapper roosts: jni.o jvm.o
OPT_CFLAGS/jni.o = -c OPT_CFLAGS/jni.o = -c
OPT_CFLAGS/jvm.o = -c OPT_CFLAGS/jvm.o = -c
# Same problem in parse2.o (probably the Big Switch over bytecodes) # Same problem in parse2.o (probably the Big Switch over bytecodes)
OPT_CFLAGS/parse2.o = -c OPT_CFLAGS/parse2.o = -c
endif # Platform_arch == i486 endif # Platform_arch == x86
endif endif
# Frame size > 100k if we allow inlining via -g0! # Frame size > 100k if we allow inlining via -g0!
DEBUG_CFLAGS/bytecodeInterpreter.o = -g DEBUG_CFLAGS/bytecodeInterpreter.o = -g
DEBUG_CFLAGS/bytecodeInterpreterWithChecks.o = -g DEBUG_CFLAGS/bytecodeInterpreterWithChecks.o = -g
ifeq ($(Platform_arch), i486) ifeq ($(Platform_arch), x86)
# ube explodes on x86 # ube explodes on x86
OPT_CFLAGS/bytecodeInterpreter.o = -xO1 OPT_CFLAGS/bytecodeInterpreter.o = -xO1
OPT_CFLAGS/bytecodeInterpreterWithChecks.o = -xO1 OPT_CFLAGS/bytecodeInterpreterWithChecks.o = -xO1
endif # Platform_arch == i486 endif # Platform_arch == x86
endif # Platform_compiler == sparcWorks endif # Platform_compiler == sparcWorks

View file

@ -35,17 +35,13 @@ Obj_Files += solaris_x86_32.o
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
# _lwp_create_interpose must have a frame # _lwp_create_interpose must have a frame
OPT_CFLAGS/os_solaris_i486.o = -xO1 OPT_CFLAGS/os_solaris_x86.o = -xO1
# force C++ interpreter to be full optimization
OPT_CFLAGS/interpret.o = -fast -O4
else else
ifeq ("${Platform_compiler}", "gcc") ifeq ("${Platform_compiler}", "gcc")
# gcc # gcc
# _lwp_create_interpose must have a frame # _lwp_create_interpose must have a frame
OPT_CFLAGS/os_solaris_i486.o = -fno-omit-frame-pointer OPT_CFLAGS/os_solaris_x86.o = -fno-omit-frame-pointer
# force C++ interpreter to be full optimization
OPT_CFLAGS/interpret.o = -O3
# #
else else
# error # error
@ -57,7 +53,7 @@ endif
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
# ILD is gone as of SS11 (5.8), not supported in SS10 (5.7) # ILD is gone as of SS11 (5.8), not supported in SS10 (5.7)
ifeq ($(shell expr $(COMPILER_REV) \< 5.7), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \< 507), 1)
# #
# Bug in ild causes it to fail randomly. Until we get a fix we can't # Bug in ild causes it to fail randomly. Until we get a fix we can't
# use ild. # use ild.

View file

@ -30,7 +30,7 @@ DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@)
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(COMPILER_REV),5.8) ifeq ($(COMPILER_REV_NUMERIC),508)
# SS11 SEGV when compiling with -g and -xarch=v8, using different backend # SS11 SEGV when compiling with -g and -xarch=v8, using different backend
DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0 DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0
DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0 DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0

View file

@ -33,7 +33,7 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
# Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876) # Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876)
ifeq ($(COMPILER_REV),5.9) ifeq ($(COMPILER_REV_NUMERIC),509)
# Not clear this workaround could be skipped in some cases. # Not clear this workaround could be skipped in some cases.
OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g
OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g
@ -41,9 +41,9 @@ ifeq ($(COMPILER_REV),5.9)
endif endif
# Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12) # Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12)
ifeq ($(COMPILER_REV),5.8)) ifeq ($(COMPILER_REV_NUMERIC),508))
OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2) OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2)
endif # COMPILER_REV == 5.8 endif # COMPILER_REV_NUMERIC == 508
endif # Platform_compiler == sparcWorks endif # Platform_compiler == sparcWorks

View file

@ -41,7 +41,7 @@ endif
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
# Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876) # Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876)
ifeq ($(COMPILER_REV),5.9) ifeq ($(COMPILER_REV_NUMERIC),509)
# Not clear this workaround could be skipped in some cases. # Not clear this workaround could be skipped in some cases.
OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) -g
OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) -g
@ -49,9 +49,9 @@ ifeq ($(COMPILER_REV),5.9)
endif endif
# Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12) # Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12)
ifeq ($(COMPILER_REV),5.8) ifeq ($(COMPILER_REV_NUMERIC),508)
OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2) OPT_CFLAGS/ciTypeFlow.o = $(OPT_CFLAGS/O2)
endif # COMPILER_REV == 5.8 endif # COMPILER_REV_NUMERIC == 508
endif # Platform_compiler == sparcWorks endif # Platform_compiler == sparcWorks

View file

@ -26,7 +26,7 @@ Obj_Files += solaris_sparc.o
ASFLAGS += $(AS_ARCHFLAG) ASFLAGS += $(AS_ARCHFLAG)
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(shell expr $(COMPILER_REV) \< 5.5), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \< 505), 1)
# For 5.2 ad_sparc file is compiled with -O2 %%%% remove when adlc is fixed # For 5.2 ad_sparc file is compiled with -O2 %%%% remove when adlc is fixed
OPT_CFLAGS/ad_sparc.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/ad_sparc.o = $(OPT_CFLAGS/SLOWER)
OPT_CFLAGS/dfa_sparc.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/dfa_sparc.o = $(OPT_CFLAGS/SLOWER)
@ -39,7 +39,7 @@ OPT_CFLAGS/carRememberedSet.o = $(OPT_CFLAGS/O2)
OPT_CFLAGS/jniHandles.o = $(OPT_CFLAGS/O2) OPT_CFLAGS/jniHandles.o = $(OPT_CFLAGS/O2)
# CC brings an US-II to its knees compiling the vmStructs asserts under -xO4 # CC brings an US-II to its knees compiling the vmStructs asserts under -xO4
OPT_CFLAGS/vmStructs.o = $(OPT_CFLAGS/O2) OPT_CFLAGS/vmStructs.o = $(OPT_CFLAGS/O2)
endif endif # COMPILER_REV_NUMERIC < 505
else else
# Options for gcc # Options for gcc
OPT_CFLAGS/ad_sparc.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/ad_sparc.o = $(OPT_CFLAGS/SLOWER)

View file

@ -41,9 +41,9 @@ REORDER_FLAG = -xF
# Get the last thing on the line that looks like x.x+ (x is a digit). # Get the last thing on the line that looks like x.x+ (x is a digit).
COMPILER_REV := \ COMPILER_REV := \
$(shell $(CPP) -V 2>&1 | sed -e 's/^.*\([1-9]\.[0-9][0-9]*\).*/\1/') $(shell $(CPP) -V 2>&1 | sed -n 's/^.*[ ,\t]C++[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/p')
C_COMPILER_REV := \ C_COMPILER_REV := \
$(shell $(CC) -V 2>&1 | grep -i "cc:" | sed -e 's/^.*\([1-9]\.[0-9][0-9]*\).*/\1/') $(shell $(CC) -V 2>&1 | sed -n 's/^.*[ ,\t]C[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/p')
# Pick which compiler is validated # Pick which compiler is validated
ifeq ($(JDK_MINOR_VERSION),6) ifeq ($(JDK_MINOR_VERSION),6)
@ -60,17 +60,19 @@ endif
ENFORCE_COMPILER_REV${ENFORCE_COMPILER_REV} := ${VALIDATED_COMPILER_REV} ENFORCE_COMPILER_REV${ENFORCE_COMPILER_REV} := ${VALIDATED_COMPILER_REV}
ifneq (${COMPILER_REV},${ENFORCE_COMPILER_REV}) ifneq (${COMPILER_REV},${ENFORCE_COMPILER_REV})
dummy_target_to_enforce_compiler_rev:=\ dummy_target_to_enforce_compiler_rev:=\
$(info WARNING: You are using CC version ${COMPILER_REV} \ $(shell echo >&2 WARNING: You are using CC version ${COMPILER_REV} \
and should be using version ${ENFORCE_COMPILER_REV}) and should be using version ${ENFORCE_COMPILER_REV}. Set ENFORCE_COMPILER_REV=${COMPILER_REV} to avoid this warning.)
endif endif
ENFORCE_C_COMPILER_REV${ENFORCE_C_COMPILER_REV} := ${VALIDATED_C_COMPILER_REV} ENFORCE_C_COMPILER_REV${ENFORCE_C_COMPILER_REV} := ${VALIDATED_C_COMPILER_REV}
ifneq (${C_COMPILER_REV},${ENFORCE_C_COMPILER_REV}) ifneq (${C_COMPILER_REV},${ENFORCE_C_COMPILER_REV})
dummy_target_to_enforce_c_compiler_rev:=\ dummy_target_to_enforce_c_compiler_rev:=\
$(info WARNING: You are using cc version ${C_COMPILER_REV} \ $(shell echo >&2 WARNING: You are using cc version ${C_COMPILER_REV} \
and should be using version ${ENFORCE_C_COMPILER_REV}) and should be using version ${ENFORCE_C_COMPILER_REV}. Set ENFORCE_C_COMPILER_REV=${C_COMPILER_REV} to avoid this warning.)
endif endif
COMPILER_REV_NUMERIC := $(shell echo $(COMPILER_REV) | awk -F. '{ print $$1 * 100 + $$2 }')
# Fail the build if __fabsf is used. __fabsf exists only in Solaris 8 2/04 # Fail the build if __fabsf is used. __fabsf exists only in Solaris 8 2/04
# and newer; objects with a dependency on this symbol will not run on older # and newer; objects with a dependency on this symbol will not run on older
# Solaris 8. # Solaris 8.
@ -120,7 +122,7 @@ ARCHFLAG_OLD/amd64 = -xarch=amd64
ARCHFLAG_NEW/amd64 = -m64 ARCHFLAG_NEW/amd64 = -m64
# Select the ARCHFLAGs and other SS12 (5.9) options # Select the ARCHFLAGs and other SS12 (5.9) options
ifeq ($(shell expr $(COMPILER_REV) \>= 5.9), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
ARCHFLAG/sparc = $(ARCHFLAG_NEW/sparc) ARCHFLAG/sparc = $(ARCHFLAG_NEW/sparc)
ARCHFLAG/sparcv9 = $(ARCHFLAG_NEW/sparcv9) ARCHFLAG/sparcv9 = $(ARCHFLAG_NEW/sparcv9)
ARCHFLAG/i486 = $(ARCHFLAG_NEW/i486) ARCHFLAG/i486 = $(ARCHFLAG_NEW/i486)
@ -150,7 +152,7 @@ OPT_CFLAGS/NOOPT=-xO1
# Begin current (>=5.6) Forte compiler options # # Begin current (>=5.6) Forte compiler options #
################################################# #################################################
ifeq ($(shell expr $(COMPILER_REV) \>= 5.6), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 506), 1)
ifeq ("${Platform_arch}", "sparc") ifeq ("${Platform_arch}", "sparc")
@ -167,7 +169,7 @@ endif
# Begin current (>=5.5) Forte compiler options # # Begin current (>=5.5) Forte compiler options #
################################################# #################################################
ifeq ($(shell expr $(COMPILER_REV) \>= 5.5), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 505), 1)
CFLAGS += $(ARCHFLAG) CFLAGS += $(ARCHFLAG)
AOUT_FLAGS += $(ARCHFLAG) AOUT_FLAGS += $(ARCHFLAG)
@ -255,7 +257,7 @@ LFLAGS += -library=%none
LFLAGS += -mt LFLAGS += -mt
endif # COMPILER_REV >= 5.5 endif # COMPILER_REV_NUMERIC >= 505
###################################### ######################################
# End 5.5 Forte compiler options # # End 5.5 Forte compiler options #
@ -265,7 +267,7 @@ endif # COMPILER_REV >= 5.5
# Begin 5.2 Forte compiler options # # Begin 5.2 Forte compiler options #
###################################### ######################################
ifeq ($(COMPILER_REV), 5.2) ifeq ($(COMPILER_REV_NUMERIC), 502)
CFLAGS += $(ARCHFLAG) CFLAGS += $(ARCHFLAG)
AOUT_FLAGS += $(ARCHFLAG) AOUT_FLAGS += $(ARCHFLAG)
@ -324,7 +326,7 @@ PICFLAG/BYFILE = $(PICFLAG/$@)$(PICFLAG/DEFAULT$(PICFLAG/$@))
LFLAGS += -library=Crun LFLAGS += -library=Crun
LIBS += -library=Crun -lCrun LIBS += -library=Crun -lCrun
endif # COMPILER_REV == 5.2 endif # COMPILER_REV_NUMERIC == 502
################################## ##################################
# End 5.2 Forte compiler options # # End 5.2 Forte compiler options #
@ -333,7 +335,7 @@ endif # COMPILER_REV == 5.2
################################## ##################################
# Begin old 5.1 compiler options # # Begin old 5.1 compiler options #
################################## ##################################
ifeq ($(COMPILER_REV), 5.1) ifeq ($(COMPILER_REV_NUMERIC), 501)
_JUNK_ := $(shell echo >&2 \ _JUNK_ := $(shell echo >&2 \
"*** ERROR: sparkWorks.make incomplete for 5.1 compiler") "*** ERROR: sparkWorks.make incomplete for 5.1 compiler")
@ -347,7 +349,7 @@ endif
# Begin old 5.0 compiler options # # Begin old 5.0 compiler options #
################################## ##################################
ifeq (${COMPILER_REV}, 5.0) ifeq (${COMPILER_REV_NUMERIC}, 500)
# Had to hoist this higher apparently because of other changes. Must # Had to hoist this higher apparently because of other changes. Must
# come before -xarch specification. # come before -xarch specification.
@ -379,7 +381,7 @@ endif # sparc
ifeq ("${Platform_arch_model}", "x86_32") ifeq ("${Platform_arch_model}", "x86_32")
OPT_CFLAGS=-xtarget=pentium $(EXTRA_OPT_CFLAGS) OPT_CFLAGS=-xtarget=pentium $(EXTRA_OPT_CFLAGS)
ifeq ("${COMPILER_REV}", "5.0") ifeq ("${COMPILER_REV_NUMERIC}", "500")
# SC5.0 tools on x86 are flakey at -xO4 # SC5.0 tools on x86 are flakey at -xO4
OPT_CFLAGS+=-xO3 OPT_CFLAGS+=-xO3
else else
@ -405,13 +407,13 @@ PICFLAG/DEFAULT = $(PICFLAG)
PICFLAG/BETTER = $(PICFLAG/DEFAULT) PICFLAG/BETTER = $(PICFLAG/DEFAULT)
PICFLAG/BYFILE = $(PICFLAG/$@)$(PICFLAG/DEFAULT$(PICFLAG/$@)) PICFLAG/BYFILE = $(PICFLAG/$@)$(PICFLAG/DEFAULT$(PICFLAG/$@))
endif # COMPILER_REV = 5.0 endif # COMPILER_REV_NUMERIC = 500
################################ ################################
# End old 5.0 compiler options # # End old 5.0 compiler options #
################################ ################################
ifeq ("${COMPILER_REV}", "4.2") ifeq ("${COMPILER_REV_NUMERIC}", "402")
# 4.2 COMPILERS SHOULD NO LONGER BE USED # 4.2 COMPILERS SHOULD NO LONGER BE USED
_JUNK_ := $(shell echo >&2 \ _JUNK_ := $(shell echo >&2 \
"*** ERROR: SC4.2 compilers are not supported by this code base!") "*** ERROR: SC4.2 compilers are not supported by this code base!")
@ -443,7 +445,7 @@ LINK_MODE/debug =
LINK_MODE/optimized = -Bsymbolic -znodefs LINK_MODE/optimized = -Bsymbolic -znodefs
# Have thread local errnos # Have thread local errnos
ifeq ($(shell expr $(COMPILER_REV) \>= 5.5), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 505), 1)
CFLAGS += -mt CFLAGS += -mt
else else
CFLAGS += -D_REENTRANT CFLAGS += -D_REENTRANT
@ -460,7 +462,7 @@ FASTDEBUG_CFLAGS = -g0
# The -g0 setting allows the C++ frontend to inline, which is a big win. # The -g0 setting allows the C++ frontend to inline, which is a big win.
# Special global options for SS12 # Special global options for SS12
ifeq ($(COMPILER_REV),5.9) ifeq ($(COMPILER_REV_NUMERIC),509)
# There appears to be multiple issues with the new Dwarf2 debug format, so # There appears to be multiple issues with the new Dwarf2 debug format, so
# we tell the compiler to use the older 'stabs' debug format all the time. # we tell the compiler to use the older 'stabs' debug format all the time.
# Note that this needs to be used in optimized compiles too to be 100%. # Note that this needs to be used in optimized compiles too to be 100%.
@ -479,8 +481,8 @@ endif
#DEBUG_CFLAGS += -Qoption ccfe -xglobalstatic #DEBUG_CFLAGS += -Qoption ccfe -xglobalstatic
#FASTDEBUG_CFLAGS += -Qoption ccfe -xglobalstatic #FASTDEBUG_CFLAGS += -Qoption ccfe -xglobalstatic
ifeq (${COMPILER_REV}, 5.2) ifeq (${COMPILER_REV_NUMERIC}, 502)
COMPILER_DATE := $(shell $(CPP) -V 2>&1 | awk '{ print $$NF; }') COMPILER_DATE := $(shell $(CPP) -V 2>&1 | sed -n '/^.*[ ]C++[ ]\([1-9]\.[0-9][0-9]*\)/p' | awk '{ print $$NF; }')
ifeq (${COMPILER_DATE}, 2001/01/31) ifeq (${COMPILER_DATE}, 2001/01/31)
# disable -g0 in fastdebug since SC6.1 dated 2001/01/31 seems to be buggy # disable -g0 in fastdebug since SC6.1 dated 2001/01/31 seems to be buggy
# use an innocuous value because it will get -g if it's empty # use an innocuous value because it will get -g if it's empty
@ -493,7 +495,7 @@ endif
CFLAGS += $(CFLAGS_BROWSE) CFLAGS += $(CFLAGS_BROWSE)
# ILD is gone as of SS11 (5.8), not supportted in SS10 (5.7) # ILD is gone as of SS11 (5.8), not supportted in SS10 (5.7)
ifeq ($(shell expr $(COMPILER_REV) \< 5.7), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \< 507), 1)
# use ild when debugging (but when optimizing we want reproducible results) # use ild when debugging (but when optimizing we want reproducible results)
ILDFLAG = $(ILDFLAG/$(VERSION)) ILDFLAG = $(ILDFLAG/$(VERSION))
ILDFLAG/debug = -xildon ILDFLAG/debug = -xildon

View file

@ -26,7 +26,7 @@ Obj_Files += solaris_sparc.o
ASFLAGS += $(AS_ARCHFLAG) ASFLAGS += $(AS_ARCHFLAG)
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
ifeq ($(shell expr $(COMPILER_REV) \< 5.5), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \< 505), 1)
# When optimized fully, stubGenerator_sparc.cpp # When optimized fully, stubGenerator_sparc.cpp
# has bogus code for the routine # has bogus code for the routine
# StubGenerator::generate_flush_callers_register_windows() # StubGenerator::generate_flush_callers_register_windows()

View file

@ -83,9 +83,9 @@ Incremental_Lists =$(GENERATED)/$(Cached_db)
AD_Dir = $(GENERATED)/adfiles AD_Dir = $(GENERATED)/adfiles
ADLC = $(AD_Dir)/adlc ADLC = $(AD_Dir)/adlc
AD_Spec = $(GAMMADIR)/src/cpu/$(Platform_arch)/vm/$(Platform_arch).ad AD_Spec = $(GAMMADIR)/src/cpu/$(Platform_arch)/vm/$(Platform_arch_model).ad
AD_Src = $(GAMMADIR)/src/share/vm/adlc AD_Src = $(GAMMADIR)/src/share/vm/adlc
AD_Names = ad_$(Platform_arch).hpp ad_$(Platform_arch).cpp AD_Names = ad_$(Platform_arch_model).hpp ad_$(Platform_arch_model).cpp
AD_Files = $(AD_Names:%=$(AD_Dir)/%) AD_Files = $(AD_Names:%=$(AD_Dir)/%)
# AD_Files_If_Required/COMPILER1 = ad_stuff # AD_Files_If_Required/COMPILER1 = ad_stuff

View file

@ -101,7 +101,7 @@ LIBM=/usr/lib$(ISA_DIR)/libm.so.1
ifeq ("${Platform_compiler}", "sparcWorks") ifeq ("${Platform_compiler}", "sparcWorks")
# The whole megilla: # The whole megilla:
ifeq ($(shell expr $(COMPILER_REV) \>= 5.5), 1) ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 505), 1)
# Old Comment: List the libraries in the order the compiler was designed for # Old Comment: List the libraries in the order the compiler was designed for
# Not sure what the 'designed for' comment is referring too above. # Not sure what the 'designed for' comment is referring too above.
# The order may not be too significant anymore, but I have placed this # The order may not be too significant anymore, but I have placed this

View file

@ -102,6 +102,12 @@ GENERATED_NAMES_IN_INCL=\
adlc.exe: main.obj adlparse.obj archDesc.obj arena.obj dfa.obj dict2.obj filebuff.obj \ adlc.exe: main.obj adlparse.obj archDesc.obj arena.obj dfa.obj dict2.obj filebuff.obj \
forms.obj formsopt.obj formssel.obj opcodes.obj output_c.obj output_h.obj forms.obj formsopt.obj formssel.obj opcodes.obj output_c.obj output_h.obj
$(LINK) $(LINK_FLAGS) /subsystem:console /out:$@ $** $(LINK) $(LINK_FLAGS) /subsystem:console /out:$@ $**
!if "$(MT)" != ""
# The previous link command created a .manifest file that we want to
# insert into the linked artifact so we do not need to track it
# separately. Use ";#2" for .dll and ";#1" for .exe:
$(MT) /manifest $@.manifest /outputresource:$@;#1
!endif
$(GENERATED_NAMES_IN_INCL): $(Platform_arch_model).ad adlc.exe includeDB.current $(GENERATED_NAMES_IN_INCL): $(Platform_arch_model).ad adlc.exe includeDB.current
rm -f $(GENERATED_NAMES) rm -f $(GENERATED_NAMES)

View file

@ -30,7 +30,7 @@ CPP=cl.exe
# /W3 Warning level 3 # /W3 Warning level 3
# /Zi Include debugging information # /Zi Include debugging information
# /WX Treat any warning error as a fatal error # /WX Treat any warning error as a fatal error
# /MD Use dynamic multi-threaded runtime (msvcrt.dll or msvc*71.dll) # /MD Use dynamic multi-threaded runtime (msvcrt.dll or msvc*NN.dll)
# /MTd Use static multi-threaded runtime debug versions # /MTd Use static multi-threaded runtime debug versions
# /O1 Optimize for size (/Os), skips /Oi # /O1 Optimize for size (/Os), skips /Oi
# /O2 Optimize for speed (/Ot), adds /Oi to /O1 # /O2 Optimize for speed (/Ot), adds /Oi to /O1
@ -80,8 +80,10 @@ CPP_FLAGS=$(CPP_FLAGS) /D "IA32"
CPP=ARCH_ERROR CPP=ARCH_ERROR
!endif !endif
# MSC_VER is a 4 digit number that tells us what compiler is being used, it is # MSC_VER is a 4 digit number that tells us what compiler is being used
# generated when the local.make file is created by the script gen_msc_ver.sh. # and is generated when the local.make file is created by build.make
# via the script get_msc_ver.sh
#
# If MSC_VER is set, it overrides the above default setting. # If MSC_VER is set, it overrides the above default setting.
# But it should be set. # But it should be set.
# Possible values: # Possible values:
@ -89,13 +91,14 @@ CPP=ARCH_ERROR
# 1300 and 1310 is VS2003 or VC7 # 1300 and 1310 is VS2003 or VC7
# 1399 is our fake number for the VS2005 compiler that really isn't 1400 # 1399 is our fake number for the VS2005 compiler that really isn't 1400
# 1400 is for VS2005 # 1400 is for VS2005
# 1500 is for VS2008
# Do not confuse this MSC_VER with the predefined macro _MSC_VER that the # Do not confuse this MSC_VER with the predefined macro _MSC_VER that the
# compiler provides, when MSC_VER==1399, _MSC_VER will be 1400. # compiler provides, when MSC_VER==1399, _MSC_VER will be 1400.
# Normally they are the same, but a pre-release of the VS2005 compilers # Normally they are the same, but a pre-release of the VS2005 compilers
# in the Windows 64bit Platform SDK said it was 1400 when it was really # in the Windows 64bit Platform SDK said it was 1400 when it was really
# closer to VS2003 in terms of option spellings, so we use 1399 for that # closer to VS2003 in terms of option spellings, so we use 1399 for that
# 1400 version that really isn't 1400. # 1400 version that really isn't 1400.
# See the file gen_msc_ver.sh for more info. # See the file get_msc_ver.sh for more info.
!if "x$(MSC_VER)" == "x" !if "x$(MSC_VER)" == "x"
COMPILER_NAME=$(DEFAULT_COMPILER_NAME) COMPILER_NAME=$(DEFAULT_COMPILER_NAME)
!else !else
@ -115,6 +118,9 @@ COMPILER_NAME=VS2003
!if "$(MSC_VER)" == "1400" !if "$(MSC_VER)" == "1400"
COMPILER_NAME=VS2005 COMPILER_NAME=VS2005
!endif !endif
!if "$(MSC_VER)" == "1500"
COMPILER_NAME=VS2008
!endif
!endif !endif
# Add what version of the compiler we think this is to the compile line # Add what version of the compiler we think this is to the compile line
@ -160,7 +166,25 @@ GX_OPTION = /EHsc
# externals at link time. Even with /GS-, you need bufferoverflowU.lib. # externals at link time. Even with /GS-, you need bufferoverflowU.lib.
# NOTE: Currently we decided to not use /GS- # NOTE: Currently we decided to not use /GS-
BUFFEROVERFLOWLIB = bufferoverflowU.lib BUFFEROVERFLOWLIB = bufferoverflowU.lib
LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) LINK_FLAGS = /manifest $(LINK_FLAGS) $(BUFFEROVERFLOWLIB)
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
MT=mt.exe
!if "$(BUILDARCH)" == "i486"
# VS2005 on x86 restricts the use of certain libc functions without this
CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE
!endif
!endif
!if "$(COMPILER_NAME)" == "VS2008"
PRODUCT_OPT_OPTION = /O2 /Oy-
FASTDEBUG_OPT_OPTION = /O2 /Oy-
DEBUG_OPT_OPTION = /Od
GX_OPTION = /EHsc
LINK_FLAGS = /manifest $(LINK_FLAGS)
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
MT=mt.exe
!if "$(BUILDARCH)" == "i486" !if "$(BUILDARCH)" == "i486"
# VS2005 on x86 restricts the use of certain libc functions without this # VS2005 on x86 restricts the use of certain libc functions without this
CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE

View file

@ -50,6 +50,12 @@ $(AOUT): $(Res_Files) $(Obj_Files)
$(LINK) @<< $(LINK) @<<
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<< <<
!if "$(MT)" != ""
# The previous link command created a .manifest file that we want to
# insert into the linked artifact so we do not need to track it
# separately. Use ";#2" for .dll and ";#1" for .exe:
$(MT) /manifest $@.manifest /outputresource:$@;#2
!endif
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make

View file

@ -25,7 +25,7 @@
# The common definitions for hotspot windows builds. # The common definitions for hotspot windows builds.
# Include the top level defs.make under make directory instead of this one. # Include the top level defs.make under make directory instead of this one.
# This file is included into make/defs.make. # This file is included into make/defs.make.
# On windows it is only used to construct parameters for # On windows it is only used to construct parameters for
# make/windows/build.make when make/Makefile is used to build VM. # make/windows/build.make when make/Makefile is used to build VM.
SLASH_JAVA ?= J: SLASH_JAVA ?= J:
@ -69,7 +69,7 @@ endif
JDK_INCLUDE_SUBDIR=win32 JDK_INCLUDE_SUBDIR=win32
# HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined # HOTSPOT_RELEASE_VERSION and HOTSPOT_BUILD_VERSION are defined
# and added to MAKE_ARGS list in $(GAMMADIR)/make/defs.make. # and added to MAKE_ARGS list in $(GAMMADIR)/make/defs.make.
# next parameters are defined in $(GAMMADIR)/make/defs.make. # next parameters are defined in $(GAMMADIR)/make/defs.make.
@ -125,7 +125,7 @@ ifneq ($(ALT_BUILD_WIN_SA),)
endif endif
ifeq ($(BUILD_WIN_SA), 1) ifeq ($(BUILD_WIN_SA), 1)
ifeq ($(ARCH),ia64) ifeq ($(ARCH),ia64)
BUILD_WIN_SA = 0 BUILD_WIN_SA = 0
endif endif
endif endif
@ -154,7 +154,7 @@ ifeq ($(BUILD_WIN_SA), 1)
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.dll EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.dll
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.pdb
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.map
EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar EXPORT_LIST += $(EXPORT_LIB_DIR)/sa-jdi.jar
# Must pass this down to nmake. # Must pass this down to nmake.
MAKE_ARGS += BUILD_WIN_SA=1 MAKE_ARGS += BUILD_WIN_SA=1
endif endif

View file

@ -50,6 +50,13 @@ $(AOUT): $(Res_Files) $(Obj_Files)
$(LINK) @<< $(LINK) @<<
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<< <<
!if "$(MT)" != ""
# The previous link command created a .manifest file that we want to
# insert into the linked artifact so we do not need to track it
# separately. Use ";#2" for .dll and ";#1" for .exe:
$(MT) /manifest $@.manifest /outputresource:$@;#2
!endif
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make

View file

@ -61,6 +61,12 @@ $(AOUT): $(Res_Files) $(Obj_Files)
$(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files)
<< <<
!endif !endif
!if "$(MT)" != ""
# The previous link command created a .manifest file that we want to
# insert into the linked artifact so we do not need to track it
# separately. Use ";#2" for .dll and ";#1" for .exe:
$(MT) /manifest $@.manifest /outputresource:$@;#2
!endif
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make

View file

@ -92,13 +92,18 @@ SA_LINK_FLAGS = bufferoverflowU.lib
!else !else
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 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 !endif
!if "$(MT)" != ""
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
!endif
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE) SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)
# Note that we do not keep sawindbj.obj around as it would then # Note that we do not keep sawindbj.obj around as it would then
# get included in the dumpbin command in build_vm_def.sh # get included in the dumpbin command in build_vm_def.sh
# In VS2005 or VS2008 the link command creates a .manifest file that we want
# to insert into the linked artifact so we do not need to track it separately.
# Use ";#2" for .dll and ";#1" for .exe in the MT command below:
$(SAWINDBG): $(SASRCFILE) $(SAWINDBG): $(SASRCFILE)
set INCLUDE=$(SA_INCLUDE)$(INCLUDE) set INCLUDE=$(SA_INCLUDE)$(INCLUDE)
$(CPP) @<< $(CPP) @<<
@ -109,6 +114,9 @@ $(SAWINDBG): $(SASRCFILE)
<< <<
set LIB=$(SA_LIB)$(LIB) set LIB=$(SA_LIB)$(LIB)
$(LINK) /out:$@ /DLL sawindbg.obj dbgeng.lib $(SA_LFLAGS) $(LINK) /out:$@ /DLL sawindbg.obj dbgeng.lib $(SA_LFLAGS)
!if "$(MT)" != ""
$(MT) /manifest $(@F).manifest /outputresource:$(@F);#2
!endif
-@rm -f sawindbg.obj -@rm -f sawindbg.obj
cleanall : cleanall :

View file

@ -56,7 +56,8 @@ IncludeDBs_gc=$(HOTSPOTWORKSPACE)/src/share/vm/includeDB_gc_parallel \
$(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_shared \ $(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_shared \
$(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_parNew \ $(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_parNew \
$(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge \ $(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge \
$(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep $(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_concurrentMarkSweep \
$(HOTSPOTWORKSPACE)/src/share/vm/gc_implementation/includeDB_gc_g1
IncludeDBs_kernel =$(IncludeDBs_base) \ IncludeDBs_kernel =$(IncludeDBs_base) \

View file

@ -22,9 +22,6 @@
* *
*/ */
// make sure the defines don't screw up the declarations later on in this file
#define DONT_USE_REGISTER_DEFINES
#include "incls/_precompiled.incl" #include "incls/_precompiled.incl"
#include "incls/_register_definitions_x86.cpp.incl" #include "incls/_register_definitions_x86.cpp.incl"

View file

@ -3756,7 +3756,6 @@ int set_lwp_priority (int ThreadID, int lwpid, int newPrio )
int maxClamped = MIN2(iaLimits.maxPrio, (int)iaInfo->ia_uprilim); int maxClamped = MIN2(iaLimits.maxPrio, (int)iaInfo->ia_uprilim);
iaInfo->ia_upri = scale_to_lwp_priority(iaLimits.minPrio, maxClamped, newPrio); iaInfo->ia_upri = scale_to_lwp_priority(iaLimits.minPrio, maxClamped, newPrio);
iaInfo->ia_uprilim = IA_NOCHANGE; iaInfo->ia_uprilim = IA_NOCHANGE;
iaInfo->ia_nice = IA_NOCHANGE;
iaInfo->ia_mode = IA_NOCHANGE; iaInfo->ia_mode = IA_NOCHANGE;
if (ThreadPriorityVerbose) { if (ThreadPriorityVerbose) {
tty->print_cr ("IA: [%d...%d] %d->%d\n", tty->print_cr ("IA: [%d...%d] %d->%d\n",

View file

@ -212,9 +212,9 @@ ArchDesc::ArchDesc()
// Initialize I/O Files // Initialize I/O Files
_ADL_file._name = NULL; _ADL_file._fp = NULL; _ADL_file._name = NULL; _ADL_file._fp = NULL;
// Machine dependent output files // Machine dependent output files
_DFA_file._name = "dfa_i486.cpp"; _DFA_file._fp = NULL; _DFA_file._name = NULL; _DFA_file._fp = NULL;
_HPP_file._name = "ad_i486.hpp"; _HPP_file._fp = NULL; _HPP_file._name = NULL; _HPP_file._fp = NULL;
_CPP_file._name = "ad_i486.cpp"; _CPP_file._fp = NULL; _CPP_file._name = NULL; _CPP_file._fp = NULL;
_bug_file._name = "bugs.out"; _bug_file._fp = NULL; _bug_file._name = "bugs.out"; _bug_file._fp = NULL;
// Initialize Register & Pipeline Form Pointers // Initialize Register & Pipeline Form Pointers

View file

@ -574,12 +574,23 @@ void ComputeLinearScanOrder::count_edges(BlockBegin* cur, BlockBegin* parent) {
TRACE_LINEAR_SCAN(3, tty->print_cr("backward branch")); TRACE_LINEAR_SCAN(3, tty->print_cr("backward branch"));
assert(is_visited(cur), "block must be visisted when block is active"); assert(is_visited(cur), "block must be visisted when block is active");
assert(parent != NULL, "must have parent"); assert(parent != NULL, "must have parent");
assert(parent->number_of_sux() == 1, "loop end blocks must have one successor (critical edges are split)");
cur->set(BlockBegin::linear_scan_loop_header_flag); cur->set(BlockBegin::linear_scan_loop_header_flag);
cur->set(BlockBegin::backward_branch_target_flag); cur->set(BlockBegin::backward_branch_target_flag);
parent->set(BlockBegin::linear_scan_loop_end_flag); parent->set(BlockBegin::linear_scan_loop_end_flag);
// When a loop header is also the start of an exception handler, then the backward branch is
// an exception edge. Because such edges are usually critical edges which cannot be split, the
// loop must be excluded here from processing.
if (cur->is_set(BlockBegin::exception_entry_flag)) {
// Make sure that dominators are correct in this weird situation
_iterative_dominators = true;
return;
}
assert(parent->number_of_sux() == 1 && parent->sux_at(0) == cur,
"loop end blocks must have one successor (critical edges are split)");
_loop_end_blocks.append(parent); _loop_end_blocks.append(parent);
return; return;
} }

View file

@ -484,11 +484,16 @@ ciConstant ciEnv::get_constant_by_index_impl(ciInstanceKlass* accessor,
} else if (tag.is_double()) { } else if (tag.is_double()) {
return ciConstant((jdouble)cpool->double_at(index)); return ciConstant((jdouble)cpool->double_at(index));
} else if (tag.is_string() || tag.is_unresolved_string()) { } else if (tag.is_string() || tag.is_unresolved_string()) {
oop string = cpool->string_at(index, THREAD); oop string = NULL;
if (HAS_PENDING_EXCEPTION) { if (cpool->is_pseudo_string_at(index)) {
CLEAR_PENDING_EXCEPTION; string = cpool->pseudo_string_at(index);
record_out_of_memory_failure(); } else {
return ciConstant(); string = cpool->string_at(index, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
record_out_of_memory_failure();
return ciConstant();
}
} }
ciObject* constant = get_object(string); ciObject* constant = get_object(string);
assert (constant->is_instance(), "must be an instance, or not? "); assert (constant->is_instance(), "must be an instance, or not? ");

View file

@ -168,11 +168,23 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
// Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward. // Got utf8 string, guarantee utf8_length+1 bytes, set stream position forward.
cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags cfs->guarantee_more(utf8_length+1, CHECK); // utf8 string, tag/access_flags
cfs->skip_u1_fast(utf8_length); cfs->skip_u1_fast(utf8_length);
// Before storing the symbol, make sure it's legal // Before storing the symbol, make sure it's legal
if (_need_verify) { if (_need_verify) {
verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK); verify_legal_utf8((unsigned char*)utf8_buffer, utf8_length, CHECK);
} }
if (AnonymousClasses && has_cp_patch_at(index)) {
Handle patch = clear_cp_patch_at(index);
guarantee_property(java_lang_String::is_instance(patch()),
"Illegal utf8 patch at %d in class file %s",
index, CHECK);
char* str = java_lang_String::as_utf8_string(patch());
// (could use java_lang_String::as_symbol instead, but might as well batch them)
utf8_buffer = (u1*) str;
utf8_length = (int) strlen(str);
}
unsigned int hash; unsigned int hash;
symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash); symbolOop result = SymbolTable::lookup_only((char*)utf8_buffer, utf8_length, hash);
if (result == NULL) { if (result == NULL) {
@ -245,7 +257,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
int klass_ref_index = cp->klass_ref_index_at(index); int klass_ref_index = cp->klass_ref_index_at(index);
int name_and_type_ref_index = cp->name_and_type_ref_index_at(index); int name_and_type_ref_index = cp->name_and_type_ref_index_at(index);
check_property(valid_cp_range(klass_ref_index, length) && check_property(valid_cp_range(klass_ref_index, length) &&
cp->tag_at(klass_ref_index).is_klass_reference(), is_klass_reference(cp, klass_ref_index),
"Invalid constant pool index %u in class file %s", "Invalid constant pool index %u in class file %s",
klass_ref_index, klass_ref_index,
CHECK_(nullHandle)); CHECK_(nullHandle));
@ -326,16 +338,46 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
} // end of switch } // end of switch
} // end of for } // end of for
if (_cp_patches != NULL) {
// need to treat this_class specially...
assert(AnonymousClasses, "");
int this_class_index;
{
cfs->guarantee_more(8, CHECK_(nullHandle)); // flags, this_class, super_class, infs_len
u1* mark = cfs->current();
u2 flags = cfs->get_u2_fast();
this_class_index = cfs->get_u2_fast();
cfs->set_current(mark); // revert to mark
}
for (index = 1; index < length; index++) { // Index 0 is unused
if (has_cp_patch_at(index)) {
guarantee_property(index != this_class_index,
"Illegal constant pool patch to self at %d in class file %s",
index, CHECK_(nullHandle));
patch_constant_pool(cp, index, cp_patch_at(index), CHECK_(nullHandle));
}
}
// Ensure that all the patches have been used.
for (index = 0; index < _cp_patches->length(); index++) {
guarantee_property(!has_cp_patch_at(index),
"Unused constant pool patch at %d in class file %s",
index, CHECK_(nullHandle));
}
}
if (!_need_verify) { if (!_need_verify) {
return cp; return cp;
} }
// second verification pass - checks the strings are of the right format. // second verification pass - checks the strings are of the right format.
// but not yet to the other entries
for (index = 1; index < length; index++) { for (index = 1; index < length; index++) {
jbyte tag = cp->tag_at(index).value(); jbyte tag = cp->tag_at(index).value();
switch (tag) { switch (tag) {
case JVM_CONSTANT_UnresolvedClass: { case JVM_CONSTANT_UnresolvedClass: {
symbolHandle class_name(THREAD, cp->unresolved_klass_at(index)); symbolHandle class_name(THREAD, cp->unresolved_klass_at(index));
// check the name, even if _cp_patches will overwrite it
verify_legal_class_name(class_name, CHECK_(nullHandle)); verify_legal_class_name(class_name, CHECK_(nullHandle));
break; break;
} }
@ -378,6 +420,73 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
} }
void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS) {
assert(AnonymousClasses, "");
BasicType patch_type = T_VOID;
switch (cp->tag_at(index).value()) {
case JVM_CONSTANT_UnresolvedClass :
// Patching a class means pre-resolving it.
// The name in the constant pool is ignored.
if (patch->klass() == SystemDictionary::class_klass()) { // %%% java_lang_Class::is_instance
guarantee_property(!java_lang_Class::is_primitive(patch()),
"Illegal class patch at %d in class file %s",
index, CHECK);
cp->klass_at_put(index, java_lang_Class::as_klassOop(patch()));
} else {
guarantee_property(java_lang_String::is_instance(patch()),
"Illegal class patch at %d in class file %s",
index, CHECK);
symbolHandle name = java_lang_String::as_symbol(patch(), CHECK);
cp->unresolved_klass_at_put(index, name());
}
break;
case JVM_CONSTANT_UnresolvedString :
// Patching a string means pre-resolving it.
// The spelling in the constant pool is ignored.
// The constant reference may be any object whatever.
// If it is not a real interned string, the constant is referred
// to as a "pseudo-string", and must be presented to the CP
// explicitly, because it may require scavenging.
cp->pseudo_string_at_put(index, patch());
break;
case JVM_CONSTANT_Integer : patch_type = T_INT; goto patch_prim;
case JVM_CONSTANT_Float : patch_type = T_FLOAT; goto patch_prim;
case JVM_CONSTANT_Long : patch_type = T_LONG; goto patch_prim;
case JVM_CONSTANT_Double : patch_type = T_DOUBLE; goto patch_prim;
patch_prim:
{
jvalue value;
BasicType value_type = java_lang_boxing_object::get_value(patch(), &value);
guarantee_property(value_type == patch_type,
"Illegal primitive patch at %d in class file %s",
index, CHECK);
switch (value_type) {
case T_INT: cp->int_at_put(index, value.i); break;
case T_FLOAT: cp->float_at_put(index, value.f); break;
case T_LONG: cp->long_at_put(index, value.j); break;
case T_DOUBLE: cp->double_at_put(index, value.d); break;
default: assert(false, "");
}
}
break;
default:
// %%% TODO: put method handles into CONSTANT_InterfaceMethodref, etc.
guarantee_property(!has_cp_patch_at(index),
"Illegal unexpected patch at %d in class file %s",
index, CHECK);
return;
}
// On fall-through, mark the patch as used.
clear_cp_patch_at(index);
}
class NameSigHash: public ResourceObj { class NameSigHash: public ResourceObj {
public: public:
symbolOop _name; // name symbolOop _name; // name
@ -448,25 +557,32 @@ objArrayHandle ClassFileParser::parse_interfaces(constantPoolHandle cp,
int index; int index;
for (index = 0; index < length; index++) { for (index = 0; index < length; index++) {
u2 interface_index = cfs->get_u2(CHECK_(nullHandle)); u2 interface_index = cfs->get_u2(CHECK_(nullHandle));
KlassHandle interf;
check_property( check_property(
valid_cp_range(interface_index, cp->length()) && valid_cp_range(interface_index, cp->length()) &&
cp->tag_at(interface_index).is_unresolved_klass(), is_klass_reference(cp, interface_index),
"Interface name has bad constant pool index %u in class file %s", "Interface name has bad constant pool index %u in class file %s",
interface_index, CHECK_(nullHandle)); interface_index, CHECK_(nullHandle));
symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index)); if (cp->tag_at(interface_index).is_klass()) {
interf = KlassHandle(THREAD, cp->resolved_klass_at(interface_index));
} else {
symbolHandle unresolved_klass (THREAD, cp->klass_name_at(interface_index));
// Don't need to check legal name because it's checked when parsing constant pool. // Don't need to check legal name because it's checked when parsing constant pool.
// But need to make sure it's not an array type. // But need to make sure it's not an array type.
guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY, guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY,
"Bad interface name in class file %s", CHECK_(nullHandle)); "Bad interface name in class file %s", CHECK_(nullHandle));
vmtimer->suspend(); // do not count recursive loading twice vmtimer->suspend(); // do not count recursive loading twice
// Call resolve_super so classcircularity is checked // Call resolve_super so classcircularity is checked
klassOop k = SystemDictionary::resolve_super_or_fail(class_name, klassOop k = SystemDictionary::resolve_super_or_fail(class_name,
unresolved_klass, class_loader, protection_domain, unresolved_klass, class_loader, protection_domain,
false, CHECK_(nullHandle)); false, CHECK_(nullHandle));
KlassHandle interf (THREAD, k); interf = KlassHandle(THREAD, k);
vmtimer->resume(); vmtimer->resume();
cp->klass_at_put(interface_index, interf()); // eagerly resolve
}
if (!Klass::cast(interf())->is_interface()) { if (!Klass::cast(interf())->is_interface()) {
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle); THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", nullHandle);
@ -877,8 +993,7 @@ typeArrayHandle ClassFileParser::parse_exception_table(u4 code_length,
"Illegal exception table handler in class file %s", CHECK_(nullHandle)); "Illegal exception table handler in class file %s", CHECK_(nullHandle));
if (catch_type_index != 0) { if (catch_type_index != 0) {
guarantee_property(valid_cp_range(catch_type_index, cp->length()) && guarantee_property(valid_cp_range(catch_type_index, cp->length()) &&
(cp->tag_at(catch_type_index).is_klass() || is_klass_reference(cp, catch_type_index),
cp->tag_at(catch_type_index).is_unresolved_klass()),
"Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle)); "Catch type in exception table has bad constant type in class file %s", CHECK_(nullHandle));
} }
} }
@ -1117,7 +1232,7 @@ void ClassFileParser::parse_type_array(u2 array_length, u4 code_length, u4* u1_i
} else if (tag == ITEM_Object) { } else if (tag == ITEM_Object) {
u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK); u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
guarantee_property(valid_cp_range(class_index, cp->length()) && guarantee_property(valid_cp_range(class_index, cp->length()) &&
cp->tag_at(class_index).is_unresolved_klass(), is_klass_reference(cp, class_index),
"Bad class index %u in StackMap in class file %s", "Bad class index %u in StackMap in class file %s",
class_index, CHECK); class_index, CHECK);
} else if (tag == ITEM_Uninitialized) { } else if (tag == ITEM_Uninitialized) {
@ -1183,7 +1298,7 @@ u2* ClassFileParser::parse_checked_exceptions(u2* checked_exceptions_length,
checked_exception = cfs->get_u2_fast(); checked_exception = cfs->get_u2_fast();
check_property( check_property(
valid_cp_range(checked_exception, cp->length()) && valid_cp_range(checked_exception, cp->length()) &&
cp->tag_at(checked_exception).is_klass_reference(), is_klass_reference(cp, checked_exception),
"Exception name has bad type at constant pool %u in class file %s", "Exception name has bad type at constant pool %u in class file %s",
checked_exception, CHECK_NULL); checked_exception, CHECK_NULL);
} }
@ -1918,7 +2033,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle c
check_property( check_property(
inner_class_info_index == 0 || inner_class_info_index == 0 ||
(valid_cp_range(inner_class_info_index, cp_size) && (valid_cp_range(inner_class_info_index, cp_size) &&
cp->tag_at(inner_class_info_index).is_klass_reference()), is_klass_reference(cp, inner_class_info_index)),
"inner_class_info_index %u has bad constant type in class file %s", "inner_class_info_index %u has bad constant type in class file %s",
inner_class_info_index, CHECK_0); inner_class_info_index, CHECK_0);
// Outer class index // Outer class index
@ -1926,7 +2041,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle c
check_property( check_property(
outer_class_info_index == 0 || outer_class_info_index == 0 ||
(valid_cp_range(outer_class_info_index, cp_size) && (valid_cp_range(outer_class_info_index, cp_size) &&
cp->tag_at(outer_class_info_index).is_klass_reference()), is_klass_reference(cp, outer_class_info_index)),
"outer_class_info_index %u has bad constant type in class file %s", "outer_class_info_index %u has bad constant type in class file %s",
outer_class_info_index, CHECK_0); outer_class_info_index, CHECK_0);
// Inner class name // Inner class name
@ -2088,7 +2203,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
} }
// Validate the constant pool indices and types // Validate the constant pool indices and types
if (!cp->is_within_bounds(class_index) || if (!cp->is_within_bounds(class_index) ||
!cp->tag_at(class_index).is_klass_reference()) { !is_klass_reference(cp, class_index)) {
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK); classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
} }
if (method_index != 0 && if (method_index != 0 &&
@ -2349,6 +2464,7 @@ void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_pt
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
GrowableArray<Handle>* cp_patches,
symbolHandle& parsed_name, symbolHandle& parsed_name,
TRAPS) { TRAPS) {
// So that JVMTI can cache class file in the state before retransformable agents // So that JVMTI can cache class file in the state before retransformable agents
@ -2380,6 +2496,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
} }
} }
_cp_patches = cp_patches;
instanceKlassHandle nullHandle; instanceKlassHandle nullHandle;
@ -2510,14 +2627,22 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
CHECK_(nullHandle)); CHECK_(nullHandle));
} else { } else {
check_property(valid_cp_range(super_class_index, cp_size) && check_property(valid_cp_range(super_class_index, cp_size) &&
cp->tag_at(super_class_index).is_unresolved_klass(), is_klass_reference(cp, super_class_index),
"Invalid superclass index %u in class file %s", "Invalid superclass index %u in class file %s",
super_class_index, super_class_index,
CHECK_(nullHandle)); CHECK_(nullHandle));
// The class name should be legal because it is checked when parsing constant pool. // The class name should be legal because it is checked when parsing constant pool.
// However, make sure it is not an array type. // However, make sure it is not an array type.
bool is_array = false;
if (cp->tag_at(super_class_index).is_klass()) {
super_klass = instanceKlassHandle(THREAD, cp->resolved_klass_at(super_class_index));
if (_need_verify)
is_array = super_klass->oop_is_array();
} else if (_need_verify) {
is_array = (cp->unresolved_klass_at(super_class_index)->byte_at(0) == JVM_SIGNATURE_ARRAY);
}
if (_need_verify) { if (_need_verify) {
guarantee_property(cp->unresolved_klass_at(super_class_index)->byte_at(0) != JVM_SIGNATURE_ARRAY, guarantee_property(!is_array,
"Bad superclass name in class file %s", CHECK_(nullHandle)); "Bad superclass name in class file %s", CHECK_(nullHandle));
} }
} }
@ -2557,7 +2682,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop); objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop);
// We check super class after class file is parsed and format is checked // We check super class after class file is parsed and format is checked
if (super_class_index > 0) { if (super_class_index > 0 && super_klass.is_null()) {
symbolHandle sk (THREAD, cp->klass_name_at(super_class_index)); symbolHandle sk (THREAD, cp->klass_name_at(super_class_index));
if (access_flags.is_interface()) { if (access_flags.is_interface()) {
// Before attempting to resolve the superclass, check for class format // Before attempting to resolve the superclass, check for class format
@ -2574,6 +2699,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
CHECK_(nullHandle)); CHECK_(nullHandle));
KlassHandle kh (THREAD, k); KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh()); super_klass = instanceKlassHandle(THREAD, kh());
cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
}
if (super_klass.not_null()) {
if (super_klass->is_interface()) { if (super_klass->is_interface()) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
Exceptions::fthrow( Exceptions::fthrow(
@ -3000,6 +3128,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
this_klass->set_method_ordering(method_ordering()); this_klass->set_method_ordering(method_ordering());
this_klass->set_initial_method_idnum(methods->length()); this_klass->set_initial_method_idnum(methods->length());
this_klass->set_name(cp->klass_name_at(this_class_index)); this_klass->set_name(cp->klass_name_at(this_class_index));
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
this_klass->set_protection_domain(protection_domain()); this_klass->set_protection_domain(protection_domain());
this_klass->set_fields_annotations(fields_annotations()); this_klass->set_fields_annotations(fields_annotations());
this_klass->set_methods_annotations(methods_annotations()); this_klass->set_methods_annotations(methods_annotations());

View file

@ -33,6 +33,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
u2 _major_version; u2 _major_version;
u2 _minor_version; u2 _minor_version;
symbolHandle _class_name; symbolHandle _class_name;
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
bool _has_finalizer; bool _has_finalizer;
bool _has_empty_finalizer; bool _has_empty_finalizer;
@ -203,6 +204,35 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
char* skip_over_field_name(char* name, bool slash_ok, unsigned int length); char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS); char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
bool has_cp_patch_at(int index) {
assert(AnonymousClasses, "");
assert(index >= 0, "oob");
return (_cp_patches != NULL
&& index < _cp_patches->length()
&& _cp_patches->adr_at(index)->not_null());
}
Handle cp_patch_at(int index) {
assert(has_cp_patch_at(index), "oob");
return _cp_patches->at(index);
}
Handle clear_cp_patch_at(int index) {
Handle patch = cp_patch_at(index);
_cp_patches->at_put(index, Handle());
assert(!has_cp_patch_at(index), "");
return patch;
}
void patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS);
// Wrapper for constantTag.is_klass_[or_]reference.
// In older versions of the VM, klassOops cannot sneak into early phases of
// constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference.
bool is_klass_reference(constantPoolHandle cp, int index) {
return ((LinkWellKnownClasses || AnonymousClasses)
? cp->tag_at(index).is_klass_or_reference()
: cp->tag_at(index).is_klass_reference());
}
public: public:
// Constructor // Constructor
ClassFileParser(ClassFileStream* st) { set_stream(st); } ClassFileParser(ClassFileStream* st) { set_stream(st); }
@ -218,6 +248,14 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
symbolHandle& parsed_name, symbolHandle& parsed_name,
TRAPS) {
return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD);
}
instanceKlassHandle parseClassFile(symbolHandle name,
Handle class_loader,
Handle protection_domain,
GrowableArray<Handle>* cp_patches,
symbolHandle& parsed_name,
TRAPS); TRAPS);
// Verifier checks // Verifier checks

View file

@ -937,6 +937,8 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
ClassFileStream* st, ClassFileStream* st,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS) { TRAPS) {
symbolHandle parsed_name; symbolHandle parsed_name;
@ -953,10 +955,10 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name,
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
class_loader, class_loader,
protection_domain, protection_domain,
cp_patches,
parsed_name, parsed_name,
THREAD); THREAD);
// We don't redefine the class, so we just need to clean up whether there // We don't redefine the class, so we just need to clean up whether there
// was an error or not (don't want to modify any system dictionary // was an error or not (don't want to modify any system dictionary
// data structures). // data structures).
@ -973,6 +975,30 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name,
} }
} }
if (host_klass.not_null() && k.not_null()) {
assert(AnonymousClasses, "");
// If it's anonymous, initialize it now, since nobody else will.
k->set_host_klass(host_klass());
{
MutexLocker mu_r(Compile_lock, THREAD);
// Add to class hierarchy, initialize vtables, and do possible
// deoptimizations.
add_to_hierarchy(k, CHECK_NULL); // No exception, but can block
// But, do not add to system dictionary.
}
k->eager_initialize(THREAD);
// notify jvmti
if (JvmtiExport::should_post_class_load()) {
assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) THREAD, k());
}
}
return k(); return k();
} }

View file

@ -228,6 +228,16 @@ public:
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
ClassFileStream* st, ClassFileStream* st,
TRAPS) {
KlassHandle nullHandle;
return parse_stream(class_name, class_loader, protection_domain, st, nullHandle, NULL, THREAD);
}
static klassOop parse_stream(symbolHandle class_name,
Handle class_loader,
Handle protection_domain,
ClassFileStream* st,
KlassHandle host_klass,
GrowableArray<Handle>* cp_patches,
TRAPS); TRAPS);
// Resolve from stream (called by jni_DefineClass and JVM_DefineClass) // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)

View file

@ -1600,7 +1600,11 @@ void ClassVerifier::verify_ldc(
types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long); types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long);
verify_cp_type(index, cp, types, CHECK_VERIFY(this)); verify_cp_type(index, cp, types, CHECK_VERIFY(this));
} }
if (tag.is_string() || tag.is_unresolved_string()) { if (tag.is_string() && cp->is_pseudo_string_at(index)) {
current_frame->push_stack(
VerificationType::reference_type(
vmSymbols::java_lang_Object()), CHECK_VERIFY(this));
} else if (tag.is_string() || tag.is_unresolved_string()) {
current_frame->push_stack( current_frame->push_stack(
VerificationType::reference_type( VerificationType::reference_type(
vmSymbols::java_lang_String()), CHECK_VERIFY(this)); vmSymbols::java_lang_String()), CHECK_VERIFY(this));

View file

@ -1,314 +0,0 @@
/*
* Copyright 2001-2005 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.
*
*/
// CopyrightVersion 1.2
# include "incls/_precompiled.incl"
# include "incls/_concurrentGCThread.cpp.incl"
bool ConcurrentGCThread::_should_terminate = false;
bool ConcurrentGCThread::_has_terminated = false;
int ConcurrentGCThread::_CGC_flag = CGC_nil;
SuspendibleThreadSet ConcurrentGCThread::_sts;
ConcurrentGCThread::ConcurrentGCThread() {
_sts.initialize();
};
void ConcurrentGCThread::stopWorldAndDo(VoidClosure* op) {
MutexLockerEx x(Heap_lock,
Mutex::_no_safepoint_check_flag);
// warning("CGC: about to try stopping world");
SafepointSynchronize::begin();
// warning("CGC: successfully stopped world");
op->do_void();
SafepointSynchronize::end();
// warning("CGC: successfully restarted world");
}
void ConcurrentGCThread::safepoint_synchronize() {
_sts.suspend_all();
}
void ConcurrentGCThread::safepoint_desynchronize() {
_sts.resume_all();
}
void ConcurrentGCThread::create_and_start() {
if (os::create_thread(this, os::cgc_thread)) {
// XXX: need to set this to low priority
// unless "agressive mode" set; priority
// should be just less than that of VMThread.
os::set_priority(this, NearMaxPriority);
if (!_should_terminate && !DisableStartThread) {
os::start_thread(this);
}
}
}
void ConcurrentGCThread::initialize_in_thread() {
this->record_stack_base_and_size();
this->initialize_thread_local_storage();
this->set_active_handles(JNIHandleBlock::allocate_block());
// From this time Thread::current() should be working.
assert(this == Thread::current(), "just checking");
}
void ConcurrentGCThread::wait_for_universe_init() {
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
while (!is_init_completed() && !_should_terminate) {
CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
}
}
void ConcurrentGCThread::terminate() {
// Signal that it is terminated
{
MutexLockerEx mu(Terminator_lock,
Mutex::_no_safepoint_check_flag);
_has_terminated = true;
Terminator_lock->notify();
}
// Thread destructor usually does this..
ThreadLocalStorage::set_thread(NULL);
}
void SuspendibleThreadSet::initialize_work() {
MutexLocker x(STS_init_lock);
if (!_initialized) {
_m = new Monitor(Mutex::leaf,
"SuspendibleThreadSetLock", true);
_async = 0;
_async_stop = false;
_async_stopped = 0;
_initialized = true;
}
}
void SuspendibleThreadSet::join() {
initialize();
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
_async++;
assert(_async > 0, "Huh.");
}
void SuspendibleThreadSet::leave() {
assert(_initialized, "Must be initialized.");
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
_async--;
assert(_async >= 0, "Huh.");
if (_async_stop) _m->notify_all();
}
void SuspendibleThreadSet::yield(const char* id) {
assert(_initialized, "Must be initialized.");
if (_async_stop) {
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
if (_async_stop) {
_async_stopped++;
assert(_async_stopped > 0, "Huh.");
if (_async_stopped == _async) {
if (ConcGCYieldTimeout > 0) {
double now = os::elapsedTime();
guarantee((now - _suspend_all_start) * 1000.0 <
(double)ConcGCYieldTimeout,
"Long delay; whodunit?");
}
}
_m->notify_all();
while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
_async_stopped--;
assert(_async >= 0, "Huh");
_m->notify_all();
}
}
}
void SuspendibleThreadSet::suspend_all() {
initialize(); // If necessary.
if (ConcGCYieldTimeout > 0) {
_suspend_all_start = os::elapsedTime();
}
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
assert(!_async_stop, "Only one at a time.");
_async_stop = true;
while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
}
void SuspendibleThreadSet::resume_all() {
assert(_initialized, "Must be initialized.");
MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
assert(_async_stopped == _async, "Huh.");
_async_stop = false;
_m->notify_all();
}
static void _sltLoop(JavaThread* thread, TRAPS) {
SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
slt->loop();
}
SurrogateLockerThread::SurrogateLockerThread() :
JavaThread(&_sltLoop),
_monitor(Mutex::nonleaf, "SLTMonitor"),
_buffer(empty)
{}
SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
klassOop k =
SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(),
true, CHECK_NULL);
instanceKlassHandle klass (THREAD, k);
instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);
const char thread_name[] = "Surrogate Locker Thread (CMS)";
Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);
// Initialize thread_oop to put it into the system threadGroup
Handle thread_group (THREAD, Universe::system_thread_group());
JavaValue result(T_VOID);
JavaCalls::call_special(&result, thread_oop,
klass,
vmSymbolHandles::object_initializer_name(),
vmSymbolHandles::threadgroup_string_void_signature(),
thread_group,
string,
CHECK_NULL);
SurrogateLockerThread* res;
{
MutexLocker mu(Threads_lock);
res = new SurrogateLockerThread();
// At this point it may be possible that no osthread was created for the
// JavaThread due to lack of memory. We would have to throw an exception
// in that case. However, since this must work and we do not allow
// exceptions anyway, check and abort if this fails.
if (res == NULL || res->osthread() == NULL) {
vm_exit_during_initialization("java.lang.OutOfMemoryError",
"unable to create new native thread");
}
java_lang_Thread::set_thread(thread_oop(), res);
java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
java_lang_Thread::set_daemon(thread_oop());
res->set_threadObj(thread_oop());
Threads::add(res);
Thread::start(res);
}
os::yield(); // This seems to help with initial start-up of SLT
return res;
}
void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) {
MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag);
assert(_buffer == empty, "Should be empty");
assert(msg != empty, "empty message");
_buffer = msg;
while (_buffer != empty) {
_monitor.notify();
_monitor.wait(Mutex::_no_safepoint_check_flag);
}
}
// ======= Surrogate Locker Thread =============
void SurrogateLockerThread::loop() {
BasicLock pll_basic_lock;
SLT_msg_type msg;
debug_only(unsigned int owned = 0;)
while (/* !isTerminated() */ 1) {
{
MutexLocker x(&_monitor);
// Since we are a JavaThread, we can't be here at a safepoint.
assert(!SafepointSynchronize::is_at_safepoint(),
"SLT is a JavaThread");
// wait for msg buffer to become non-empty
while (_buffer == empty) {
_monitor.notify();
_monitor.wait();
}
msg = _buffer;
}
switch(msg) {
case acquirePLL: {
instanceRefKlass::acquire_pending_list_lock(&pll_basic_lock);
debug_only(owned++;)
break;
}
case releaseAndNotifyPLL: {
assert(owned > 0, "Don't have PLL");
instanceRefKlass::release_and_notify_pending_list_lock(&pll_basic_lock);
debug_only(owned--;)
break;
}
case empty:
default: {
guarantee(false,"Unexpected message in _buffer");
break;
}
}
{
MutexLocker x(&_monitor);
// Since we are a JavaThread, we can't be here at a safepoint.
assert(!SafepointSynchronize::is_at_safepoint(),
"SLT is a JavaThread");
_buffer = empty;
_monitor.notify();
}
}
assert(!_monitor.owned_by_self(), "Should unlock before exit.");
}
// ===== STS Access From Outside CGCT =====
void ConcurrentGCThread::stsYield(const char* id) {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.yield(id);
}
bool ConcurrentGCThread::stsShouldYield() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
return _sts.should_yield();
}
void ConcurrentGCThread::stsJoin() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.join();
}
void ConcurrentGCThread::stsLeave() {
assert( Thread::current()->is_ConcurrentGC_thread(),
"only a conc GC thread can call this" );
_sts.leave();
}

View file

@ -1,167 +0,0 @@
/*
* Copyright 2001-2005 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.
*
*/
class VoidClosure;
// A SuspendibleThreadSet is (obviously) a set of threads that can be
// suspended. A thread can join and later leave the set, and periodically
// yield. If some thread (not in the set) requests, via suspend_all, that
// the threads be suspended, then the requesting thread is blocked until
// all the threads in the set have yielded or left the set. (Threads may
// not enter the set when an attempted suspension is in progress.) The
// suspending thread later calls resume_all, allowing the suspended threads
// to continue.
class SuspendibleThreadSet {
Monitor* _m;
int _async;
bool _async_stop;
int _async_stopped;
bool _initialized;
double _suspend_all_start;
void initialize_work();
public:
SuspendibleThreadSet() : _initialized(false) {}
// Add the current thread to the set. May block if a suspension
// is in progress.
void join();
// Removes the current thread from the set.
void leave();
// Returns "true" iff an suspension is in progress.
bool should_yield() { return _async_stop; }
// Suspends the current thread if a suspension is in progress (for
// the duration of the suspension.)
void yield(const char* id);
// Return when all threads in the set are suspended.
void suspend_all();
// Allow suspended threads to resume.
void resume_all();
// Redundant initializations okay.
void initialize() {
// Double-check dirty read idiom.
if (!_initialized) initialize_work();
}
};
class ConcurrentGCThread: public NamedThread {
friend class VMStructs;
protected:
static bool _should_terminate;
static bool _has_terminated;
enum CGC_flag_type {
CGC_nil = 0x0,
CGC_dont_suspend = 0x1,
CGC_CGC_safepoint = 0x2,
CGC_VM_safepoint = 0x4
};
static int _CGC_flag;
static bool CGC_flag_is_set(int b) { return (_CGC_flag & b) != 0; }
static int set_CGC_flag(int b) { return _CGC_flag |= b; }
static int reset_CGC_flag(int b) { return _CGC_flag &= ~b; }
void stopWorldAndDo(VoidClosure* op);
// All instances share this one set.
static SuspendibleThreadSet _sts;
// Create and start the thread (setting it's priority high.)
void create_and_start();
// Do initialization steps in the thread: record stack base and size,
// init thread local storage, set JNI handle block.
void initialize_in_thread();
// Wait until Universe::is_fully_initialized();
void wait_for_universe_init();
// Record that the current thread is terminating, and will do more
// concurrent work.
void terminate();
public:
// Constructor
ConcurrentGCThread();
~ConcurrentGCThread() {} // Exists to call NamedThread destructor.
// Tester
bool is_ConcurrentGC_thread() const { return true; }
static void safepoint_synchronize();
static void safepoint_desynchronize();
// All overridings should probably do _sts::yield, but we allow
// overriding for distinguished debugging messages. Default is to do
// nothing.
virtual void yield() {}
bool should_yield() { return _sts.should_yield(); }
// they are prefixed by sts since there are already yield() and
// should_yield() (non-static) methods in this class and it was an
// easy way to differentiate them.
static void stsYield(const char* id);
static bool stsShouldYield();
static void stsJoin();
static void stsLeave();
};
// The SurrogateLockerThread is used by concurrent GC threads for
// manipulating Java monitors, in particular, currently for
// manipulating the pending_list_lock. XXX
class SurrogateLockerThread: public JavaThread {
friend class VMStructs;
public:
enum SLT_msg_type {
empty = 0, // no message
acquirePLL, // acquire pending list lock
releaseAndNotifyPLL // notify and release pending list lock
};
private:
// the following are shared with the CMSThread
SLT_msg_type _buffer; // communication buffer
Monitor _monitor; // monitor controlling buffer
BasicLock _basicLock; // used for PLL locking
public:
static SurrogateLockerThread* make(TRAPS);
SurrogateLockerThread();
bool is_hidden_from_external_view() const { return true; }
void loop(); // main method
void manipulatePLL(SLT_msg_type msg);
};

View file

@ -30,7 +30,7 @@ PtrQueue::PtrQueue(PtrQueueSet* qset_, bool perm) :
_perm(perm), _lock(NULL) _perm(perm), _lock(NULL)
{} {}
PtrQueue::~PtrQueue() { void PtrQueue::flush() {
if (!_perm && _buf != NULL) { if (!_perm && _buf != NULL) {
if (_index == _sz) { if (_index == _sz) {
// No work to do. // No work to do.
@ -41,8 +41,9 @@ PtrQueue::~PtrQueue() {
_buf[byte_index_to_index((int)i)] = NULL; _buf[byte_index_to_index((int)i)] = NULL;
} }
qset()->enqueue_complete_buffer(_buf); qset()->enqueue_complete_buffer(_buf);
_buf = NULL;
} }
_buf = NULL;
_index = 0;
} }
} }

View file

@ -62,7 +62,9 @@ public:
// given PtrQueueSet. // given PtrQueueSet.
PtrQueue(PtrQueueSet*, bool perm = false); PtrQueue(PtrQueueSet*, bool perm = false);
// Release any contained resources. // Release any contained resources.
~PtrQueue(); void flush();
// Calls flush() when destroyed.
~PtrQueue() { flush(); }
// Associate a lock with a ptr queue. // Associate a lock with a ptr queue.
void set_lock(Mutex* lock) { _lock = lock; } void set_lock(Mutex* lock) { _lock = lock; }

View file

@ -90,10 +90,10 @@ void PSMarkSweepDecorator::precompact() {
*/ */
bool skip_dead = ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0); bool skip_dead = ((PSMarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0);
ssize_t allowed_deadspace = 0; size_t allowed_deadspace = 0;
if (skip_dead) { if (skip_dead) {
int ratio = allowed_dead_ratio(); const size_t ratio = allowed_dead_ratio();
allowed_deadspace = (space()->capacity_in_bytes() * ratio / 100) / HeapWordSize; allowed_deadspace = space()->capacity_in_words() * ratio / 100;
} }
// Fetch the current destination decorator // Fetch the current destination decorator
@ -271,10 +271,10 @@ void PSMarkSweepDecorator::precompact() {
dest->set_compaction_top(compact_top); dest->set_compaction_top(compact_top);
} }
bool PSMarkSweepDecorator::insert_deadspace(ssize_t& allowed_deadspace_words, bool PSMarkSweepDecorator::insert_deadspace(size_t& allowed_deadspace_words,
HeapWord* q, size_t deadlength) { HeapWord* q, size_t deadlength) {
allowed_deadspace_words -= deadlength; if (allowed_deadspace_words >= deadlength) {
if (allowed_deadspace_words >= 0) { allowed_deadspace_words -= deadlength;
oop(q)->set_mark(markOopDesc::prototype()->set_marked()); oop(q)->set_mark(markOopDesc::prototype()->set_marked());
const size_t aligned_min_int_array_size = const size_t aligned_min_int_array_size =
align_object_size(typeArrayOopDesc::header_size(T_INT)); align_object_size(typeArrayOopDesc::header_size(T_INT));

View file

@ -39,14 +39,16 @@ class PSMarkSweepDecorator: public CHeapObj {
HeapWord* _first_dead; HeapWord* _first_dead;
HeapWord* _end_of_live; HeapWord* _end_of_live;
HeapWord* _compaction_top; HeapWord* _compaction_top;
unsigned int _allowed_dead_ratio; size_t _allowed_dead_ratio;
bool insert_deadspace(ssize_t& allowed_deadspace_words, HeapWord* q, size_t word_len); bool insert_deadspace(size_t& allowed_deadspace_words, HeapWord* q,
size_t word_len);
public: public:
PSMarkSweepDecorator(MutableSpace* space, ObjectStartArray* start_array, PSMarkSweepDecorator(MutableSpace* space, ObjectStartArray* start_array,
unsigned int allowed_dead_ratio) : size_t allowed_dead_ratio) :
_space(space), _start_array(start_array), _allowed_dead_ratio(allowed_dead_ratio) { } _space(space), _start_array(start_array),
_allowed_dead_ratio(allowed_dead_ratio) { }
// During a compacting collection, we need to collapse objects into // During a compacting collection, we need to collapse objects into
// spaces in a given order. We want to fill space A, space B, and so // spaces in a given order. We want to fill space A, space B, and so
@ -57,14 +59,14 @@ class PSMarkSweepDecorator: public CHeapObj {
static PSMarkSweepDecorator* destination_decorator(); static PSMarkSweepDecorator* destination_decorator();
// Accessors // Accessors
MutableSpace* space() { return _space; } MutableSpace* space() { return _space; }
ObjectStartArray* start_array() { return _start_array; } ObjectStartArray* start_array() { return _start_array; }
HeapWord* compaction_top() { return _compaction_top; } HeapWord* compaction_top() { return _compaction_top; }
void set_compaction_top(HeapWord* value) { _compaction_top = value; } void set_compaction_top(HeapWord* value) { _compaction_top = value; }
unsigned int allowed_dead_ratio() { return _allowed_dead_ratio; } size_t allowed_dead_ratio() { return _allowed_dead_ratio; }
void set_allowed_dead_ratio(unsigned int value) { _allowed_dead_ratio = value; } void set_allowed_dead_ratio(size_t value) { _allowed_dead_ratio = value; }
// Work methods // Work methods
void adjust_pointers(); void adjust_pointers();

View file

@ -30,6 +30,12 @@ collectorPolicy.cpp cmsGCAdaptivePolicyCounters.hpp
compiledICHolderKlass.cpp oop.pcgc.inline.hpp compiledICHolderKlass.cpp oop.pcgc.inline.hpp
constantPoolKlass.cpp cardTableRS.hpp
constantPoolKlass.cpp oop.pcgc.inline.hpp
constantPoolKlass.cpp psPromotionManager.inline.hpp
constantPoolKlass.cpp psScavenge.inline.hpp
constantPoolKlass.cpp parOopClosures.inline.hpp
genCollectedHeap.cpp concurrentMarkSweepThread.hpp genCollectedHeap.cpp concurrentMarkSweepThread.hpp
genCollectedHeap.cpp vmCMSOperations.hpp genCollectedHeap.cpp vmCMSOperations.hpp

View file

@ -997,11 +997,11 @@ void OffsetTableContigSpace::serialize_block_offset_array_offsets(
} }
int TenuredSpace::allowed_dead_ratio() const { size_t TenuredSpace::allowed_dead_ratio() const {
return MarkSweepDeadRatio; return MarkSweepDeadRatio;
} }
int ContigPermSpace::allowed_dead_ratio() const { size_t ContigPermSpace::allowed_dead_ratio() const {
return PermMarkSweepDeadRatio; return PermMarkSweepDeadRatio;
} }

View file

@ -421,7 +421,7 @@ public:
// The maximum percentage of objects that can be dead in the compacted // The maximum percentage of objects that can be dead in the compacted
// live part of a compacted space ("deadwood" support.) // live part of a compacted space ("deadwood" support.)
virtual int allowed_dead_ratio() const { return 0; }; virtual size_t allowed_dead_ratio() const { return 0; };
// Some contiguous spaces may maintain some data structures that should // Some contiguous spaces may maintain some data structures that should
// be updated whenever an allocation crosses a boundary. This function // be updated whenever an allocation crosses a boundary. This function
@ -507,7 +507,7 @@ protected:
\ \
size_t allowed_deadspace = 0; \ size_t allowed_deadspace = 0; \
if (skip_dead) { \ if (skip_dead) { \
int ratio = allowed_dead_ratio(); \ const size_t ratio = allowed_dead_ratio(); \
allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize; \ allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize; \
} \ } \
\ \
@ -1079,7 +1079,7 @@ class TenuredSpace: public OffsetTableContigSpace {
friend class VMStructs; friend class VMStructs;
protected: protected:
// Mark sweep support // Mark sweep support
int allowed_dead_ratio() const; size_t allowed_dead_ratio() const;
public: public:
// Constructor // Constructor
TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray,
@ -1094,7 +1094,7 @@ class ContigPermSpace: public OffsetTableContigSpace {
friend class VMStructs; friend class VMStructs;
protected: protected:
// Mark sweep support // Mark sweep support
int allowed_dead_ratio() const; size_t allowed_dead_ratio() const;
public: public:
// Constructor // Constructor
ContigPermSpace(BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) : ContigPermSpace(BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) :

View file

@ -73,7 +73,6 @@ class TenuredGeneration: public OneContigSpaceCardGeneration {
// Mark sweep support // Mark sweep support
void compute_new_size(); void compute_new_size();
int allowed_dead_ratio() const;
virtual void gc_prologue(bool full); virtual void gc_prologue(bool full);
virtual void gc_epilogue(bool full); virtual void gc_epilogue(bool full);

View file

@ -35,6 +35,7 @@ constantPoolOop constantPoolKlass::allocate(int length, TRAPS) {
c->set_tags(NULL); c->set_tags(NULL);
c->set_cache(NULL); c->set_cache(NULL);
c->set_pool_holder(NULL); c->set_pool_holder(NULL);
c->set_flags(0);
// only set to non-zero if constant pool is merged by RedefineClasses // only set to non-zero if constant pool is merged by RedefineClasses
c->set_orig_length(0); c->set_orig_length(0);
// all fields are initialized; needed for GC // all fields are initialized; needed for GC
@ -261,10 +262,32 @@ constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj,
void constantPoolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { void constantPoolKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
assert(obj->is_constantPool(), "should be constant pool"); assert(obj->is_constantPool(), "should be constant pool");
constantPoolOop cp = (constantPoolOop) obj;
if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
oop* base = (oop*)cp->base();
for (int i = 0; i < cp->length(); ++i, ++base) {
if (cp->tag_at(i).is_string()) {
if (PSScavenge::should_scavenge(base)) {
pm->claim_or_forward_breadth(base);
}
}
}
}
} }
void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
assert(obj->is_constantPool(), "should be constant pool"); assert(obj->is_constantPool(), "should be constant pool");
constantPoolOop cp = (constantPoolOop) obj;
if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
oop* base = (oop*)cp->base();
for (int i = 0; i < cp->length(); ++i, ++base) {
if (cp->tag_at(i).is_string()) {
if (PSScavenge::should_scavenge(base)) {
pm->claim_or_forward_depth(base);
}
}
}
}
} }
#endif // SERIALGC #endif // SERIALGC
@ -278,6 +301,11 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
assert(obj->is_constantPool(), "must be constantPool"); assert(obj->is_constantPool(), "must be constantPool");
Klass::oop_print_on(obj, st); Klass::oop_print_on(obj, st);
constantPoolOop cp = constantPoolOop(obj); constantPoolOop cp = constantPoolOop(obj);
if (cp->flags() != 0) {
st->print(" - flags : 0x%x", cp->flags());
if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
st->cr();
}
// Temp. remove cache so we can do lookups with original indicies. // Temp. remove cache so we can do lookups with original indicies.
constantPoolCacheHandle cache (THREAD, cp->cache()); constantPoolCacheHandle cache (THREAD, cp->cache());
@ -302,7 +330,11 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
break; break;
case JVM_CONSTANT_UnresolvedString : case JVM_CONSTANT_UnresolvedString :
case JVM_CONSTANT_String : case JVM_CONSTANT_String :
anObj = cp->string_at(index, CATCH); if (cp->is_pseudo_string_at(index)) {
anObj = cp->pseudo_string_at(index);
} else {
anObj = cp->string_at(index, CATCH);
}
anObj->print_value_on(st); anObj->print_value_on(st);
st->print(" {0x%lx}", (address)anObj); st->print(" {0x%lx}", (address)anObj);
break; break;
@ -382,8 +414,12 @@ void constantPoolKlass::oop_verify_on(oop obj, outputStream* st) {
"should be symbol or instance"); "should be symbol or instance");
} }
if (cp->tag_at(i).is_string()) { if (cp->tag_at(i).is_string()) {
guarantee((*base)->is_perm(), "should be in permspace"); if (!cp->has_pseudo_string()) {
guarantee((*base)->is_instance(), "should be instance"); guarantee((*base)->is_perm(), "should be in permspace");
guarantee((*base)->is_instance(), "should be instance");
} else {
// can be non-perm, can be non-instance (array)
}
} }
base++; base++;
} }

View file

@ -25,6 +25,18 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_constantPoolOop.cpp.incl" # include "incls/_constantPoolOop.cpp.incl"
void constantPoolOopDesc::set_flag_at(FlagBit fb) {
const int MAX_STATE_CHANGES = 2;
for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
int oflags = _flags;
int nflags = oflags | (1 << (int)fb);
if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags)
return;
}
assert(false, "failed to cmpxchg flags");
_flags |= (1 << (int)fb); // better than nothing
}
klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) { klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
// A resolved constantPool entry will contain a klassOop, otherwise a symbolOop. // A resolved constantPool entry will contain a klassOop, otherwise a symbolOop.
// It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and // It is not safe to rely on the tag bit's here, since we don't have a lock, and the entry and
@ -333,8 +345,10 @@ char* constantPoolOopDesc::string_at_noresolve(int which) {
oop entry = *(obj_at_addr(which)); oop entry = *(obj_at_addr(which));
if (entry->is_symbol()) { if (entry->is_symbol()) {
return ((symbolOop)entry)->as_C_string(); return ((symbolOop)entry)->as_C_string();
} else { } else if (java_lang_String::is_instance(entry)) {
return java_lang_String::as_utf8_string(entry); return java_lang_String::as_utf8_string(entry);
} else {
return (char*)"<pseudo-string>";
} }
} }
@ -385,6 +399,19 @@ oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which,
} }
bool constantPoolOopDesc::is_pseudo_string_at(int which) {
oop entry = *(obj_at_addr(which));
if (entry->is_symbol())
// Not yet resolved, but it will resolve to a string.
return false;
else if (java_lang_String::is_instance(entry))
return false; // actually, it might be a non-interned or non-perm string
else
// truly pseudo
return true;
}
bool constantPoolOopDesc::klass_name_at_matches(instanceKlassHandle k, bool constantPoolOopDesc::klass_name_at_matches(instanceKlassHandle k,
int which) { int which) {
// Names are interned, so we can compare symbolOops directly // Names are interned, so we can compare symbolOops directly

View file

@ -41,6 +41,7 @@ class constantPoolOopDesc : public oopDesc {
typeArrayOop _tags; // the tag array describing the constant pool's contents typeArrayOop _tags; // the tag array describing the constant pool's contents
constantPoolCacheOop _cache; // the cache holding interpreter runtime information constantPoolCacheOop _cache; // the cache holding interpreter runtime information
klassOop _pool_holder; // the corresponding class klassOop _pool_holder; // the corresponding class
int _flags; // a few header bits to describe contents for GC
int _length; // number of elements in the array int _length; // number of elements in the array
// only set to non-zero if constant pool is merged by RedefineClasses // only set to non-zero if constant pool is merged by RedefineClasses
int _orig_length; int _orig_length;
@ -49,6 +50,16 @@ class constantPoolOopDesc : public oopDesc {
void tag_at_put(int which, jbyte t) { tags()->byte_at_put(which, t); } void tag_at_put(int which, jbyte t) { tags()->byte_at_put(which, t); }
void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); } void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
enum FlagBit {
FB_has_pseudo_string = 2
};
int flags() const { return _flags; }
void set_flags(int f) { _flags = f; }
bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; }
void set_flag_at(FlagBit fb);
// no clear_flag_at function; they only increase
private: private:
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); } intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); }
oop* tags_addr() { return (oop*)&_tags; } oop* tags_addr() { return (oop*)&_tags; }
@ -82,6 +93,9 @@ class constantPoolOopDesc : public oopDesc {
public: public:
typeArrayOop tags() const { return _tags; } typeArrayOop tags() const { return _tags; }
bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); }
// Klass holding pool // Klass holding pool
klassOop pool_holder() const { return _pool_holder; } klassOop pool_holder() const { return _pool_holder; }
void set_pool_holder(klassOop k) { oop_store_without_check((oop*)&_pool_holder, (oop) k); } void set_pool_holder(klassOop k) { oop_store_without_check((oop*)&_pool_holder, (oop) k); }
@ -272,6 +286,27 @@ class constantPoolOopDesc : public oopDesc {
return string_at_impl(h_this, which, CHECK_NULL); return string_at_impl(h_this, which, CHECK_NULL);
} }
// A "pseudo-string" is an non-string oop that has found is way into
// a String entry.
// Under AnonymousClasses this can happen if the user patches a live
// object into a CONSTANT_String entry of an anonymous class.
// Method oops internally created for method handles may also
// use pseudo-strings to link themselves to related metaobjects.
bool is_pseudo_string_at(int which);
oop pseudo_string_at(int which) {
assert(tag_at(which).is_string(), "Corrupted constant pool");
return *obj_at_addr(which);
}
void pseudo_string_at_put(int which, oop x) {
assert(AnonymousClasses, "");
set_pseudo_string(); // mark header
assert(tag_at(which).is_string() || tag_at(which).is_unresolved_string(), "Corrupted constant pool");
string_at_put(which, x); // this works just fine
}
// only called when we are sure a string entry is already resolved (via an // only called when we are sure a string entry is already resolved (via an
// earlier string_at call. // earlier string_at call.
oop resolved_string_at(int which) { oop resolved_string_at(int which) {
@ -293,6 +328,7 @@ class constantPoolOopDesc : public oopDesc {
// UTF8 char* representation was chosen to avoid conversion of // UTF8 char* representation was chosen to avoid conversion of
// java_lang_Strings at resolved entries into symbolOops // java_lang_Strings at resolved entries into symbolOops
// or vice versa. // or vice versa.
// Caller is responsible for checking for pseudo-strings.
char* string_at_noresolve(int which); char* string_at_noresolve(int which);
jint name_and_type_at(int which) { jint name_and_type_at(int which) {

View file

@ -147,6 +147,10 @@ class instanceKlass: public Klass {
oop _class_loader; oop _class_loader;
// Protection domain. // Protection domain.
oop _protection_domain; oop _protection_domain;
// Host class, which grants its access privileges to this class also.
// This is only non-null for an anonymous class (AnonymousClasses enabled).
// The host class is either named, or a previously loaded anonymous class.
klassOop _host_klass;
// Class signers. // Class signers.
objArrayOop _signers; objArrayOop _signers;
// Name of source file containing this klass, NULL if not specified. // Name of source file containing this klass, NULL if not specified.
@ -375,6 +379,11 @@ class instanceKlass: public Klass {
oop protection_domain() { return _protection_domain; } oop protection_domain() { return _protection_domain; }
void set_protection_domain(oop pd) { oop_store((oop*) &_protection_domain, pd); } void set_protection_domain(oop pd) { oop_store((oop*) &_protection_domain, pd); }
// host class
oop host_klass() const { return _host_klass; }
void set_host_klass(oop host) { oop_store((oop*) &_host_klass, host); }
bool is_anonymous() const { return _host_klass != NULL; }
// signers // signers
objArrayOop signers() const { return _signers; } objArrayOop signers() const { return _signers; }
void set_signers(objArrayOop s) { oop_store((oop*) &_signers, oop(s)); } void set_signers(objArrayOop s) { oop_store((oop*) &_signers, oop(s)); }
@ -709,6 +718,7 @@ private:
oop* adr_constants() const { return (oop*)&this->_constants;} oop* adr_constants() const { return (oop*)&this->_constants;}
oop* adr_class_loader() const { return (oop*)&this->_class_loader;} oop* adr_class_loader() const { return (oop*)&this->_class_loader;}
oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;} oop* adr_protection_domain() const { return (oop*)&this->_protection_domain;}
oop* adr_host_klass() const { return (oop*)&this->_host_klass;}
oop* adr_signers() const { return (oop*)&this->_signers;} oop* adr_signers() const { return (oop*)&this->_signers;}
oop* adr_source_file_name() const { return (oop*)&this->_source_file_name;} oop* adr_source_file_name() const { return (oop*)&this->_source_file_name;}
oop* adr_source_debug_extension() const { return (oop*)&this->_source_debug_extension;} oop* adr_source_debug_extension() const { return (oop*)&this->_source_debug_extension;}

View file

@ -81,6 +81,7 @@ void instanceKlassKlass::oop_follow_contents(oop obj) {
MarkSweep::mark_and_push(ik->adr_source_debug_extension()); MarkSweep::mark_and_push(ik->adr_source_debug_extension());
MarkSweep::mark_and_push(ik->adr_inner_classes()); MarkSweep::mark_and_push(ik->adr_inner_classes());
MarkSweep::mark_and_push(ik->adr_protection_domain()); MarkSweep::mark_and_push(ik->adr_protection_domain());
MarkSweep::mark_and_push(ik->adr_host_klass());
MarkSweep::mark_and_push(ik->adr_signers()); MarkSweep::mark_and_push(ik->adr_signers());
MarkSweep::mark_and_push(ik->adr_generic_signature()); MarkSweep::mark_and_push(ik->adr_generic_signature());
MarkSweep::mark_and_push(ik->adr_class_annotations()); MarkSweep::mark_and_push(ik->adr_class_annotations());
@ -120,6 +121,7 @@ void instanceKlassKlass::oop_follow_contents(ParCompactionManager* cm,
PSParallelCompact::mark_and_push(cm, ik->adr_source_debug_extension()); PSParallelCompact::mark_and_push(cm, ik->adr_source_debug_extension());
PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes()); PSParallelCompact::mark_and_push(cm, ik->adr_inner_classes());
PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain()); PSParallelCompact::mark_and_push(cm, ik->adr_protection_domain());
PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
PSParallelCompact::mark_and_push(cm, ik->adr_signers()); PSParallelCompact::mark_and_push(cm, ik->adr_signers());
PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature()); PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature());
PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations()); PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
@ -159,6 +161,7 @@ int instanceKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
blk->do_oop(ik->adr_constants()); blk->do_oop(ik->adr_constants());
blk->do_oop(ik->adr_class_loader()); blk->do_oop(ik->adr_class_loader());
blk->do_oop(ik->adr_protection_domain()); blk->do_oop(ik->adr_protection_domain());
blk->do_oop(ik->adr_host_klass());
blk->do_oop(ik->adr_signers()); blk->do_oop(ik->adr_signers());
blk->do_oop(ik->adr_source_file_name()); blk->do_oop(ik->adr_source_file_name());
blk->do_oop(ik->adr_source_debug_extension()); blk->do_oop(ik->adr_source_debug_extension());
@ -211,6 +214,8 @@ int instanceKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk,
if (mr.contains(adr)) blk->do_oop(adr); if (mr.contains(adr)) blk->do_oop(adr);
adr = ik->adr_protection_domain(); adr = ik->adr_protection_domain();
if (mr.contains(adr)) blk->do_oop(adr); if (mr.contains(adr)) blk->do_oop(adr);
adr = ik->adr_host_klass();
if (mr.contains(adr)) blk->do_oop(adr);
adr = ik->adr_signers(); adr = ik->adr_signers();
if (mr.contains(adr)) blk->do_oop(adr); if (mr.contains(adr)) blk->do_oop(adr);
adr = ik->adr_source_file_name(); adr = ik->adr_source_file_name();
@ -260,6 +265,7 @@ int instanceKlassKlass::oop_adjust_pointers(oop obj) {
MarkSweep::adjust_pointer(ik->adr_constants()); MarkSweep::adjust_pointer(ik->adr_constants());
MarkSweep::adjust_pointer(ik->adr_class_loader()); MarkSweep::adjust_pointer(ik->adr_class_loader());
MarkSweep::adjust_pointer(ik->adr_protection_domain()); MarkSweep::adjust_pointer(ik->adr_protection_domain());
MarkSweep::adjust_pointer(ik->adr_host_klass());
MarkSweep::adjust_pointer(ik->adr_signers()); MarkSweep::adjust_pointer(ik->adr_signers());
MarkSweep::adjust_pointer(ik->adr_source_file_name()); MarkSweep::adjust_pointer(ik->adr_source_file_name());
MarkSweep::adjust_pointer(ik->adr_source_debug_extension()); MarkSweep::adjust_pointer(ik->adr_source_debug_extension());
@ -295,6 +301,11 @@ void instanceKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) {
pm->claim_or_forward_breadth(pd_addr); pm->claim_or_forward_breadth(pd_addr);
} }
oop* hk_addr = ik->adr_host_klass();
if (PSScavenge::should_scavenge(hk_addr)) {
pm->claim_or_forward_breadth(hk_addr);
}
oop* sg_addr = ik->adr_signers(); oop* sg_addr = ik->adr_signers();
if (PSScavenge::should_scavenge(sg_addr)) { if (PSScavenge::should_scavenge(sg_addr)) {
pm->claim_or_forward_breadth(sg_addr); pm->claim_or_forward_breadth(sg_addr);
@ -318,6 +329,11 @@ void instanceKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
pm->claim_or_forward_depth(pd_addr); pm->claim_or_forward_depth(pd_addr);
} }
oop* hk_addr = ik->adr_host_klass();
if (PSScavenge::should_scavenge(hk_addr)) {
pm->claim_or_forward_depth(hk_addr);
}
oop* sg_addr = ik->adr_signers(); oop* sg_addr = ik->adr_signers();
if (PSScavenge::should_scavenge(sg_addr)) { if (PSScavenge::should_scavenge(sg_addr)) {
pm->claim_or_forward_depth(sg_addr); pm->claim_or_forward_depth(sg_addr);
@ -421,6 +437,7 @@ klassOop instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_
ik->set_constants(NULL); ik->set_constants(NULL);
ik->set_class_loader(NULL); ik->set_class_loader(NULL);
ik->set_protection_domain(NULL); ik->set_protection_domain(NULL);
ik->set_host_klass(NULL);
ik->set_signers(NULL); ik->set_signers(NULL);
ik->set_source_file_name(NULL); ik->set_source_file_name(NULL);
ik->set_source_debug_extension(NULL); ik->set_source_debug_extension(NULL);
@ -526,6 +543,7 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) {
st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr(); st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr();
st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr(); st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr();
st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr(); st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
st->print(" - host class: "); ik->host_klass()->print_value_on(st); st->cr();
st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr(); st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr();
if (ik->source_file_name() != NULL) { if (ik->source_file_name() != NULL) {
st->print(" - source file: "); st->print(" - source file: ");
@ -626,7 +644,7 @@ void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) {
ik->_verify_count = Universe::verify_count(); ik->_verify_count = Universe::verify_count();
#endif #endif
// Verify that klass is present in SystemDictionary // Verify that klass is present in SystemDictionary
if (ik->is_loaded()) { if (ik->is_loaded() && !ik->is_anonymous()) {
symbolHandle h_name (thread, ik->name()); symbolHandle h_name (thread, ik->name());
Handle h_loader (thread, ik->class_loader()); Handle h_loader (thread, ik->class_loader());
Handle h_obj(thread, obj); Handle h_obj(thread, obj);
@ -764,6 +782,9 @@ void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) {
if (ik->protection_domain() != NULL) { if (ik->protection_domain() != NULL) {
guarantee(ik->protection_domain()->is_oop(), "should be oop"); guarantee(ik->protection_domain()->is_oop(), "should be oop");
} }
if (ik->host_klass() != NULL) {
guarantee(ik->host_klass()->is_oop(), "should be oop");
}
if (ik->signers() != NULL) { if (ik->signers() != NULL) {
guarantee(ik->signers()->is_objArray(), "should be obj array"); guarantee(ik->signers()->is_objArray(), "should be obj array");
} }

View file

@ -478,6 +478,24 @@ void Klass::with_array_klasses_do(void f(klassOop k)) {
const char* Klass::external_name() const { const char* Klass::external_name() const {
if (oop_is_instance()) {
instanceKlass* ik = (instanceKlass*) this;
if (ik->is_anonymous()) {
assert(AnonymousClasses, "");
intptr_t hash = ik->java_mirror()->identity_hash();
char hash_buf[40];
sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
size_t hash_len = strlen(hash_buf);
size_t result_len = name()->utf8_length();
char* result = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
name()->as_klass_external_name(result, (int) result_len + 1);
assert(strlen(result) == result_len, "");
strcpy(result + result_len, hash_buf);
assert(strlen(result) == result_len + hash_len, "");
return result;
}
}
return name()->as_klass_external_name(); return name()->as_klass_external_name();
} }

View file

@ -256,10 +256,10 @@
develop(intx, PrintIdealGraphPort, 4444, \ develop(intx, PrintIdealGraphPort, 4444, \
"Ideal graph printer to network port") \ "Ideal graph printer to network port") \
\ \
develop(ccstr, PrintIdealGraphAddress, "127.0.0.1", \ notproduct(ccstr, PrintIdealGraphAddress, "127.0.0.1", \
"IP address to connect to visualizer") \ "IP address to connect to visualizer") \
\ \
develop(ccstr, PrintIdealGraphFile, NULL, \ notproduct(ccstr, PrintIdealGraphFile, NULL, \
"File to dump ideal graph to. If set overrides the " \ "File to dump ideal graph to. If set overrides the " \
"use of the network") \ "use of the network") \
\ \

View file

@ -1673,7 +1673,6 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
if (klass_node == NULL) { if (klass_node == NULL) {
Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes());
klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) ); klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
klass_node->init_req(0, ctrl);
} }
Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type()); Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type());

View file

@ -175,7 +175,7 @@ class Parse : public GraphKit {
bool is_SEL_backedge(Block* pred) const{ return is_SEL_head() && pred->rpo() >= rpo(); } bool is_SEL_backedge(Block* pred) const{ return is_SEL_head() && pred->rpo() >= rpo(); }
bool is_invariant_local(uint i) const { bool is_invariant_local(uint i) const {
const JVMState* jvms = start_map()->jvms(); const JVMState* jvms = start_map()->jvms();
if (!jvms->is_loc(i)) return false; if (!jvms->is_loc(i) || flow()->outer()->has_irreducible_entry()) return false;
return flow()->is_invariant_local(i - jvms->locoff()); return flow()->is_invariant_local(i - jvms->locoff());
} }
bool can_elide_SEL_phi(uint i) const { assert(is_SEL_head(),""); return is_invariant_local(i); } bool can_elide_SEL_phi(uint i) const { assert(is_SEL_head(),""); return is_invariant_local(i); }

View file

@ -744,6 +744,7 @@ static void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) {
// common code for JVM_DefineClass() and JVM_DefineClassWithSource() // common code for JVM_DefineClass() and JVM_DefineClassWithSource()
static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) { static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
if (source == NULL) source = "__JVM_DefineClass__";
// Since exceptions can be thrown, class initialization can take place // Since exceptions can be thrown, class initialization can take place
// if name is NULL no check for class name in .class stream has to be made. // if name is NULL no check for class name in .class stream has to be made.
@ -782,7 +783,7 @@ static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loa
JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)) JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
JVMWrapper2("JVM_DefineClass %s", name); JVMWrapper2("JVM_DefineClass %s", name);
return jvm_define_class_common(env, name, loader, buf, len, pd, "__JVM_DefineClass__", THREAD); return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD);
JVM_END JVM_END

View file

@ -422,6 +422,14 @@ JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len, jobject pd, const jbyte *buf, jsize len, jobject pd,
const char *source); const char *source);
/* Define a class with a source (MLVM) */
JNIEXPORT jclass JNICALL
JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len, jobject pd,
const char *source,
// same args as JVM_DefineClassWithSource to this point
jobjectArray constants);
/* /*
* Reflection support functions * Reflection support functions
*/ */

View file

@ -837,6 +837,163 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineClass1(JNIEnv *env, jobject unsafe, jstring na
} }
UNSAFE_END UNSAFE_END
#define DAC_Args CLS"[B["OBJ
// define a class but do not make it known to the class loader or system dictionary
// - host_class: supplies context for linkage, access control, protection domain, and class loader
// - data: bytes of a class file, a raw memory address (length gives the number of bytes)
// - cp_patches: where non-null entries exist, they replace corresponding CP entries in data
// When you load an anonymous class U, it works as if you changed its name just before loading,
// to a name that you will never use again. Since the name is lost, no other class can directly
// link to any member of U. Just after U is loaded, the only way to use it is reflectively,
// through java.lang.Class methods like Class.newInstance.
// Access checks for linkage sites within U continue to follow the same rules as for named classes.
// The package of an anonymous class is given by the package qualifier on the name under which it was loaded.
// An anonymous class also has special privileges to access any member of its host class.
// This is the main reason why this loading operation is unsafe. The purpose of this is to
// allow language implementations to simulate "open classes"; a host class in effect gets
// new code when an anonymous class is loaded alongside it. A less convenient but more
// standard way to do this is with reflection, which can also be set to ignore access
// restrictions.
// Access into an anonymous class is possible only through reflection. Therefore, there
// are no special access rules for calling into an anonymous class. The relaxed access
// rule for the host class is applied in the opposite direction: A host class reflectively
// access one of its anonymous classes.
// If you load the same bytecodes twice, you get two different classes. You can reload
// the same bytecodes with or without varying CP patches.
// By using the CP patching array, you can have a new anonymous class U2 refer to an older one U1.
// The bytecodes for U2 should refer to U1 by a symbolic name (doesn't matter what the name is).
// The CONSTANT_Class entry for that name can be patched to refer directly to U1.
// This allows, for example, U2 to use U1 as a superclass or super-interface, or as
// an outer class (so that U2 is an anonymous inner class of anonymous U1).
// It is not possible for a named class, or an older anonymous class, to refer by
// name (via its CP) to a newer anonymous class.
// CP patching may also be used to modify (i.e., hack) the names of methods, classes,
// or type descriptors used in the loaded anonymous class.
// Finally, CP patching may be used to introduce "live" objects into the constant pool,
// instead of "dead" strings. A compiled statement like println((Object)"hello") can
// be changed to println(greeting), where greeting is an arbitrary object created before
// the anonymous class is loaded. This is useful in dynamic languages, in which
// various kinds of metaobjects must be introduced as constants into bytecode.
// Note the cast (Object), which tells the verifier to expect an arbitrary object,
// not just a literal string. For such ldc instructions, the verifier uses the
// type Object instead of String, if the loaded constant is not in fact a String.
static oop
Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
jclass host_class, jbyteArray data, jobjectArray cp_patches_jh,
HeapWord* *temp_alloc,
TRAPS) {
if (UsePerfData) {
ClassLoader::unsafe_defineClassCallCounter()->inc();
}
if (data == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length();
jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord);
HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length);
if (body == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
// caller responsible to free it:
(*temp_alloc) = body;
{
jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0);
Copy::conjoint_words((HeapWord*) array_base, body, word_length);
}
u1* class_bytes = (u1*) body;
int class_bytes_length = (int) length;
if (class_bytes_length < 0) class_bytes_length = 0;
if (class_bytes == NULL
|| host_class == NULL
|| length != class_bytes_length)
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
objArrayHandle cp_patches_h;
if (cp_patches_jh != NULL) {
oop p = JNIHandles::resolve_non_null(cp_patches_jh);
if (!p->is_objArray())
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p);
}
KlassHandle host_klass(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(host_class)));
const char* host_source = host_klass->external_name();
Handle host_loader(THREAD, host_klass->class_loader());
Handle host_domain(THREAD, host_klass->protection_domain());
GrowableArray<Handle>* cp_patches = NULL;
if (cp_patches_h.not_null()) {
int alen = cp_patches_h->length();
for (int i = alen-1; i >= 0; i--) {
oop p = cp_patches_h->obj_at(i);
if (p != NULL) {
Handle patch(THREAD, p);
if (cp_patches == NULL)
cp_patches = new GrowableArray<Handle>(i+1, i+1, Handle());
cp_patches->at_put(i, patch);
}
}
}
ClassFileStream st(class_bytes, class_bytes_length, (char*) host_source);
instanceKlassHandle anon_klass;
{
symbolHandle no_class_name;
klassOop anonk = SystemDictionary::parse_stream(no_class_name,
host_loader, host_domain,
&st, host_klass, cp_patches,
CHECK_NULL);
if (anonk == NULL) return NULL;
anon_klass = instanceKlassHandle(THREAD, anonk);
}
// let caller initialize it as needed...
return anon_klass->java_mirror();
}
UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh))
{
UnsafeWrapper("Unsafe_DefineAnonymousClass");
ResourceMark rm(THREAD);
HeapWord* temp_alloc = NULL;
jobject res_jh = NULL;
{ oop res_oop = Unsafe_DefineAnonymousClass_impl(env,
host_class, data, cp_patches_jh,
&temp_alloc, THREAD);
if (res_oop != NULL)
res_jh = JNIHandles::make_local(env, res_oop);
}
// try/finally clause:
if (temp_alloc != NULL) {
FREE_C_HEAP_ARRAY(HeapWord, temp_alloc);
}
return (jclass) res_jh;
}
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj)) UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
UnsafeWrapper("Unsafe_MonitorEnter"); UnsafeWrapper("Unsafe_MonitorEnter");
@ -1292,6 +1449,9 @@ JNINativeMethod memcopy_methods_15[] = {
{CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)} {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)}
}; };
JNINativeMethod anonk_methods[] = {
{CC"defineAnonymousClass", CC"("DAC_Args")"CLS, FN_PTR(Unsafe_DefineAnonymousClass)},
};
#undef CC #undef CC
#undef FN_PTR #undef FN_PTR
@ -1354,6 +1514,15 @@ JVM_ENTRY(void, JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls))
} }
} }
} }
if (AnonymousClasses) {
env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) {
tty->print_cr("Warning: SDK 1.7 Unsafe.defineClass (anonymous version) not found.");
}
env->ExceptionClear();
}
}
int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod)); int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) { if (env->ExceptionOccurred()) {
if (PrintMiscellaneous && (Verbose || WizardMode)) { if (PrintMiscellaneous && (Verbose || WizardMode)) {

View file

@ -493,7 +493,7 @@ class CommandLineFlags {
develop(bool, DeoptimizeALot, false, \ develop(bool, DeoptimizeALot, false, \
"deoptimize at every exit from the runtime system") \ "deoptimize at every exit from the runtime system") \
\ \
develop(ccstrlist, DeoptimizeOnlyAt, "", \ notproduct(ccstrlist, DeoptimizeOnlyAt, "", \
"a comma separated list of bcis to deoptimize at") \ "a comma separated list of bcis to deoptimize at") \
\ \
product(bool, DeoptimizeRandom, false, \ product(bool, DeoptimizeRandom, false, \
@ -2792,7 +2792,7 @@ class CommandLineFlags {
product(intx, TargetSurvivorRatio, 50, \ product(intx, TargetSurvivorRatio, 50, \
"Desired percentage of survivor space used after scavenge") \ "Desired percentage of survivor space used after scavenge") \
\ \
product(intx, MarkSweepDeadRatio, 5, \ product(uintx, MarkSweepDeadRatio, 5, \
"Percentage (0-100) of the old gen allowed as dead wood." \ "Percentage (0-100) of the old gen allowed as dead wood." \
"Serial mark sweep treats this as both the min and max value." \ "Serial mark sweep treats this as both the min and max value." \
"CMS uses this value only if it falls back to mark sweep." \ "CMS uses this value only if it falls back to mark sweep." \
@ -2801,7 +2801,7 @@ class CommandLineFlags {
"either completely full or completely empty. Par compact also" \ "either completely full or completely empty. Par compact also" \
"has a smaller default value; see arguments.cpp.") \ "has a smaller default value; see arguments.cpp.") \
\ \
product(intx, PermMarkSweepDeadRatio, 20, \ product(uintx, PermMarkSweepDeadRatio, 20, \
"Percentage (0-100) of the perm gen allowed as dead wood." \ "Percentage (0-100) of the perm gen allowed as dead wood." \
"See MarkSweepDeadRatio for collector-specific comments.") \ "See MarkSweepDeadRatio for collector-specific comments.") \
\ \
@ -3230,6 +3230,9 @@ class CommandLineFlags {
"Skip assert() and verify() which page-in unwanted shared " \ "Skip assert() and verify() which page-in unwanted shared " \
"objects. ") \ "objects. ") \
\ \
product(bool, AnonymousClasses, false, \
"support sun.misc.Unsafe.defineAnonymousClass") \
\
product(bool, TaggedStackInterpreter, false, \ product(bool, TaggedStackInterpreter, false, \
"Insert tags in interpreter execution stack for oopmap generaion")\ "Insert tags in interpreter execution stack for oopmap generaion")\
\ \

View file

@ -25,6 +25,14 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_perfMemory.cpp.incl" # include "incls/_perfMemory.cpp.incl"
// Prefix of performance data file.
const char PERFDATA_NAME[] = "hsperfdata";
// Add 1 for the '_' character between PERFDATA_NAME and pid. The '\0' terminating
// character will be included in the sizeof(PERFDATA_NAME) operation.
static const size_t PERFDATA_FILENAME_LEN = sizeof(PERFDATA_NAME) +
UINT_CHARS + 1;
char* PerfMemory::_start = NULL; char* PerfMemory::_start = NULL;
char* PerfMemory::_end = NULL; char* PerfMemory::_end = NULL;
char* PerfMemory::_top = NULL; char* PerfMemory::_top = NULL;

View file

@ -95,7 +95,7 @@ typedef struct {
} PerfDataEntry; } PerfDataEntry;
// Prefix of performance data file. // Prefix of performance data file.
static const char PERFDATA_NAME[] = "hsperfdata"; extern const char PERFDATA_NAME[];
// UINT_CHARS contains the number of characters holding a process id // UINT_CHARS contains the number of characters holding a process id
// (i.e. pid). pid is defined as unsigned "int" so the maximum possible pid value // (i.e. pid). pid is defined as unsigned "int" so the maximum possible pid value
@ -103,11 +103,6 @@ static const char PERFDATA_NAME[] = "hsperfdata";
// string. // string.
static const size_t UINT_CHARS = 10; static const size_t UINT_CHARS = 10;
// Add 1 for the '_' character between PERFDATA_NAME and pid. The '\0' terminating
// character will be included in the sizeof(PERFDATA_NAME) operation.
static const size_t PERFDATA_FILENAME_LEN = sizeof(PERFDATA_NAME) +
UINT_CHARS + 1;
/* the PerfMemory class manages creation, destruction, /* the PerfMemory class manages creation, destruction,
* and allocation of the PerfData region. * and allocation of the PerfData region.
*/ */

View file

@ -456,10 +456,32 @@ bool Reflection::verify_class_access(klassOop current_class, klassOop new_class,
return can_relax_access_check_for(current_class, new_class, classloader_only); return can_relax_access_check_for(current_class, new_class, classloader_only);
} }
static bool under_host_klass(instanceKlass* ik, klassOop host_klass) {
DEBUG_ONLY(int inf_loop_check = 1000 * 1000 * 1000);
for (;;) {
klassOop hc = (klassOop) ik->host_klass();
if (hc == NULL) return false;
if (hc == host_klass) return true;
ik = instanceKlass::cast(hc);
// There's no way to make a host class loop short of patching memory.
// Therefore there cannot be a loop here unles there's another bug.
// Still, let's check for it.
assert(--inf_loop_check > 0, "no host_klass loop");
}
}
bool Reflection::can_relax_access_check_for( bool Reflection::can_relax_access_check_for(
klassOop accessor, klassOop accessee, bool classloader_only) { klassOop accessor, klassOop accessee, bool classloader_only) {
instanceKlass* accessor_ik = instanceKlass::cast(accessor); instanceKlass* accessor_ik = instanceKlass::cast(accessor);
instanceKlass* accessee_ik = instanceKlass::cast(accessee); instanceKlass* accessee_ik = instanceKlass::cast(accessee);
// If either is on the other's host_klass chain, access is OK,
// because one is inside the other.
if (under_host_klass(accessor_ik, accessee) ||
under_host_klass(accessee_ik, accessor))
return true;
if (RelaxAccessControlCheck || if (RelaxAccessControlCheck ||
(accessor_ik->major_version() < JAVA_1_5_VERSION && (accessor_ik->major_version() < JAVA_1_5_VERSION &&
accessee_ik->major_version() < JAVA_1_5_VERSION)) { accessee_ik->major_version() < JAVA_1_5_VERSION)) {

View file

@ -1422,6 +1422,7 @@ static void ensure_join(JavaThread* thread) {
thread->clear_pending_exception(); thread->clear_pending_exception();
} }
// For any new cleanup additions, please check to see if they need to be applied to // For any new cleanup additions, please check to see if they need to be applied to
// cleanup_failed_attach_current_thread as well. // cleanup_failed_attach_current_thread as well.
void JavaThread::exit(bool destroy_vm, ExitType exit_type) { void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
@ -1592,37 +1593,60 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
JvmtiExport::cleanup_thread(this); JvmtiExport::cleanup_thread(this);
} }
#ifndef SERIALGC
// We must flush G1-related buffers before removing a thread from
// the list of active threads.
if (UseG1GC) {
flush_barrier_queues();
}
#endif
// Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
Threads::remove(this); Threads::remove(this);
} }
void JavaThread::cleanup_failed_attach_current_thread() { #ifndef SERIALGC
// Flush G1-related queues.
if (get_thread_profiler() != NULL) { void JavaThread::flush_barrier_queues() {
get_thread_profiler()->disengage(); satb_mark_queue().flush();
ResourceMark rm; dirty_card_queue().flush();
get_thread_profiler()->print(get_thread_name());
}
if (active_handles() != NULL) {
JNIHandleBlock* block = active_handles();
set_active_handles(NULL);
JNIHandleBlock::release_block(block);
}
if (free_handle_block() != NULL) {
JNIHandleBlock* block = free_handle_block();
set_free_handle_block(NULL);
JNIHandleBlock::release_block(block);
}
if (UseTLAB) {
tlab().make_parsable(true); // retire TLAB, if any
}
Threads::remove(this);
delete this;
} }
#endif
void JavaThread::cleanup_failed_attach_current_thread() {
if (get_thread_profiler() != NULL) {
get_thread_profiler()->disengage();
ResourceMark rm;
get_thread_profiler()->print(get_thread_name());
}
if (active_handles() != NULL) {
JNIHandleBlock* block = active_handles();
set_active_handles(NULL);
JNIHandleBlock::release_block(block);
}
if (free_handle_block() != NULL) {
JNIHandleBlock* block = free_handle_block();
set_free_handle_block(NULL);
JNIHandleBlock::release_block(block);
}
if (UseTLAB) {
tlab().make_parsable(true); // retire TLAB, if any
}
#ifndef SERIALGC
if (UseG1GC) {
flush_barrier_queues();
}
#endif
Threads::remove(this);
delete this;
}
JavaThread* JavaThread::active() { JavaThread* JavaThread::active() {

View file

@ -793,6 +793,8 @@ class JavaThread: public Thread {
DirtyCardQueue _dirty_card_queue; // Thread-local log for dirty cards. DirtyCardQueue _dirty_card_queue; // Thread-local log for dirty cards.
// Set of all such queues. // Set of all such queues.
static DirtyCardQueueSet _dirty_card_queue_set; static DirtyCardQueueSet _dirty_card_queue_set;
void flush_barrier_queues();
#endif // !SERIALGC #endif // !SERIALGC
friend class VMThread; friend class VMThread;

View file

@ -40,11 +40,18 @@ class ResourceArray: public ResourceObj {
_length = 0; _length = 0;
_data = NULL; _data = NULL;
DEBUG_ONLY(init_nesting();) DEBUG_ONLY(init_nesting();)
// client may call initialize, at most once
} }
ResourceArray(size_t esize, int length) { ResourceArray(size_t esize, int length) {
DEBUG_ONLY(_data = NULL);
initialize(esize, length);
}
void initialize(size_t esize, int length) {
assert(length >= 0, "illegal length"); assert(length >= 0, "illegal length");
assert(_data == NULL, "must be new object");
_length = length; _length = length;
_data = resource_allocate_bytes(esize * length); _data = resource_allocate_bytes(esize * length);
DEBUG_ONLY(init_nesting();) DEBUG_ONLY(init_nesting();)
@ -111,7 +118,10 @@ class CHeapArray: public CHeapObj {
/* creation */ \ /* creation */ \
array_name() : base_class() {} \ array_name() : base_class() {} \
array_name(const int length) : base_class(esize, length) {} \ array_name(const int length) : base_class(esize, length) {} \
array_name(const int length, const etype fx) : base_class(esize, length) { \ array_name(const int length, const etype fx) { initialize(length, fx); } \
void initialize(const int length) { base_class::initialize(esize, length); } \
void initialize(const int length, const etype fx) { \
initialize(length); \
for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx; \ for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx; \
} \ } \
\ \
@ -157,16 +167,29 @@ class CHeapArray: public CHeapObj {
\ \
public: \ public: \
/* creation */ \ /* creation */ \
stack_name() : array_name() { _size = 0; } \ stack_name() : array_name() { _size = 0; } \
stack_name(const int size) : array_name(size){ _length = 0; _size = size; } \ stack_name(const int size) { initialize(size); } \
stack_name(const int size, const etype fx) : array_name(size, fx) { _size = size; } \ stack_name(const int size, const etype fx) { initialize(size, fx); } \
void initialize(const int size, const etype fx) { \
_size = size; \
array_name::initialize(size, fx); \
/* _length == size, allocation and size are the same */ \
} \
void initialize(const int size) { \
_size = size; \
array_name::initialize(size); \
_length = 0; /* reset length to zero; _size records the allocation */ \
} \
\ \
/* standard operations */ \ /* standard operations */ \
int size() const { return _size; } \ int size() const { return _size; } \
\ \
void push(const etype x) { \ int push(const etype x) { \
if (length() >= size()) expand(esize, length(), _size); \ int len = length(); \
((etype*)_data)[_length++] = x; \ if (len >= size()) expand(esize, len, _size); \
((etype*)_data)[len] = x; \
_length = len+1; \
return len; \
} \ } \
\ \
etype pop() { \ etype pop() { \
@ -235,7 +258,7 @@ class CHeapArray: public CHeapObj {
int capacity() const { return size(); } \ int capacity() const { return size(); } \
void clear() { truncate(0); } \ void clear() { truncate(0); } \
void trunc_to(const int length) { truncate(length); } \ void trunc_to(const int length) { truncate(length); } \
void append(const etype x) { push(x); } \ int append(const etype x) { return push(x); } \
void appendAll(const stack_name* stack) { push_all(stack); } \ void appendAll(const stack_name* stack) { push_all(stack); } \
etype last() const { return top(); } \ etype last() const { return top(); } \
}; \ }; \

View file

@ -71,6 +71,7 @@ class constantTag VALUE_OBJ_CLASS_SPEC {
bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; }
bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); } bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); }
bool is_klass_or_reference() const{ return is_klass() || is_klass_reference(); }
bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); } bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); }
bool is_symbol() const { return is_utf8(); } bool is_symbol() const { return is_utf8(); }

View file

@ -567,7 +567,7 @@ static void find(intptr_t x, bool print_pc) {
} }
// the InlineCacheBuffer is using stubs generated into a buffer blob // the InlineCacheBuffer is using stubs generated into a buffer blob
if (InlineCacheBuffer::contains(addr)) { if (InlineCacheBuffer::contains(addr)) {
tty->print_cr(INTPTR_FORMAT "is pointing into InlineCacheBuffer", addr); tty->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", addr);
return; return;
} }
VtableStub* v = VtableStubs::stub_containing(addr); VtableStub* v = VtableStubs::stub_containing(addr);
@ -595,7 +595,7 @@ static void find(intptr_t x, bool print_pc) {
return; return;
} }
if (Universe::heap()->is_in_reserved(addr)) { if (Universe::heap()->is_in(addr)) {
HeapWord* p = Universe::heap()->block_start(addr); HeapWord* p = Universe::heap()->block_start(addr);
bool print = false; bool print = false;
// If we couldn't find it it just may mean that heap wasn't parseable // If we couldn't find it it just may mean that heap wasn't parseable
@ -621,24 +621,28 @@ static void find(intptr_t x, bool print_pc) {
} }
return; return;
} }
} else if (Universe::heap()->is_in_reserved(addr)) {
tty->print_cr(INTPTR_FORMAT " is an unallocated location in the heap", addr);
return;
} }
if (JNIHandles::is_global_handle((jobject) addr)) { if (JNIHandles::is_global_handle((jobject) addr)) {
tty->print_cr(INTPTR_FORMAT "is a global jni handle", addr); tty->print_cr(INTPTR_FORMAT " is a global jni handle", addr);
return; return;
} }
if (JNIHandles::is_weak_global_handle((jobject) addr)) { if (JNIHandles::is_weak_global_handle((jobject) addr)) {
tty->print_cr(INTPTR_FORMAT "is a weak global jni handle", addr); tty->print_cr(INTPTR_FORMAT " is a weak global jni handle", addr);
return; return;
} }
if (JNIHandleBlock::any_contains((jobject) addr)) { if (JNIHandleBlock::any_contains((jobject) addr)) {
tty->print_cr(INTPTR_FORMAT "is a local jni handle", addr); tty->print_cr(INTPTR_FORMAT " is a local jni handle", addr);
return; return;
} }
for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) { for(JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
// Check for priviledge stack // Check for privilege stack
if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) { if (thread->privileged_stack_top() != NULL && thread->privileged_stack_top()->contains(addr)) {
tty->print_cr(INTPTR_FORMAT "is pointing into the priviledge stack for thread: " INTPTR_FORMAT, addr, thread); tty->print_cr(INTPTR_FORMAT " is pointing into the privilege stack for thread: " INTPTR_FORMAT, addr, thread);
return; return;
} }
// If the addr is a java thread print information about that. // If the addr is a java thread print information about that.
@ -659,7 +663,7 @@ static void find(intptr_t x, bool print_pc) {
return; return;
} }
tty->print_cr(INTPTR_FORMAT "is pointing to unknown location", addr); tty->print_cr(INTPTR_FORMAT " is pointing to unknown location", addr);
} }

View file

@ -111,6 +111,12 @@ class GenericGrowableArray : public ResourceObj {
} }
void* raw_allocate(int elementSize); void* raw_allocate(int elementSize);
// some uses pass the Thread explicitly for speed (4990299 tuning)
void* raw_allocate(Thread* thread, int elementSize) {
assert(on_stack(), "fast ResourceObj path only");
return (void*)resource_allocate_bytes(thread, elementSize * _max);
}
}; };
template<class E> class GrowableArray : public GenericGrowableArray { template<class E> class GrowableArray : public GenericGrowableArray {
@ -121,6 +127,11 @@ template<class E> class GrowableArray : public GenericGrowableArray {
void raw_at_put_grow(int i, const E& p, const E& fill); void raw_at_put_grow(int i, const E& p, const E& fill);
void clear_and_deallocate(); void clear_and_deallocate();
public: public:
GrowableArray(Thread* thread, int initial_size) : GenericGrowableArray(initial_size, 0, false) {
_data = (E*)raw_allocate(thread, sizeof(E));
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
}
GrowableArray(int initial_size, bool C_heap = false) : GenericGrowableArray(initial_size, 0, C_heap) { GrowableArray(int initial_size, bool C_heap = false) : GenericGrowableArray(initial_size, 0, C_heap) {
_data = (E*)raw_allocate(sizeof(E)); _data = (E*)raw_allocate(sizeof(E));
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E(); for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
@ -159,10 +170,12 @@ template<class E> class GrowableArray : public GenericGrowableArray {
void print(); void print();
void append(const E& elem) { int append(const E& elem) {
check_nesting(); check_nesting();
if (_len == _max) grow(_len); if (_len == _max) grow(_len);
_data[_len++] = elem; int idx = _len++;
_data[idx] = elem;
return idx;
} }
void append_if_missing(const E& elem) { void append_if_missing(const E& elem) {

View file

@ -43,9 +43,11 @@ BasicHashtableEntry* BasicHashtable::new_entry(unsigned int hashValue) {
entry = _free_list; entry = _free_list;
_free_list = _free_list->next(); _free_list = _free_list->next();
} else { } else {
const int block_size = 500; if (_first_free_entry + _entry_size >= _end_block) {
if (_first_free_entry == _end_block) { int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
int len = _entry_size * block_size; int len = _entry_size * block_size;
len = 1 << log2_intptr(len); // round down to power of 2
assert(len >= _entry_size, "");
_first_free_entry = NEW_C_HEAP_ARRAY(char, len); _first_free_entry = NEW_C_HEAP_ARRAY(char, len);
_end_block = _first_free_entry + len; _end_block = _first_free_entry + len;
} }
@ -53,6 +55,7 @@ BasicHashtableEntry* BasicHashtable::new_entry(unsigned int hashValue) {
_first_free_entry += _entry_size; _first_free_entry += _entry_size;
} }
assert(_entry_size % HeapWordSize == 0, "");
entry->set_hash(hashValue); entry->set_hash(hashValue);
return entry; return entry;
} }

View file

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

View file

@ -14,3 +14,4 @@ cf4894b78ceb966326e93bf221db0c2d14d59218 jdk7-b35
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37 14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38 cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39 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. * The version of the JMX specification implemented by this product.
* <BR> * <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. * 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 @SuppressWarnings("cast") // cast for jdk 1.5
public static long getLeaseTimeout() { public static long getLeaseTimeout() {
long timeout = EventClient.DEFAULT_LEASE_TIMEOUT; long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
try { try {
final GetPropertyAction act = final GetPropertyAction act =
new GetPropertyAction(DEFAULT_LEASE_TIMEOUT); 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.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -143,9 +144,10 @@ public class LeaseManager {
private final Runnable callback; private final Runnable callback;
private ScheduledFuture<?> scheduled; // If null, the lease has expired. private ScheduledFuture<?> scheduled; // If null, the lease has expired.
private static final ThreadFactory threadFactory =
new DaemonThreadFactory("JMX LeaseManager %d");
private final ScheduledExecutorService executor private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1, = Executors.newScheduledThreadPool(1, threadFactory);
new DaemonThreadFactory("JMX LeaseManager %d"));
private static final ClassLogger logger = private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager"); 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.namespace.MBeanServerSupport;
import javax.management.remote.IdentityMBeanServerForwarder; 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 { public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
private final ObjectName mbeanName; private final ObjectName mbeanName;
private final boolean visible;
private DynamicMBean mbean; private DynamicMBean mbean;
private MBeanServer mbeanMBS = new MBeanServerSupport() { private MBeanServer mbeanMBS = new MBeanServerSupport() {
@ -85,10 +95,20 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
return null; 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.mbeanName = mbeanName;
this.visible = visible;
setSingleMBean(mbean); setSingleMBean(mbean);
} }
@ -213,8 +233,10 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override @Override
public String[] getDomains() { public String[] getDomains() {
TreeSet<String> domainSet = String[] domains = super.getDomains();
new TreeSet<String>(Arrays.asList(super.getDomains())); if (!visible)
return domains;
TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains));
domainSet.add(mbeanName.getDomain()); domainSet.add(mbeanName.getDomain());
return domainSet.toArray(new String[domainSet.size()]); return domainSet.toArray(new String[domainSet.size()]);
} }
@ -222,7 +244,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override @Override
public Integer getMBeanCount() { public Integer getMBeanCount() {
Integer count = super.getMBeanCount(); Integer count = super.getMBeanCount();
if (!super.isRegistered(mbeanName)) if (visible && !super.isRegistered(mbeanName))
count++; count++;
return count; return count;
} }
@ -284,7 +306,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
*/ */
private boolean applies(ObjectName pattern) { private boolean applies(ObjectName pattern) {
// we know pattern is not null. // we know pattern is not null.
if (!pattern.apply(mbeanName)) if (!visible || !pattern.apply(mbeanName))
return false; return false;
final String dompat = pattern.getDomain(); final String dompat = pattern.getDomain();
@ -306,10 +328,12 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override @Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
Set<ObjectInstance> names = super.queryMBeans(name, query); Set<ObjectInstance> names = super.queryMBeans(name, query);
if (name == null || applies(name) ) { if (visible) {
// Don't assume mbs.queryNames returns a writable set. if (name == null || applies(name) ) {
names = Util.cloneSet(names); // Don't assume mbs.queryNames returns a writable set.
names.addAll(mbeanMBS.queryMBeans(name, query)); names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryMBeans(name, query));
}
} }
return names; return names;
} }
@ -317,10 +341,12 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override @Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
Set<ObjectName> names = super.queryNames(name, query); Set<ObjectName> names = super.queryNames(name, query);
if (name == null || applies(name)) { if (visible) {
// Don't assume mbs.queryNames returns a writable set. if (name == null || applies(name)) {
names = Util.cloneSet(names); // Don't assume mbs.queryNames returns a writable set.
names.addAll(mbeanMBS.queryNames(name, query)); names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryNames(name, query));
}
} }
return names; return names;
} }

View file

@ -122,7 +122,7 @@ public final class JmxMBeanServer
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)} * {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* instead. * instead.
* <p> * <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. * {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
* </ul> * </ul>
* @param domain The default domain name used by this MBeanServer. * @param domain The default domain name used by this MBeanServer.
@ -239,7 +239,7 @@ public final class JmxMBeanServer
this.mBeanServerDelegateObject = delegate; this.mBeanServerDelegateObject = delegate;
this.outerShell = outer; this.outerShell = outer;
final Repository repository = new Repository(domain,fairLock); final Repository repository = new Repository(domain);
this.mbsInterceptor = this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator, new NamespaceDispatchInterceptor(outer, delegate, instantiator,
repository); 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 int tlen;
final boolean identity; final boolean identity;
public ObjectNameRouter(String targetDirName) {
this(targetDirName,null);
}
/** Creates a new instance of ObjectNameRouter */ /** Creates a new instance of ObjectNameRouter */
public ObjectNameRouter(final String remove, final String add) { public ObjectNameRouter(final String remove, final String add) {
this.targetPrefix = (remove==null?"":remove); this.targetPrefix = (remove==null?"":remove);
@ -186,6 +181,4 @@ public class ObjectNameRouter {
b.append(NAMESPACE_SEPARATOR); b.append(NAMESPACE_SEPARATOR);
return b.toString(); return b.toString();
} }
} }

View file

@ -31,7 +31,6 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.management.MBeanServerConnection; import javax.management.MBeanServerConnection;
import javax.management.namespace.JMXNamespaces;
/** /**
@ -57,22 +56,14 @@ public class RoutingConnectionProxy
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; 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 * Creates a new instance of RoutingConnectionProxy
*/ */
public RoutingConnectionProxy(MBeanServerConnection source, public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir, String sourceDir,
String targetDir, String targetDir,
boolean forwardsContext) { boolean probe) {
super(source,sourceDir,targetDir,forwardsContext); super(source, sourceDir, targetDir, probe);
if (LOG.isLoggable(Level.FINER)) if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() + LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
@ -85,15 +76,13 @@ public class RoutingConnectionProxy
final String sourceNs = getSourceNamespace(); final String sourceNs = getSourceNamespace();
String wrapped = String.valueOf(source()); String wrapped = String.valueOf(source());
if ("".equals(targetNs)) { if ("".equals(targetNs)) {
if (forwardsContext)
wrapped = "ClientContext.withDynamicContext("+wrapped+")";
return "JMXNamespaces.narrowToNamespace("+ return "JMXNamespaces.narrowToNamespace("+
wrapped+", \""+ wrapped+", \""+
sourceNs+"\")"; sourceNs+"\")";
} }
return this.getClass().getSimpleName()+"("+wrapped+", \""+ return this.getClass().getSimpleName()+"("+wrapped+", \""+
sourceNs+"\", \""+ sourceNs+"\", \""+
targetNs+"\", "+forwardsContext+")"; targetNs+"\")";
} }
static final RoutingProxyFactory static final RoutingProxyFactory
@ -102,22 +91,16 @@ public class RoutingConnectionProxy
<MBeanServerConnection,RoutingConnectionProxy>() { <MBeanServerConnection,RoutingConnectionProxy>() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source, public RoutingConnectionProxy newInstance(MBeanServerConnection source,
String sourcePath, String targetPath, String sourcePath, String targetPath, boolean probe) {
boolean forwardsContext) {
return new RoutingConnectionProxy(source,sourcePath, return new RoutingConnectionProxy(source,sourcePath,
targetPath,forwardsContext); targetPath, probe);
}
public RoutingConnectionProxy newInstance(
MBeanServerConnection source, String sourcePath) {
return new RoutingConnectionProxy(source,sourcePath);
} }
}; };
public static MBeanServerConnection cd(MBeanServerConnection source, public static MBeanServerConnection cd(
String sourcePath) { MBeanServerConnection source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY, 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.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException; import javax.management.MBeanException;
import javax.management.MBeanRegistrationException; import javax.management.MBeanRegistrationException;
@ -90,17 +91,9 @@ import javax.management.namespace.JMXNamespaces;
// targetNs=<encoded-context> // context must be removed from object name // targetNs=<encoded-context> // context must be removed from object name
// sourceNs="" // nothing to add... // 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, // Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a // 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 // return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and // another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd // RoutingServerProxy.cd
@ -146,25 +139,27 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
private final T source; private final T source;
// The name space we're narrowing to (usually some name space in // 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; 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; private final String targetNs;
// The name of the JMXNamespace that handles the source name space // The name of the JMXNamespace that handles the source name space
private final ObjectName handlerName; private final ObjectName handlerName;
private final ObjectNameRouter router; private final ObjectNameRouter router;
final boolean forwardsContext;
private volatile String defaultDomain = null; private volatile String defaultDomain = null;
/** /**
* Creates a new instance of RoutingProxy * Creates a new instance of RoutingProxy
*/ */
protected RoutingProxy(T source, protected RoutingProxy(T source,
String sourceNs, String sourceNs,
String targetNs, String targetNs,
boolean forwardsContext) { boolean probe) {
if (source == null) throw new IllegalArgumentException("null"); if (source == null) throw new IllegalArgumentException("null");
this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs); this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
@ -177,13 +172,17 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// System.err.println("sourceNs: "+sourceNs); // System.err.println("sourceNs: "+sourceNs);
this.handlerName = this.handlerName =
JMXNamespaces.getNamespaceObjectName(this.sourceNs); JMXNamespaces.getNamespaceObjectName(this.sourceNs);
try { if (probe) {
// System.err.println("handlerName: "+handlerName); try {
if (!source.isRegistered(handlerName)) if (!source.isRegistered(handlerName)) {
throw new IllegalArgumentException(sourceNs + InstanceNotFoundException infe =
": no such name space"); new InstanceNotFoundException(handlerName);
} catch (IOException x) { throw new IllegalArgumentException(sourceNs +
throw new IllegalArgumentException("source stale: "+x,x); ": no such name space", infe);
}
} catch (IOException x) {
throw new IllegalArgumentException("source stale: "+x,x);
}
} }
} }
this.source = source; this.source = source;
@ -191,7 +190,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
JMXNamespaces.normalizeNamespaceName(targetNs)); JMXNamespaces.normalizeNamespaceName(targetNs));
this.router = this.router =
new ObjectNameRouter(this.targetNs,this.sourceNs); new ObjectNameRouter(this.targetNs,this.sourceNs);
this.forwardsContext = forwardsContext;
if (LOG.isLoggable(Level.FINER)) if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingProxy for " + this.sourceNs + " created"); LOG.finer("RoutingProxy for " + this.sourceNs + " created");
@ -200,14 +198,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
@Override @Override
public T source() { return source; } public T source() { return source; }
ObjectNameRouter getObjectNameRouter() {
// TODO: uncomment this when contexts are added
// if (forwardsContext)
// return ObjectNameRouter.wrapWithContext(router);
// else
return router;
}
@Override @Override
public ObjectName toSource(ObjectName targetName) public ObjectName toSource(ObjectName targetName)
throws MalformedObjectNameException { throws MalformedObjectNameException {
@ -222,8 +212,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
if (defaultDomain != null) if (defaultDomain != null)
targetName = targetName.withDomain(defaultDomain); targetName = targetName.withDomain(defaultDomain);
} }
final ObjectNameRouter r = getObjectNameRouter(); return router.toSourceContext(targetName,true);
return r.toSourceContext(targetName,true);
} }
@Override @Override
@ -243,8 +232,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
public ObjectName toTarget(ObjectName sourceName) public ObjectName toTarget(ObjectName sourceName)
throws MalformedObjectNameException { throws MalformedObjectNameException {
if (sourceName == null) return null; if (sourceName == null) return null;
final ObjectNameRouter r = getObjectNameRouter(); return router.toTargetContext(sourceName,false);
return r.toTargetContext(sourceName,false);
} }
private Object getAttributeFromHandler(String attributeName) private Object getAttributeFromHandler(String attributeName)
@ -357,11 +345,8 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// instance. // instance.
static interface RoutingProxyFactory<T extends MBeanServerConnection, static interface RoutingProxyFactory<T extends MBeanServerConnection,
R extends RoutingProxy<T>> { R extends RoutingProxy<T>> {
R newInstance(T source, public R newInstance(
String sourcePath, String targetPath, T source, String sourcePath, String targetPath, boolean probe);
boolean forwardsContext);
R newInstance(T source,
String sourcePath);
} }
// Performs a narrowDownToNamespace operation. // Performs a narrowDownToNamespace operation.
@ -377,7 +362,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
static <T extends MBeanServerConnection, R extends RoutingProxy<T>> static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
R cd(Class<R> routingProxyClass, R cd(Class<R> routingProxyClass,
RoutingProxyFactory<T,R> factory, RoutingProxyFactory<T,R> factory,
T source, String sourcePath) { T source, String sourcePath, boolean probe) {
if (source == null) throw new IllegalArgumentException("null"); if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) { if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast // 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 = final String path =
JMXNamespaces.concat(other.getSourceNamespace(), JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath); sourcePath);
return factory.newInstance(other.source(),path,"", return factory.newInstance(other.source(), path, "", probe);
other.forwardsContext);
} }
// Note: we could do possibly something here - but it would involve // Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding // removing part of targetDir, and possibly adding
// something to sourcePath. // something to sourcePath.
// Too complex to bother! => simply default to stacking... // 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.QueryExp;
import javax.management.ReflectionException; import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository; import javax.management.loading.ClassLoaderRepository;
import javax.management.namespace.JMXNamespaces;
/** /**
* A RoutingServerProxy is an MBeanServer proxy that proxies a * A RoutingServerProxy is an MBeanServer proxy that proxies a
@ -76,19 +75,11 @@ public class RoutingServerProxy
extends RoutingProxy<MBeanServer> extends RoutingProxy<MBeanServer>
implements MBeanServer { implements MBeanServer {
/**
* Creates a new instance of RoutingServerProxy
*/
public RoutingServerProxy(MBeanServer source,
String sourceNs) {
this(source,sourceNs,"",false);
}
public RoutingServerProxy(MBeanServer source, public RoutingServerProxy(MBeanServer source,
String sourceNs, String sourceNs,
String targetNs, String targetNs,
boolean forwardsContext) { boolean probe) {
super(source,sourceNs,targetNs,forwardsContext); super(source, sourceNs, targetNs, probe);
} }
/** /**
@ -571,20 +562,15 @@ public class RoutingServerProxy
FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() { FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() {
public RoutingServerProxy newInstance(MBeanServer source, public RoutingServerProxy newInstance(MBeanServer source,
String sourcePath, String targetPath, String sourcePath, String targetPath, boolean probe) {
boolean forwardsContext) { return new RoutingServerProxy(
return new RoutingServerProxy(source,sourcePath, source, sourcePath, targetPath, probe);
targetPath,forwardsContext);
}
public RoutingServerProxy newInstance(
MBeanServer source, String sourcePath) {
return new RoutingServerProxy(source,sourcePath);
} }
}; };
public static MBeanServer cd(MBeanServer source, String sourcePath) { public static MBeanServer cd(
MBeanServer source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY, 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 * The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used * for the first time. If null, a default factory will be used
* (see {@link #createEventClient}). * (see {@link #createEventClient}).
* @return the * @return the MBeanServerConnection.
**/ **/
public static MBeanServerConnection getEventConnectionFor( public static MBeanServerConnection getEventConnectionFor(
MBeanServerConnection connection, MBeanServerConnection connection,
Callable<EventClient> eventClientFactory) { Callable<EventClient> eventClientFactory) {
// if c already uses an EventClient no need to create a new one.
//
if (connection instanceof EventClientFactory if (connection instanceof EventClientFactory
&& eventClientFactory != null) && eventClientFactory != null)
throw new IllegalArgumentException("connection already uses EventClient"); throw new IllegalArgumentException("connection already uses EventClient");

View file

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

View file

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

View file

@ -73,10 +73,23 @@ abstract public class HttpURLConnection extends URLConnection {
* The fixed content-length when using fixed-length streaming mode. * The fixed content-length when using fixed-length streaming mode.
* A value of <code>-1</code> means fixed-length streaming mode is disabled * A value of <code>-1</code> means fixed-length streaming mode is disabled
* for output. * 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 * @since 1.5
*/ */
protected int fixedContentLength = -1; 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. * Returns the key for the <code>n</code><sup>th</sup> header field.
* Some implementations may treat the <code>0</code><sup>th</sup> * 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. * This exception can be queried for the details of the error.
* <p> * <p>
* This method must be called before the URLConnection is connected. * 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 * @param contentLength The number of bytes which will be written
* to the OutputStream. * to the OutputStream.
@ -135,6 +151,52 @@ abstract public class HttpURLConnection extends URLConnection {
fixedContentLength = contentLength; 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; /* Default chunk size (including chunk header) if not specified;
* we want to keep this in sync with the one defined in * we want to keep this in sync with the one defined in
* sun.net.www.http.ChunkedOutputStream * sun.net.www.http.ChunkedOutputStream
@ -170,7 +232,7 @@ abstract public class HttpURLConnection extends URLConnection {
if (connected) { if (connected) {
throw new IllegalStateException ("Can't set streaming mode: already 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"); throw new IllegalStateException ("Fixed length streaming mode set");
} }
chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen; 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.) * permitted, and indicates that the cause is nonexistent or unknown.)
*/ */
public CertPathValidatorException(Throwable cause) { 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Represents a list of values for attributes of an MBean. The methods * <p>Represents a list of values for attributes of an MBean. See the
* used for the insertion of {@link javax.management.Attribute * {@link MBeanServerConnection#getAttributes getAttributes} and
* Attribute} objects in the <CODE>AttributeList</CODE> overrides the * {@link MBeanServerConnection#setAttributes setAttributes} methods of
* corresponding methods in the superclass * {@link MBeanServer} and {@link MBeanServerConnection}.</p>
* <CODE>ArrayList</CODE>. This is needed in order to insure that the *
* objects contained in the <CODE>AttributeList</CODE> are only * <p id="type-safe">For compatibility reasons, it is possible, though
* <CODE>Attribute</CODE> objects. This avoids getting an exception * highly discouraged, to add objects to an {@code AttributeList} that are
* when retrieving elements from the <CODE>AttributeList</CODE>. * 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 * @since 1.5
*/ */
@ -58,8 +64,8 @@ import java.util.List;
*/ */
public class AttributeList extends ArrayList<Object> { public class AttributeList extends ArrayList<Object> {
private transient boolean typeSafe; private transient volatile boolean typeSafe;
private transient boolean tainted; private transient volatile boolean tainted;
/* Serial version */ /* Serial version */
private static final long serialVersionUID = -4077085769279709076L; private static final long serialVersionUID = -4077085769279709076L;
@ -124,13 +130,63 @@ public class AttributeList extends ArrayList<Object> {
// Check for non-Attribute objects // Check for non-Attribute objects
// //
checkTypeSafe(list); adding(list);
// Build the List<Attribute> // Build the List<Attribute>
// //
super.addAll(list); 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>}. * Return a view of this list as a {@code List<Attribute>}.
* Changes to the returned value are reflected by changes * Changes to the returned value are reflected by changes
@ -154,11 +210,9 @@ public class AttributeList extends ArrayList<Object> {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<Attribute> asList() { public List<Attribute> asList() {
if (!typeSafe) { typeSafe = true;
if (tainted) if (tainted)
checkTypeSafe(this); adding((Collection<?>) this); // will throw IllegalArgumentException
typeSafe = true;
}
return (List<Attribute>) (List<?>) this; 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. * Inserts the attribute specified as an element at the position specified.
* Elements with an index greater than or equal to the current position are * 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 > * 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. * java.lang.IndexOutOfBoundsException thrown.
* *
* @param object The <CODE>Attribute</CODE> object to be inserted. * @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) { public boolean addAll(int index, AttributeList list) {
try { try {
return super.addAll(index, list); return super.addAll(index, list);
} } catch (IndexOutOfBoundsException e) {
catch (IndexOutOfBoundsException e) {
throw new RuntimeOperationsException(e, throw new RuntimeOperationsException(e,
"The specified index is out of range"); "The specified index is out of range");
} }
@ -258,96 +311,77 @@ public class AttributeList extends ArrayList<Object> {
* been called on this instance. * 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 @Override
public boolean add(Object o) { public boolean add(Object element) {
if (!tainted) adding(element);
tainted = isTainted(o); return super.add(element);
if (typeSafe)
checkTypeSafe(o);
return super.add(o);
} }
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override @Override
public void add(int index, Object element) { public void add(int index, Object element) {
if (!tainted) adding(element);
tainted = isTainted(element);
if (typeSafe)
checkTypeSafe(element);
super.add(index, 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 @Override
public boolean addAll(Collection<?> c) { public boolean addAll(Collection<?> c) {
if (!tainted) adding(c);
tainted = isTainted(c);
if (typeSafe)
checkTypeSafe(c);
return super.addAll(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 @Override
public boolean addAll(int index, Collection<?> c) { public boolean addAll(int index, Collection<?> c) {
if (!tainted) adding(c);
tainted = isTainted(c);
if (typeSafe)
checkTypeSafe(c);
return super.addAll(index, 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 @Override
public Object set(int index, Object element) { public Object set(int index, Object element) {
if (!tainted) adding(element);
tainted = isTainted(element);
if (typeSafe)
checkTypeSafe(element);
return super.set(index, element); return super.set(index, element);
} }
/** private void adding(Object x) {
* IllegalArgumentException if o is a non-Attribute object. if (x == null || x instanceof Attribute)
*/ return;
private static void checkTypeSafe(Object o) { if (typeSafe)
try { throw new IllegalArgumentException("Not an Attribute: " + x);
o = (Attribute) o; else
} catch (ClassCastException e) { tainted = true;
throw new IllegalArgumentException(e);
}
} }
/** private void adding(Collection<?> c) {
* IllegalArgumentException if c contains any non-Attribute objects. for (Object x : c)
*/ adding(x);
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;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -35,8 +35,8 @@ import java.io.Serializable;
// Javadoc imports: // Javadoc imports:
import java.lang.management.MemoryUsage; import java.lang.management.MemoryUsage;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
@ -118,19 +118,22 @@ import javax.management.openmbean.OpenType;
* deprecation, for example {@code "1.3 Replaced by the Capacity * deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td> * attribute"}.</td>
* *
* <tr id="descriptionResourceBundleBaseName"> * <tr><td id="descriptionResourceBundleBaseName"><i>descriptionResource<br>
* <td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td> * BundleBaseName</i></td><td>String</td><td>Any</td>
* *
* <td>The base name for the {@link ResourceBundle} in which the key given in * <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example * 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"> * <tr><td id="descriptionResourceKey"><i>descriptionResourceKey</i></td>
* <td>descriptionResourceKey</td><td>String</td><td>Any</td> * <td>String</td><td>Any</td>
* *
* <td>A resource key for the description of this element. In * <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName}, * 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> * <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</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> * href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a>
* notification.</td> * 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 * <td>The time in milli-seconds that the MBeanInfo can reasonably be
* reasonably be expected to be unchanged. The value can be a {@code Long} * expected to be unchanged. The value can be a {@code Long} or a
* or a decimal string. This provides a hint from a DynamicMBean or any * decimal string. This provides a hint from a DynamicMBean or any
* MBean that does not define {@code immutableInfo} as {@code true} * MBean that does not define {@code immutableInfo} as {@code true}
* that the MBeanInfo is not likely to change within this period and * that the MBeanInfo is not likely to change within this period and
* therefore can be cached. When this field is missing or has the * 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 * <td>Legal values for an attribute or parameter. See
* {@link javax.management.openmbean}.</td> * {@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> * <tr id="maxValue"><td><i>maxValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</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 com.sun.jmx.remote.util.ClassLogger;
import java.beans.BeanInfo; import java.beans.BeanInfo;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -37,6 +38,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import javax.management.namespace.JMXNamespaces;
import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.MXBeanMappingFactory;
/** /**
@ -60,6 +62,21 @@ public class JMX {
*/ */
public static final String DEFAULT_VALUE_FIELD = "defaultValue"; 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 * The name of the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field. * immutableInfo}</a> field.
@ -78,6 +95,12 @@ public class JMX {
*/ */
public static final String LEGAL_VALUES_FIELD = "legalValues"; 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 * The name of the <a href="Descriptor.html#maxValue">{@code
* maxValue}</a> field. * maxValue}</a> field.
@ -120,13 +143,12 @@ public class JMX {
* <p>Options to apply to an MBean proxy or to an instance of {@link * <p>Options to apply to an MBean proxy or to an instance of {@link
* StandardMBean}.</p> * StandardMBean}.</p>
* *
* <p>For example, to specify a custom {@link MXBeanMappingFactory} * <p>For example, to specify the "wrapped object visible" option for a
* for a {@code StandardMBean}, you might write this:</p> * {@code StandardMBean}, you might write this:</p>
* *
* <pre> * <pre>
* MXBeanMappingFactory factory = new MyMXBeanMappingFactory(); * StandardMBean.Options opts = new StandardMBean.Options();
* JMX.MBeanOptions opts = new JMX.MBeanOptions(); * opts.setWrappedObjectVisible(true);
* opts.setMXBeanMappingFactory(factory);
* StandardMBean mbean = new StandardMBean(impl, intf, opts); * StandardMBean mbean = new StandardMBean(impl, intf, opts);
* </pre> * </pre>
* *
@ -808,4 +830,80 @@ public class JMX {
((DynamicWrapperMBean) mbean).getWrappedObject() : mbean; ((DynamicWrapperMBean) mbean).getWrappedObject() : mbean;
return (MBeanInjector.injectsSendNotification(resource)); 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; package javax.management;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException; import java.io.IOException;
import java.io.StreamCorruptedException; import java.io.StreamCorruptedException;
import java.io.Serializable; import java.io.Serializable;
@ -37,6 +38,12 @@ import java.util.WeakHashMap;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; 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; 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 * <p>Since this class is immutable, the clone method is chiefly of
* interest to subclasses.</p> * interest to subclasses.</p>
*/ */
@Override
public Object clone () { public Object clone () {
try { try {
return super.clone() ; return super.clone() ;
@ -474,6 +482,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
return (Descriptor) nonNullDescriptor(descriptor).clone(); return (Descriptor) nonNullDescriptor(descriptor).clone();
} }
@Override
public String toString() { public String toString() {
return return
getClass().getName() + "[" + 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 * @return true if and only if <code>o</code> is an MBeanInfo that is equal
* to this one according to the rules above. * to this one according to the rules above.
*/ */
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) if (o == this)
return true; return true;
@ -524,6 +534,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
Arrays.equals(p.fastGetNotifications(), fastGetNotifications())); Arrays.equals(p.fastGetNotifications(), fastGetNotifications()));
} }
@Override
public int hashCode() { public int hashCode() {
/* Since computing the hashCode is quite expensive, we cache it. /* Since computing the hashCode is quite expensive, we cache it.
If by some terrible misfortune the computed value is 0, the 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."); 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 * <p>Retrieves the values of several attributes of a named MBean. The MBean
* is identified by its object name. * 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 * @param name The object name of the MBean from which the
* attributes are retrieved. * attributes are retrieved.
@ -557,6 +579,7 @@ public interface MBeanServerConnection extends NotificationManager {
throws InstanceNotFoundException, ReflectionException, throws InstanceNotFoundException, ReflectionException,
IOException; IOException;
/** /**
* Sets the value of a specific attribute of a named MBean. The MBean * Sets the value of a specific attribute of a named MBean. The MBean
* is identified by its object name. * is identified by its object name.
@ -592,10 +615,36 @@ public interface MBeanServerConnection extends NotificationManager {
ReflectionException, IOException; ReflectionException, IOException;
/** /**
* Sets the values of several attributes of a named MBean. The MBean is * <p>Sets the values of several attributes of a named MBean. The MBean is
* identified by its object name. * 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 * @param name The object name of the MBean within which the
* attributes are to be set. * attributes are to be set.
@ -622,7 +671,39 @@ public interface MBeanServerConnection extends NotificationManager {
throws InstanceNotFoundException, ReflectionException, IOException; 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 * @param name The object name of the MBean on which the method is
* to be invoked. * to be invoked.
@ -630,7 +711,8 @@ public interface MBeanServerConnection extends NotificationManager {
* @param params An array containing the parameters to be set when * @param params An array containing the parameters to be set when
* the operation is invoked * the operation is invoked
* @param signature An array containing the signature of the * @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 * class loader as the one used for loading the MBean on which the
* operation was invoked. * 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 * The MBean Server emits the following types of notifications: MBean registration, MBean
* de-registration. * unregistration.
* <P> * <P>
* To receive to MBeanServerNotifications, you need to be declared as listener to * To receive MBeanServerNotifications, you need to register a listener with
* the {@link javax.management.MBeanServerDelegate javax.management.MBeanServerDelegate} MBean * the {@link MBeanServerDelegate MBeanServerDelegate} MBean
* that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is: * that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is
* {@link MBeanServerDelegate#DELEGATE_NAME}, which is
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>. * <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 * @since 1.5
*/ */
public class MBeanServerNotification extends Notification { public class MBeanServerNotification extends Notification {

View file

@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetPropertyAction;
* @since 1.5 * @since 1.5
*/ */
@SuppressWarnings("serial") // serialVersionUID is not constant @SuppressWarnings("serial") // serialVersionUID is not constant
public class Notification extends EventObject { public class Notification extends EventObject implements Cloneable {
// Serialization compatibility stuff: // Serialization compatibility stuff:
// Two serial forms are supported in this class. The selected form depends // Two serial forms are supported in this class. The selected form depends
@ -243,6 +243,26 @@ public class Notification extends EventObject {
this.message = message ; 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. * Sets the source.
* *
@ -285,8 +305,10 @@ public class Notification extends EventObject {
/** /**
* Get the notification type. * Get the notification type.
* *
* @return The notification type. It's a string expressed in a dot notation similar * @return The notification type. It's a string expressed in a dot notation
* to Java properties. An example of a notification type is network.alarm.router . * 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() { public String getType() {
return type ; return type ;
@ -317,14 +339,25 @@ public class Notification extends EventObject {
/** /**
* Get the notification message. * Get the notification message.
* *
* @return The message string of this notification object. It contains in a string, * @return The message string of this notification object.
* which could be the explanation of the notification for displaying to a user
* *
* @see #setMessage
*/ */
public String getMessage() { public String getMessage() {
return message ; 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. * Get the user data.
* *
@ -355,6 +388,7 @@ public class Notification extends EventObject {
* *
* @return A String representation of this notification. * @return A String representation of this notification.
*/ */
@Override
public String toString() { public String toString() {
return super.toString()+"[type="+type+"][message="+message+"]"; return super.toString()+"[type="+type+"][message="+message+"]";
} }

View file

@ -26,7 +26,6 @@
package javax.management; package javax.management;
import com.sun.jmx.mbeanserver.NotificationMBeanSupport; import com.sun.jmx.mbeanserver.NotificationMBeanSupport;
import com.sun.jmx.mbeanserver.Util;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; 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 * on both the client and the server in the remote case, so using this class
* instead is recommended where possible.</p> * 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 * <p>This class uses the {@linkplain Query Query API} to specify the
* filtering logic. For example, to select only notifications where the * filtering logic. For example, to select only notifications where the
* {@linkplain Notification#getType() type} is {@code "com.example.mytype"}, * {@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.LeaseRenewer;
import com.sun.jmx.event.ReceiverBuffer; import com.sun.jmx.event.ReceiverBuffer;
import com.sun.jmx.event.RepeatedSingletonJob; import com.sun.jmx.event.RepeatedSingletonJob;
import com.sun.jmx.namespace.JMXNamespaceUtils;
import com.sun.jmx.mbeanserver.PerThreadGroupPool; import com.sun.jmx.mbeanserver.PerThreadGroupPool;
import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.ClassLogger;
@ -58,7 +57,6 @@ import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter; import javax.management.NotificationFilter;
import javax.management.NotificationListener; import javax.management.NotificationListener;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.NotificationResult; import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification; 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"; 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 * @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> * <p>Constructs a default {@code EventClient} object.</p>
@ -173,7 +172,7 @@ public class EventClient implements EventConsumer, NotificationManager {
*/ */
public EventClient(EventClientDelegateMBean delegate) public EventClient(EventClientDelegateMBean delegate)
throws IOException { 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. * If {@code null}, a default scheduler will be used.
* @param requestedLeaseTime The lease time used to keep this client alive * @param requestedLeaseTime The lease time used to keep this client alive
* in the {@link EventClientDelegateMBean}. A value of zero is equivalent * 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 IllegalArgumentException If {@code delegate} is null.
* @throws IOException If an I/O error occurs when communicating with the * @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) if (requestedLeaseTime == 0)
requestedLeaseTime = DEFAULT_LEASE_TIMEOUT; requestedLeaseTime = DEFAULT_REQUESTED_LEASE_TIME;
else if (requestedLeaseTime < 0) { else if (requestedLeaseTime < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Negative lease time: " + requestedLeaseTime); "Negative lease time: " + requestedLeaseTime);
@ -269,7 +268,13 @@ public class EventClient implements EventConsumer, NotificationManager {
new ScheduledThreadPoolExecutor(20, daemonThreadFactory); new ScheduledThreadPoolExecutor(20, daemonThreadFactory);
executor.setKeepAliveTime(1, TimeUnit.SECONDS); executor.setKeepAliveTime(1, TimeUnit.SECONDS);
executor.allowCoreThreadTimeOut(true); 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 // By default, a ScheduledThreadPoolExecutor will keep jobs
// in its queue even after they have been cancelled. They // in its queue even after they have been cancelled. They
// will only be removed when their scheduled time arrives. // 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 // this EventClient, this can lead to a moderately large number
// of objects remaining referenced until the renewal time // of objects remaining referenced until the renewal time
// arrives. Hence the above call, which removes the job from // 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 executor;
} }
}; };
return leaseRenewerThreadPool.getThreadPoolExecutor(create); 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 { final public EventClient call() throws Exception {
EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn); EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn);
return new EventClient(ecd, eventRelay, null, null, 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; 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> private static final PerThreadGroupPool<ScheduledThreadPoolExecutor>
leaseRenewerThreadPool = PerThreadGroupPool.make(); 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. // of a setMBeanServer on some other forwarder later in the chain.
private static class Forwarder extends SingleMBeanForwarder { private static class Forwarder extends SingleMBeanForwarder {
private MBeanServer loopMBS;
private static class UnsupportedInvocationHandler private static class UnsupportedInvocationHandler
implements InvocationHandler { implements InvocationHandler {
@ -173,7 +174,11 @@ public class EventClientDelegate implements EventClientDelegateMBean {
private volatile boolean madeECD; private volatile boolean madeECD;
Forwarder() { Forwarder() {
super(OBJECT_NAME, makeUnsupportedECD()); super(OBJECT_NAME, makeUnsupportedECD(), true);
}
synchronized void setLoopMBS(MBeanServer loopMBS) {
this.loopMBS = loopMBS;
} }
@Override @Override
@ -186,7 +191,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
AccessController.doPrivileged( AccessController.doPrivileged(
new PrivilegedAction<EventClientDelegate>() { new PrivilegedAction<EventClientDelegate>() {
public EventClientDelegate run() { public EventClientDelegate run() {
return getEventClientDelegate(Forwarder.this); return getEventClientDelegate(loopMBS);
} }
}); });
DynamicMBean mbean = new StandardMBean( 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 * that are targeted for that MBean and handles them itself. All other
* requests are forwarded to the next element in the forwarder chain.</p> * 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 * @return a new {@code MBeanServerForwarder} that simulates the existence
* of an {@code EventClientDelegateMBean}. * of an {@code EventClientDelegateMBean}.
*
* @see javax.management.remote.JMXConnectorServer#installStandardForwarders
*/ */
public static MBeanServerForwarder newForwarder() { public static MBeanServerForwarder newForwarder(
return new Forwarder(); 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 classes
// ------------------------------------ // ------------------------------------
private class ClientInfo { private class ClientInfo {
String clientId; final String clientId;
EventBuffer buffer; final NotificationListener clientListener;
NotificationListener clientListener; final Map<Integer, AddedListener> listenerInfoMap =
Map<Integer, AddedListener> listenerInfoMap =
new HashMap<Integer, AddedListener>(); new HashMap<Integer, AddedListener>();
ClientInfo(String clientId, EventForwarder forwarder) { ClientInfo(String clientId, EventForwarder forwarder) {
@ -703,7 +742,8 @@ public class EventClientDelegate implements EventClientDelegateMBean {
clientInfo = clientInfoMap.get(clientId); clientInfo = clientInfoMap.get(clientId);
if (clientInfo == null) { if (clientInfo == null) {
throw new EventClientNotFoundException("The client is not found."); throw new EventClientNotFoundException(
"Client not found (id " + clientId + ")");
} }
return clientInfo; 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 * 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 * 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 * 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 * <li><p>A variant on the above is to replace the MBean Server that is
* used locally with a forwarder as described above. Since * used locally with a forwarder as described above. Since
@ -61,9 +62,7 @@ import javax.management.remote.NotificationResult;
* *
* <pre> * <pre>
* MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever * MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
* MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(); * mbs = EventClientDelegate.newForwarder(mbs, null);
* mbsf.setMBeanServer(mbs);
* mbs = mbsf;
* // now use mbs just as you did before, but it will have an EventClientDelegate * // now use mbs just as you did before, but it will have an EventClientDelegate
* </pre> * </pre>
* *

View file

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

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