This commit is contained in:
J. Duke 2017-07-05 16:39:25 +02:00
commit ee82845d00
124 changed files with 6906 additions and 1273 deletions

View File

@ -5,3 +5,4 @@ cbc8ad9dd0e085a607427ea35411990982f19a36 jdk7-b25
56652b46f328937f6b9b5130f1e4cd80f48868ef jdk7-b28
31e08f70e88d77c2053f91c21b49a04296bdc59a jdk7-b29
2dab2f712e1832c92acfa63ec0337048b9422c20 jdk7-b30
3300a35a0bd56d695b92fe0b34f03ebbfc939064 jdk7-b31

View File

@ -5,15 +5,12 @@
</head>
<body style="background-color:lightcyan">
<!-- ====================================================== -->
<table width="100%" style="background-color:white">
+ <table width="100%">
<tr>
<td align="center">
<a href="http://openjdk.java.net" border="0">
<img alt="OpenJDK"
src="http://openjdk.java.net/images/openjdk.png"
width=256
style="border-style: none"/>
</a>
<img alt="OpenJDK"
src="http://openjdk.java.net/images/openjdk.png"
width=256 />
</td>
</tr>
<tr>
@ -54,6 +51,7 @@
<li><a href="#bootjdk">Bootstrap JDK</a> </li>
<li><a href="#binaryplugs">Binary Plugs</a> </li>
<li><a href="#importjdk">Optional Import JDK</a> </li>
<li><a href="#ant">Ant</a> </li>
<li><a href="#cacerts">Certificate Authority File (cacert)</a> </li>
<li><a href="#compilers">Compilers</a>
<ul>
@ -424,24 +422,37 @@
you should use <tt>gmake</tt>
which will be located in either the <tt>/opt/sfw/bin</tt> or
<tt>/usr/sfw/bin</tt> directory.
In more recent versions of Solaris GNU make can be found
at <tt>/usr/bin/gmake</tt>.
</li>
<li>
<strong>Windows:</strong>
Make sure you start your build inside a bash/sh/ksh shell.
<br>
<b>WARNING:</b> Watch out for make version 3.81, it may
not work due to a lack of support for drive letter paths
like <tt>C:/</tt>. See
<a href="#gmake">section on gmake</a>.
not work due to a lack of support for MS-DOS drive letter paths
like <tt>C:/</tt> or <tt>C:\</tt>.
Use a 3.80 version, or find a newer
version that has this problem fixed.
version that has this problem fixed, like 3.82.
The older 3.80 version of make.exe can be downloaded with this
<a href="http://cygwin.paracoda.com/release/make/make-3.80-1.tar.bz2" target="_blank">
link</a>.
Use of this older 3.80 make.exe may require that you install the
libintl2.dll library or libintl2 cygwin package which is
no longer installed by default by the cygwin installer.
<br>
Also see the
<a href="http://developer.mozilla.org/en/docs/Windows_build_prerequisites_using_cygwin#make" target="_blank">
mozilla developer center</a>
on this topic.
<br>
It's hoped that when make 3.82 starts shipping in a future cygwin
release that this MS-DOS path issue will be fixed.
In addition to the above 3.80 make.exe you can download
this
<a href="http://www.cmake.org/files/cygwin/make.exe">
www.cmake.org make.exe</a> which will not have a libintl2.dll
dependency.
</li>
</ul>
<p>
@ -507,6 +518,11 @@
Install or upgrade the <a href="#freetype">FreeType development
package</a>.
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
</li>
</ol>
</blockquote>
<!-- ------------------------------------------------------ -->
@ -567,6 +583,11 @@
<a href="#cups">CUPS Include files</a>, set
<tt><a href="#ALT_CUPS_HEADERS_PATH">ALT_CUPS_HEADERS_PATH</a></tt>.
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
</li>
</ol>
</blockquote>
<!-- ------------------------------------------------------ -->
@ -654,6 +675,11 @@
Install
<a href="#dxsdk">Microsoft DirectX SDK</a>.
</li>
<li>
Install
<a href="#ant">Ant</a>, set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
</li>
</ol>
</blockquote>
<!-- ------------------------------------------------------ -->
@ -736,6 +762,22 @@
and the build will copy the needed files from this import area.
</blockquote>
<!-- ------------------------------------------------------ -->
<h4><a name="ant">Ant</a></h4>
<blockquote>
All OpenJDK builds require access to least Ant 1.6.5.
The Ant tool is available from the
<a href="http://ant.apache.org/antlibs/bindownload.cgi" target="_blank">
Ant download site</a>.
You should always set
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>
to point to the location of
the Ant installation, this is the directory pathname
that contains a <tt>bin and lib</tt>.
It's also a good idea to also place its <tt>bin</tt> directory
in the <tt>PATH</tt> environment variable, although it's
not absolutely required.
</blockquote>
<!-- ------------------------------------------------------ -->
<h4><a name="cacerts">Certificate Authority File (cacert)</a></h4>
<blockquote>
See <a href="http://en.wikipedia.org/wiki/Certificate_Authority" target="_blank">
@ -915,6 +957,21 @@
and
<tt><a href="#ALT_FREETYPE_HEADERS_PATH">ALT_FREETYPE_HEADERS_PATH</a></tt>
to refer to place where library and header files are installed.
<p>
Building the freetype 2 libraries from scratch is also possible,
however on Windows refer to the
<a href="http://freetype.freedesktop.org/wiki/FreeType_DLL">
Windows FreeType DLL build instructions</a>.
<p>
Note that by default FreeType is built with byte code hinting
support disabled due to licensing restrictions.
In this case, text appearance and metrics are expected to
differ from Sun's official JDK build.
See
<a href="http://freetype.sourceforge.net/freetype2/index.html">
the SourceForge FreeType2 Home Page
</a>
for more information.
</blockquote>
<!-- ------------------------------------------------------ -->
<h4><a name="alsa">Advanced Linux Sound Architecture (ALSA) (Linux only)</a></h4>
@ -1036,7 +1093,8 @@
<tr>
<td>make.exe</td>
<td>Devel</td>
<td>make: The GNU version of the 'make' utility</td>
<td>make: The GNU version of the 'make' utility<br>
<b>NOTE</b>: See <a href="#gmake">the GNU make section</a></td>
</tr>
<tr>
<td>m4.exe</td>
@ -1050,7 +1108,7 @@
<td>cpio: A program to manage archives of files</td>
</tr>
<tr>
<td>awk.exe</td>
<td>gawk.exe</td>
<td>Utils</td>
<td>awk: Pattern-directed scanning and processing language</td>
</tr>
@ -1061,17 +1119,17 @@
</tr>
<tr>
<td>zip.exe</td>
<td>Utils</td>
<td>Archive</td>
<td>zip: Package and compress (archive) files</td>
</tr>
<tr>
<td>unzip.exe</td>
<td>Utils</td>
<td>Archive</td>
<td>unzip: Extract compressed files in a ZIP archive</td>
</tr>
<tr>
<td>free.exe</td>
<td>Utils</td>
<td>Procps</td>
<td>free: Display amount of free and used memory in the system</td>
</tr>
</tbody>
@ -1224,46 +1282,6 @@
document) that can impact the build are:
<blockquote>
<dl>
<dt><a name="path"><tt>PATH</tt></a> </dt>
<dd>Typically you want to set the <tt>PATH</tt> to include:
<ul>
<li>The location of the GNU make binary</li>
<li>The location of the Bootstrap JDK <tt>java</tt>
(see <a href="#bootjdk">Bootstrap JDK</a>)</li>
<li>The location of the C/C++ compilers
(see <a href="#compilers"><tt>compilers</tt></a>)</li>
<li>The location or locations for the Unix command utilities
(e.g. <tt>/usr/bin</tt>)</li>
</ul>
</dd>
<dt><tt>MILESTONE</tt> </dt>
<dd>
The milestone name for the build (<i>e.g.</i>"beta").
The default value is "internal".
</dd>
<dt><tt>BUILD_NUMBER</tt> </dt>
<dd>
The build number for the build (<i>e.g.</i> "b27").
The default value is "b00".
</dd>
<dt><a name="arch_data_model"><tt>ARCH_DATA_MODEL</tt></a></dt>
<dd>The <tt>ARCH_DATA_MODEL</tt> variable
is used to specify whether the build is to generate 32-bit or 64-bit
binaries.
The Solaris build supports either 32-bit or 64-bit builds, but
Windows and Linux will support only one, depending on the specific
OS being used.
Normally, setting this variable is only necessary on Solaris.
Set <tt>ARCH_DATA_MODEL</tt> to <tt>32</tt> for generating 32-bit binaries,
or to <tt>64</tt> for generating 64-bit binaries.
</dd>
<dt><a name="ALT_BOOTDIR"><tt>ALT_BOOTDIR</tt></a></dt>
<dd>
The location of the bootstrap JDK installation.
See <a href="#bootjdk">Bootstrap JDK</a> for more information.
You should always install your own local Bootstrap JDK and
always set <tt>ALT_BOOTDIR</tt> explicitly.
</dd>
<dt><a name="ALT_BINARY_PLUGS_PATH"><tt>ALT_BINARY_PLUGS_PATH</tt></a></dt>
<dd>
The location of the binary plugs installation.
@ -1272,118 +1290,12 @@
recent Binary Plugs install image
and set this variable to that location.
</dd>
<dt><a name="ALT_JDK_IMPORT_PATH"><tt>ALT_JDK_IMPORT_PATH</tt></a></dt>
<dt><a name="ALT_BOOTDIR"><tt>ALT_BOOTDIR</tt></a></dt>
<dd>
The location of a previously built JDK installation.
See <a href="#importjdk">Optional Import JDK</a> for more information.
</dd>
<dt><a name="ALT_OUTPUTDIR"><tt>ALT_OUTPUTDIR</tt></a> </dt>
<dd>
An override for specifying the (absolute) path of where the
build output is to go.
The default output directory will be build/<i>platform</i>.
</dd>
<dt><a name="ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a> </dt>
<dd>
The location of the C/C++ compiler.
The default varies depending on the platform.
</dd>
<dt><tt><a name="ALT_CACERTS_FILE">ALT_CACERTS_FILE</a></tt></dt>
<dd>
The location of the <a href="#cacerts">cacerts</a> file.
The default will refer to
<tt>jdk/src/share/lib/security/cacerts</tt>.
</dd>
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
<dd>
The location of the CUPS header files.
See <a href="#cups">CUPS information</a> for more information.
If this path does not exist the fallback path is
<tt>/usr/include</tt>.
</dd>
<dt><a name="ALT_FREETYPE_LIB_PATH"><tt>ALT_FREETYPE_LIB_PATH</tt></a></dt>
<dd>
The location of the FreeType shared library.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_FREETYPE_HEADERS_PATH"><tt>ALT_FREETYPE_HEADERS_PATH</tt></a></dt>
<dd>
The location of the FreeType header files.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_JDK_DEVTOOLS_PATH"><tt>ALT_JDK_DEVTOOLS_PATH</tt></a></dt>
<dd>
The default root location of the devtools.
The default value is
<tt>$(ALT_SLASH_JAVA)/devtools</tt>.
</dd>
<dt><tt><a name="ALT_DEVTOOLS_PATH">ALT_DEVTOOLS_PATH</a></tt> </dt>
<dd>
The location of tools like the
<a href="#zip"><tt>zip</tt> and <tt>unzip</tt></a>
binaries, but might also contain the GNU make utility
(<tt><i>gmake</i></tt>).
So this area is a bit of a grab bag, especially on Windows.
The default value depends on the platform and
Unix Commands being used.
On Linux the default will be
<tt>$(ALT_JDK_DEVTOOLS_PATH)/linux/bin</tt>,
on Solaris
<tt>$(ALT_JDK_DEVTOOLS_PATH)/<i>{sparc,i386}</i>/bin</tt>,
on Windows with MKS
<tt>%SYSTEMDRIVE%/UTILS</tt>,
and on Windows with CYGWIN
<tt>/usr/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_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_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="ALT_SLASHJAVA"><tt>ALT_SLASHJAVA</tt></a></dt>
<dd>
The default root location for many of the ALT path locations
of the following ALT variables.
The default value is
<tt>"/java"</tt> on Solaris and Linux,
<tt>"J:"</tt> on Windows.
</dd>
<dt><a name="ALT_BUILD_JDK_IMPORT_PATH"><tt>ALT_BUILD_JDK_IMPORT_PATH</tt></a></dt>
<dd>
These are useful in managing builds on multiple platforms.
The default network location for all of the import JDK images
for all platforms.
If <tt><a href="#ALT_JDK_IMPORT_PATH">ALT_JDK_IMPORT_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 import JDK image
for that platform.
The location of the bootstrap JDK installation.
See <a href="#bootjdk">Bootstrap JDK</a> for more information.
You should always install your own local Bootstrap JDK and
always set <tt>ALT_BOOTDIR</tt> explicitly.
</dd>
<dt><a name="ALT_BUILD_BINARY_PLUGS_PATH"><tt>ALT_BUILD_BINARY_PLUGS_PATH</tt></a></dt>
<dd>
@ -1405,36 +1317,186 @@
Where each of these directories contain the binary plugs image
for that platform.
</dd>
<dt><strong>Windows specific:</strong></dt>
<dt><a name="ALT_BUILD_JDK_IMPORT_PATH"><tt>ALT_BUILD_JDK_IMPORT_PATH</tt></a></dt>
<dd>
<dl>
<dt><a name="ALT_MSDEVTOOLS_PATH"><tt>ALT_MSDEVTOOLS_PATH</tt></a> </dt>
<dd>
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_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt>
<dd>
The location of the
<a href="#dxsdk">Microsoft DirectX 9 SDK</a>.
The default will be to try and use the DirectX environment
variable <tt>DXSDK_DIR</tt>,
failing that, look in <tt>C:/DXSDK</tt>.
</dd>
<dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
<dd>
The location of the
<a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCR71_DLL_PATH">ALT_MSVCR71_DLL_PATH</a></tt> </dt>
<dd>
<strong>i586 only:</strong>
The location of the
<a href="#msvcr71"><tt>MSVCR71.DLL</tt></a>.
</dd>
</dl>
These are useful in managing builds on multiple platforms.
The default network location for all of the import JDK images
for all platforms.
If <tt><a href="#ALT_JDK_IMPORT_PATH">ALT_JDK_IMPORT_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 import JDK image
for that 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_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><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
<dd>
The location of the CUPS header files.
See <a href="#cups">CUPS information</a> for more information.
If this path does not exist the fallback path is
<tt>/usr/include</tt>.
</dd>
<dt><tt><a name="ALT_DEVTOOLS_PATH">ALT_DEVTOOLS_PATH</a></tt> </dt>
<dd>
The location of tools like the
<a href="#zip"><tt>zip</tt> and <tt>unzip</tt></a>
binaries, but might also contain the GNU make utility
(<tt><i>gmake</i></tt>).
So this area is a bit of a grab bag, especially on Windows.
The default value depends on the platform and
Unix Commands being used.
On Linux the default will be
<tt>$(ALT_JDK_DEVTOOLS_PATH)/linux/bin</tt>,
on Solaris
<tt>$(ALT_JDK_DEVTOOLS_PATH)/<i>{sparc,i386}</i>/bin</tt>,
on Windows with MKS
<tt>%SYSTEMDRIVE%/UTILS</tt>,
and on Windows with CYGWIN
<tt>/usr/bin</tt>.
</dd>
<dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the
<a href="#dxsdk">Microsoft DirectX 9 SDK</a>.
The default will be to try and use the DirectX environment
variable <tt>DXSDK_DIR</tt>,
failing that, look in <tt>C:/DXSDK</tt>.
</dd>
<dt><a name="ALT_FREETYPE_HEADERS_PATH"><tt>ALT_FREETYPE_HEADERS_PATH</tt></a></dt>
<dd>
The location of the FreeType header files.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_FREETYPE_LIB_PATH"><tt>ALT_FREETYPE_LIB_PATH</tt></a></dt>
<dd>
The location of the FreeType shared library.
See <a href="#freetype">FreeType information</a> for details.
</dd>
<dt><a name="ALT_JDK_DEVTOOLS_PATH"><tt>ALT_JDK_DEVTOOLS_PATH</tt></a></dt>
<dd>
The default root location of the devtools.
The default value is
<tt>$(ALT_SLASH_JAVA)/devtools</tt>.
</dd>
<dt><a name="ALT_JDK_IMPORT_PATH"><tt>ALT_JDK_IMPORT_PATH</tt></a></dt>
<dd>
The location of a previously built JDK installation.
See <a href="#importjdk">Optional Import JDK</a> for more information.
</dd>
<dt><a name="ALT_MSDEVTOOLS_PATH"><tt>ALT_MSDEVTOOLS_PATH</tt></a> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the Microsoft Visual Studio .NET 2003
tools 'bin' directory.
The default is usually derived from
<a href="#ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCR71_DLL_PATH">ALT_MSVCR71_DLL_PATH</a></tt> </dt>
<dd>
<strong>Windows i586 only:</strong>
The location of the
<a href="#msvcr71"><tt>MSVCR71.DLL</tt></a>.
</dd>
<dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
<dd>
<strong>Windows Only:</strong>
The location of the
<a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
</dd>
<dt><a name="ALT_OUTPUTDIR"><tt>ALT_OUTPUTDIR</tt></a> </dt>
<dd>
An override for specifying the (absolute) path of where the
build output is to go.
The default output directory will be build/<i>platform</i>.
</dd>
<dt><a name="ALT_SLASHJAVA"><tt>ALT_SLASHJAVA</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>
</dl>
</blockquote>

View File

@ -5,3 +5,4 @@ e84e9018bebbf3e5bafc5706e7882a15cb1c7d99 jdk7-b27
27509b7d21ed783b3f6eb7b7612781c675a30c2f jdk7-b28
8b71960f79ce0a6fb8ddfeec03f03d400a361747 jdk7-b29
c0252adbb2abbfdd6c35595429ac6fbdd98e20ac jdk7-b30
ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31

View File

@ -5,3 +5,4 @@ e3d2692f8442e2d951166dc9bd9a330684754438 jdk7-b27
c14dab40ed9bf45ad21150bd70c9c80cdf655415 jdk7-b28
4f91c08b3e4498213a9c5a24898f7d9c38cf86fb jdk7-b29
d1605aabd0a15ecf93787c47de63073c33fba52d jdk7-b30
9c2ecc2ffb125f14fab3857fe7689598956348a0 jdk7-b31

View File

@ -2414,8 +2414,20 @@ static bool linux_mprotect(char* addr, size_t size, int prot) {
return ::mprotect(bottom, size, prot) == 0;
}
bool os::protect_memory(char* addr, size_t size) {
return linux_mprotect(addr, size, PROT_READ);
// Set protections specified
bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed) {
unsigned int p = 0;
switch (prot) {
case MEM_PROT_NONE: p = PROT_NONE; break;
case MEM_PROT_READ: p = PROT_READ; break;
case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
default:
ShouldNotReachHere();
}
// is_committed is unused.
return linux_mprotect(addr, bytes, p);
}
bool os::guard_memory(char* addr, size_t size) {
@ -3704,8 +3716,9 @@ void os::make_polling_page_unreadable(void) {
// Mark the polling page as readable
void os::make_polling_page_readable(void) {
if( !protect_memory((char *)_polling_page, Linux::page_size()) )
if( !linux_mprotect((char *)_polling_page, Linux::page_size(), PROT_READ)) {
fatal("Could not enable polling page");
}
};
int os::active_processor_count() {

View File

@ -2965,10 +2965,21 @@ static bool solaris_mprotect(char* addr, size_t bytes, int prot) {
return retVal == 0;
}
// Protect memory (make it read-only. (Used to pass readonly pages through
// Protect memory (Used to pass readonly pages through
// JNI GetArray<type>Elements with empty arrays.)
bool os::protect_memory(char* addr, size_t bytes) {
return solaris_mprotect(addr, bytes, PROT_READ);
bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed) {
unsigned int p = 0;
switch (prot) {
case MEM_PROT_NONE: p = PROT_NONE; break;
case MEM_PROT_READ: p = PROT_READ; break;
case MEM_PROT_RW: p = PROT_READ|PROT_WRITE; break;
case MEM_PROT_RWX: p = PROT_READ|PROT_WRITE|PROT_EXEC; break;
default:
ShouldNotReachHere();
}
// is_committed is unused.
return solaris_mprotect(addr, bytes, p);
}
// guard_memory and unguard_memory only happens within stack guard pages.

View File

@ -2170,6 +2170,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
// Windows 98 reports faulting addresses incorrectly
if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) ||
!os::win32::is_nt()) {
return Handle_Exception(exceptionInfo,
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL));
}
@ -2563,9 +2564,33 @@ bool os::release_memory(char* addr, size_t bytes) {
return VirtualFree(addr, 0, MEM_RELEASE) != 0;
}
bool os::protect_memory(char* addr, size_t bytes) {
// Set protections specified
bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed) {
unsigned int p = 0;
switch (prot) {
case MEM_PROT_NONE: p = PAGE_NOACCESS; break;
case MEM_PROT_READ: p = PAGE_READONLY; break;
case MEM_PROT_RW: p = PAGE_READWRITE; break;
case MEM_PROT_RWX: p = PAGE_EXECUTE_READWRITE; break;
default:
ShouldNotReachHere();
}
DWORD old_status;
return VirtualProtect(addr, bytes, PAGE_READONLY, &old_status) != 0;
// Strange enough, but on Win32 one can change protection only for committed
// memory, not a big deal anyway, as bytes less or equal than 64K
if (!is_committed && !commit_memory(addr, bytes)) {
fatal("cannot commit protection page");
}
// One cannot use os::guard_memory() here, as on Win32 guard page
// have different (one-shot) semantics, from MSDN on PAGE_GUARD:
//
// Pages in the region become guard pages. Any attempt to access a guard page
// causes the system to raise a STATUS_GUARD_PAGE exception and turn off
// the guard page status. Guard pages thus act as a one-time access alarm.
return VirtualProtect(addr, bytes, p, &old_status) != 0;
}
bool os::guard_memory(char* addr, size_t bytes) {

View File

@ -27,12 +27,6 @@
#include <asm-sparc/traps.h>
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Since the linux kernel resides at the low end of
// user address space, no null pointer check is needed.
return offset < 0 || offset >= 0x100000;
}
void MacroAssembler::read_ccr_trap(Register ccr_save) {
// No implementation
breakpoint_trap();

View File

@ -39,10 +39,3 @@ void MacroAssembler::get_thread(Register thread) {
movptr(thread, tls);
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Linux kernel guarantees that the first page is always unmapped. Don't
// assume anything more than that.
bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
return !offset_in_first_page;
}

View File

@ -65,22 +65,3 @@ void MacroAssembler::get_thread(Register thread) {
popq(rax);
}
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Exception handler checks the nmethod's implicit null checks table
// only when this method returns false.
if (UseCompressedOops) {
// The first page after heap_base is unmapped and
// the 'offset' is equal to [heap_base + offset] for
// narrow oop implicit null checks.
uintptr_t heap_base = (uintptr_t)Universe::heap_base();
if ((uintptr_t)offset >= heap_base) {
// Normalize offset for the next check.
offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
}
}
// Linux kernel guarantees that the first page is always unmapped. Don't
// assume anything more than that.
bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
return !offset_in_first_page;
}

View File

@ -28,18 +28,6 @@
#include <sys/trap.h> // For trap numbers
#include <v9/sys/psr_compat.h> // For V8 compatibility
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// The first page of virtual addresses is unmapped on SPARC.
// Thus, any access the VM makes through a null pointer with an offset of
// less than 4K will get a recognizable SIGSEGV, which the signal handler
// will transform into a NullPointerException.
// (Actually, the first 64K or so is unmapped, but it's simpler
// to depend only on the first 4K or so.)
bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
return !offset_in_first_page;
}
void MacroAssembler::read_ccr_trap(Register ccr_save) {
// Execute a trap to get the PSR, mask and shift
// to get the condition codes.

View File

@ -79,9 +79,3 @@ void MacroAssembler::get_thread(Register thread) {
if (thread != rax) popl(rax);
popl(thread);
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Identical to Sparc/Solaris code
bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
return !offset_in_first_page;
}

View File

@ -85,22 +85,3 @@ void MacroAssembler::get_thread(Register thread) {
popq(rax);
}
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Identical to Sparc/Solaris code
// Exception handler checks the nmethod's implicit null checks table
// only when this method returns false.
if (UseCompressedOops) {
// The first page after heap_base is unmapped and
// the 'offset' is equal to [heap_base + offset] for
// narrow oop implicit null checks.
uintptr_t heap_base = (uintptr_t)Universe::heap_base();
if ((uintptr_t)offset >= heap_base) {
// Normalize offset for the next check.
offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
}
}
bool offset_in_first_page = 0 <= offset && offset < os::vm_page_size();
return !offset_in_first_page;
}

View File

@ -58,7 +58,3 @@ void MacroAssembler::get_thread(Register thread) {
"Thread Pointer Offset has not been initialized");
movl(thread, Address(thread, ThreadLocalStorage::get_thread_ptr_offset()));
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
return offset < 0 || (int)os::vm_page_size() <= offset;
}

View File

@ -65,19 +65,3 @@ void MacroAssembler::get_thread(Register thread) {
popq(rax);
}
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Exception handler checks the nmethod's implicit null checks table
// only when this method returns false.
if (UseCompressedOops) {
// The first page after heap_base is unmapped and
// the 'offset' is equal to [heap_base + offset] for
// narrow oop implicit null checks.
uintptr_t heap_base = (uintptr_t)Universe::heap_base();
if ((uintptr_t)offset >= heap_base) {
// Normalize offset for the next check.
offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
}
}
return offset < 0 || os::vm_page_size() <= offset;
}

View File

@ -246,6 +246,24 @@ void AbstractAssembler::block_comment(const char* comment) {
}
}
bool MacroAssembler::needs_explicit_null_check(intptr_t offset) {
// Exception handler checks the nmethod's implicit null checks table
// only when this method returns false.
#ifndef SPARC
// Sparc does not have based addressing
if (UseCompressedOops) {
// The first page after heap_base is unmapped and
// the 'offset' is equal to [heap_base + offset] for
// narrow oop implicit null checks.
uintptr_t heap_base = (uintptr_t)Universe::heap_base();
if ((uintptr_t)offset >= heap_base) {
// Normalize offset for the next check.
offset = (intptr_t)(pointer_delta((void*)offset, (void*)heap_base, 1));
}
}
#endif // SPARC
return offset < 0 || os::vm_page_size() <= offset;
}
#ifndef PRODUCT
void Label::print_instructions(MacroAssembler* masm) const {

View File

@ -61,6 +61,8 @@ ParMarkBitMap::initialize(MemRegion covered_region)
if (_virtual_space != NULL) {
delete _virtual_space;
_virtual_space = NULL;
// Release memory reserved in the space.
rs.release();
}
return false;
}

View File

@ -108,8 +108,8 @@ jint ParallelScavengeHeap::initialize() {
// size than is needed or wanted for the perm gen. Use the "compound
// alignment" ReservedSpace ctor to avoid having to use the same page size for
// all gens.
ReservedSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size,
og_align);
ReservedHeapSpace heap_rs(pg_max_size, pg_align, og_max_size + yg_max_size,
og_align);
os::trace_page_sizes("ps perm", pg_min_size, pg_max_size, pg_page_sz,
heap_rs.base(), pg_max_size);
os::trace_page_sizes("ps main", og_min_size + yg_min_size,

View File

@ -422,6 +422,8 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size)
return vspace;
}
delete vspace;
// Release memory reserved in the space.
rs.release();
}
return 0;

View File

@ -71,13 +71,8 @@ bool PSVirtualSpace::contains(void* p) const {
void PSVirtualSpace::release() {
DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
if (reserved_low_addr() != NULL) {
if (special()) {
os::release_memory_special(reserved_low_addr(), reserved_size());
} else {
(void)os::release_memory(reserved_low_addr(), reserved_size());
}
}
// This may not release memory it didn't reserve.
// Use rs.release() to release the underlying memory instead.
_reserved_low_addr = _reserved_high_addr = NULL;
_committed_low_addr = _committed_high_addr = NULL;
_special = false;

View File

@ -222,8 +222,8 @@ char* GenCollectedHeap::allocate(size_t alignment,
*_total_reserved = total_reserved;
*_n_covered_regions = n_covered_regions;
*heap_rs = ReservedSpace(total_reserved, alignment,
UseLargePages, heap_address);
*heap_rs = ReservedHeapSpace(total_reserved, alignment,
UseLargePages, heap_address);
return heap_address;
}

View File

@ -2173,8 +2173,7 @@ static char* get_bad_address() {
size_t size = os::vm_allocation_granularity();
bad_address = os::reserve_memory(size);
if (bad_address != NULL) {
os::commit_memory(bad_address, size);
os::protect_memory(bad_address, size);
os::protect_memory(bad_address, size, os::MEM_PROT_READ);
}
}
return bad_address;

View File

@ -1176,8 +1176,7 @@ void Arguments::set_ergonomics_flags() {
// by ergonomics.
if (MaxHeapSize <= max_heap_for_compressed_oops()) {
if (FLAG_IS_DEFAULT(UseCompressedOops)) {
// Leave compressed oops off by default. Uncomment
// the following line to return it to default status.
// Turn off until bug is fixed.
// FLAG_SET_ERGO(bool, UseCompressedOops, true);
}
} else {

View File

@ -922,8 +922,9 @@ void os::serialize_thread_states() {
// time and expensive page trap spinning, 'SerializePageLock' is used to block
// the mutator thread if such case is encountered. See bug 6546278 for details.
Thread::muxAcquire(&SerializePageLock, "serialize_thread_states");
os::protect_memory( (char *)os::get_memory_serialize_page(), os::vm_page_size() );
os::unguard_memory( (char *)os::get_memory_serialize_page(), os::vm_page_size() );
os::protect_memory((char *)os::get_memory_serialize_page(),
os::vm_page_size(), MEM_PROT_READ, /*is_committed*/true );
os::unguard_memory((char *)os::get_memory_serialize_page(), os::vm_page_size());
Thread::muxRelease(&SerializePageLock);
}

View File

@ -193,7 +193,11 @@ class os: AllStatic {
static bool commit_memory(char* addr, size_t size, size_t alignment_hint);
static bool uncommit_memory(char* addr, size_t bytes);
static bool release_memory(char* addr, size_t bytes);
static bool protect_memory(char* addr, size_t bytes);
enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX };
static bool protect_memory(char* addr, size_t bytes, ProtType prot,
bool is_committed = false);
static bool guard_memory(char* addr, size_t bytes);
static bool unguard_memory(char* addr, size_t bytes);
static char* map_memory(int fd, const char* file_name, size_t file_offset,

View File

@ -28,12 +28,15 @@
// ReservedSpace
ReservedSpace::ReservedSpace(size_t size) {
initialize(size, 0, false, NULL);
initialize(size, 0, false, NULL, 0);
}
ReservedSpace::ReservedSpace(size_t size, size_t alignment,
bool large, char* requested_address) {
initialize(size, alignment, large, requested_address);
bool large,
char* requested_address,
const size_t noaccess_prefix) {
initialize(size+noaccess_prefix, alignment, large, requested_address,
noaccess_prefix);
}
char *
@ -105,7 +108,8 @@ char* ReservedSpace::reserve_and_align(const size_t reserve_size,
ReservedSpace::ReservedSpace(const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
const size_t suffix_align)
const size_t suffix_align,
const size_t noaccess_prefix)
{
assert(prefix_size != 0, "sanity");
assert(prefix_align != 0, "sanity");
@ -118,12 +122,16 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
assert((suffix_align & prefix_align - 1) == 0,
"suffix_align not divisible by prefix_align");
// Add in noaccess_prefix to prefix_size;
const size_t adjusted_prefix_size = prefix_size + noaccess_prefix;
const size_t size = adjusted_prefix_size + suffix_size;
// On systems where the entire region has to be reserved and committed up
// front, the compound alignment normally done by this method is unnecessary.
const bool try_reserve_special = UseLargePages &&
prefix_align == os::large_page_size();
if (!os::can_commit_large_page_memory() && try_reserve_special) {
initialize(prefix_size + suffix_size, prefix_align, true);
initialize(size, prefix_align, true, NULL, noaccess_prefix);
return;
}
@ -131,15 +139,19 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
_size = 0;
_alignment = 0;
_special = false;
_noaccess_prefix = 0;
// Assert that if noaccess_prefix is used, it is the same as prefix_align.
assert(noaccess_prefix == 0 ||
noaccess_prefix == prefix_align, "noaccess prefix wrong");
// Optimistically try to reserve the exact size needed.
const size_t size = prefix_size + suffix_size;
char* addr = os::reserve_memory(size, NULL, prefix_align);
if (addr == NULL) return;
// Check whether the result has the needed alignment (unlikely unless
// prefix_align == suffix_align).
const size_t ofs = size_t(addr) + prefix_size & suffix_align - 1;
const size_t ofs = size_t(addr) + adjusted_prefix_size & suffix_align - 1;
if (ofs != 0) {
// Wrong alignment. Release, allocate more space and do manual alignment.
//
@ -153,11 +165,11 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
}
const size_t extra = MAX2(ofs, suffix_align - ofs);
addr = reserve_and_align(size + extra, prefix_size, prefix_align,
addr = reserve_and_align(size + extra, adjusted_prefix_size, prefix_align,
suffix_size, suffix_align);
if (addr == NULL) {
// Try an even larger region. If this fails, address space is exhausted.
addr = reserve_and_align(size + suffix_align, prefix_size,
addr = reserve_and_align(size + suffix_align, adjusted_prefix_size,
prefix_align, suffix_size, suffix_align);
}
}
@ -165,10 +177,12 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
_base = addr;
_size = size;
_alignment = prefix_align;
_noaccess_prefix = noaccess_prefix;
}
void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
char* requested_address) {
char* requested_address,
const size_t noaccess_prefix) {
const size_t granularity = os::vm_allocation_granularity();
assert((size & granularity - 1) == 0,
"size not aligned to os::vm_allocation_granularity()");
@ -181,6 +195,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
_size = 0;
_special = false;
_alignment = 0;
_noaccess_prefix = 0;
if (size == 0) {
return;
}
@ -220,7 +235,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
// important. If available space is not detected, return NULL.
if (requested_address != 0) {
base = os::attempt_reserve_memory_at(size, requested_address);
base = os::attempt_reserve_memory_at(size,
requested_address-noaccess_prefix);
} else {
base = os::reserve_memory(size, NULL, alignment);
}
@ -259,6 +275,11 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
_base = base;
_size = size;
_alignment = MAX2(alignment, (size_t) os::vm_page_size());
_noaccess_prefix = noaccess_prefix;
// Assert that if noaccess_prefix is used, it is the same as alignment.
assert(noaccess_prefix == 0 ||
noaccess_prefix == _alignment, "noaccess prefix wrong");
assert(markOopDesc::encode_pointer_as_mark(_base)->decode_pointer() == _base,
"area must be distinguisable from marks for mark-sweep");
@ -274,6 +295,7 @@ ReservedSpace::ReservedSpace(char* base, size_t size, size_t alignment,
_base = base;
_size = size;
_alignment = alignment;
_noaccess_prefix = 0;
_special = special;
}
@ -320,17 +342,58 @@ size_t ReservedSpace::allocation_align_size_down(size_t size) {
void ReservedSpace::release() {
if (is_reserved()) {
char *real_base = _base - _noaccess_prefix;
const size_t real_size = _size + _noaccess_prefix;
if (special()) {
os::release_memory_special(_base, _size);
os::release_memory_special(real_base, real_size);
} else{
os::release_memory(_base, _size);
os::release_memory(real_base, real_size);
}
_base = NULL;
_size = 0;
_noaccess_prefix = 0;
_special = false;
}
}
void ReservedSpace::protect_noaccess_prefix(const size_t size) {
// If there is noaccess prefix, return.
if (_noaccess_prefix == 0) return;
assert(_noaccess_prefix >= (size_t)os::vm_page_size(),
"must be at least page size big");
// Protect memory at the base of the allocated region.
// If special, the page was committed (only matters on windows)
if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE,
_special)) {
fatal("cannot protect protection page");
}
_base += _noaccess_prefix;
_size -= _noaccess_prefix;
assert((size == _size) && ((uintptr_t)_base % _alignment == 0),
"must be exactly of required size and alignment");
}
ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment,
bool large, char* requested_address) :
ReservedSpace(size, alignment, large,
requested_address,
UseCompressedOops ? lcm(os::vm_page_size(), alignment) : 0) {
// Only reserved space for the java heap should have a noaccess_prefix
// if using compressed oops.
protect_noaccess_prefix(size);
}
ReservedHeapSpace::ReservedHeapSpace(const size_t prefix_size,
const size_t prefix_align,
const size_t suffix_size,
const size_t suffix_align) :
ReservedSpace(prefix_size, prefix_align, suffix_size, suffix_align,
UseCompressedOops ? lcm(os::vm_page_size(), prefix_align) : 0) {
protect_noaccess_prefix(prefix_size+suffix_size);
}
// VirtualSpace
@ -348,6 +411,7 @@ VirtualSpace::VirtualSpace() {
_lower_alignment = 0;
_middle_alignment = 0;
_upper_alignment = 0;
_special = false;
}
@ -402,7 +466,8 @@ VirtualSpace::~VirtualSpace() {
void VirtualSpace::release() {
(void)os::release_memory(low_boundary(), reserved_size());
// This does not release memory it never reserved.
// Caller must release via rs.release();
_low_boundary = NULL;
_high_boundary = NULL;
_low = NULL;

View File

@ -29,13 +29,15 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC {
private:
char* _base;
size_t _size;
size_t _noaccess_prefix;
size_t _alignment;
bool _special;
// ReservedSpace
ReservedSpace(char* base, size_t size, size_t alignment, bool special);
void initialize(size_t size, size_t alignment, bool large,
char* requested_address = NULL);
char* requested_address,
const size_t noaccess_prefix);
// Release parts of an already-reserved memory region [addr, addr + len) to
// get a new region that has "compound alignment." Return the start of the
@ -59,13 +61,19 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC {
const size_t suffix_size,
const size_t suffix_align);
protected:
// Create protection page at the beginning of the space.
void protect_noaccess_prefix(const size_t size);
public:
// Constructor
ReservedSpace(size_t size);
ReservedSpace(size_t size, size_t alignment, bool large,
char* requested_address = NULL);
char* requested_address = NULL,
const size_t noaccess_prefix = 0);
ReservedSpace(const size_t prefix_size, const size_t prefix_align,
const size_t suffix_size, const size_t suffix_align);
const size_t suffix_size, const size_t suffix_align,
const size_t noaccess_prefix);
// Accessors
char* base() const { return _base; }
@ -73,6 +81,8 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC {
size_t alignment() const { return _alignment; }
bool special() const { return _special; }
size_t noaccess_prefix() const { return _noaccess_prefix; }
bool is_reserved() const { return _base != NULL; }
void release();
@ -104,6 +114,16 @@ ReservedSpace ReservedSpace::last_part(size_t partition_size)
return last_part(partition_size, alignment());
}
// Class encapsulating behavior specific of memory space reserved for Java heap
class ReservedHeapSpace : public ReservedSpace {
public:
// Constructor
ReservedHeapSpace(size_t size, size_t forced_base_alignment,
bool large, char* requested_address);
ReservedHeapSpace(const size_t prefix_size, const size_t prefix_align,
const size_t suffix_size, const size_t suffix_align);
};
// VirtualSpace is data structure for committing a previously reserved address range in smaller chunks.
class VirtualSpace VALUE_OBJ_CLASS_SPEC {

View File

@ -5,3 +5,4 @@ bafed478d67c3acf7744aaad88b9404261ea6739 jdk7-b27
b996318955c0ad8e9fa0ffb56c74f626786e863f jdk7-b28
617ee8607cfd5fd81f233f3c0b690f85084687a0 jdk7-b29
2d94a238a1641d074e6032dcdceed461d6f85d6a jdk7-b30
255d64ee287e926e8629dd80bc67690e65eeba30 jdk7-b31

View File

@ -5,3 +5,4 @@ debd37e1a422e580edb086c95d6e89199133a39c jdk7-b26
eefcd5204500a11d6aa802dca9f961cf10ab64c2 jdk7-b28
836c55713abab186e4de0c6eabd06ff008c7b8d0 jdk7-b29
7f2466f8cc7009702e548d1a763254f546024d7e jdk7-b30
f978623825364a2ad9c6f51d02fc9424a8b0bc86 jdk7-b31

View File

@ -5,3 +5,4 @@ fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26
02e4c5348592a8d7fc2cba28bc5f8e35c0e17277 jdk7-b28
e21f4266466cd1306b176aaa08b2cd8337a9be3d jdk7-b29
b6d6877c1155621a175dccd12dc14c54f938fb8b jdk7-b30
b7474b739d13bacd9972f88ac91f6350b7b0be12 jdk7-b31

View File

@ -97,9 +97,6 @@ ifeq ($(PLATFORM), windows)
/D "J2SE_FTYPE=0x1L"
RES = $(OBJDIR)/$(PGRM).res
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
else
LDOUTPUT = -o #Have a space
LDDFLAGS += -lc

View File

@ -55,9 +55,6 @@ LIBRARY = jaas_nt
EXTRA_LIBS += netapi32.lib user32.lib mpr.lib
endif #fdlibm
# code generates errors when compiled at warning level 3 and warnings are fatal
ifeq ($(ARCH_DATA_MODEL), 64)
COMPILER_WARNINGS_FATAL=false
endif # ARCH_DATA_MODEL
endif # windows
ifeq ($(PLATFORM), solaris)

View File

@ -149,10 +149,9 @@ endif # ARCH
PIC_CODE_LARGE = -fPIC
PIC_CODE_SMALL = -fpic
GLOBAL_KPIC = $(PIC_CODE_LARGE)
CFLAGS_COMMON += $(GLOBAL_KPIC) $(GCC_WARNINGS)
ifeq ($(ARCH), amd64)
CFLAGS_COMMON += $(GLOBAL_KPIC) $(GCC_WARNINGS) -pipe
else
CFLAGS_COMMON += $(GLOBAL_KPIC) $(GCC_WARNINGS)
CFLAGS_COMMON += -pipe
endif
# Linux 64bit machines use Dwarf2, which can be HUGE, have fastdebug use -g1

View File

@ -40,6 +40,9 @@
# LDLIBS (set $(EXTRA_LIBS) instead)
# LDLIBS_COMMON (set $(EXTRA_LIBS) instead)
# LINTFLAGS (set $(OTHER_LINTFLAGS) instead)
#
# Note: CPPFLAGS are used in C and C++ compiles.
#
# Get shared JDK settings
include $(JDK_MAKE_SHARED_DIR)/Defs.gmk
@ -112,6 +115,10 @@ endif
# Required with many of the source files.
# -mt Assume multi-threaded (important)
#
# The more unusual options to the Sun C compiler:
# +w Print more warnings
# +w2 Maximum warnings
#
#
# Debug flag for C and C++ compiler
@ -140,15 +147,34 @@ ifeq ($(FASTDEBUG), true)
CXXFLAGS_DEBUG_OPTION = -g0 $(CC_FASTDEBUG_OPT)
endif
CFLAGS_COMMON = -v -mt -L$(OBJDIR) -xc99=%none
CFLAGS_COMMON = -L$(OBJDIR)
# Do not allow C99 language features like declarations in code etc.
CFLAGS_COMMON += -xc99=%none
# Allow C++ comments in C code
CFLAGS_COMMON += -xCC
CFLAGS_COMMON += -errshort=tags
# Show error message tags on errors
CFLAGS_COMMON += -errshort=tags
CXXFLAGS_COMMON += -errtags=yes
# Optimization flags
CFLAGS_OPT = $(POPT)
# Debug version flags
CFLAGS_DBG = $(CFLAGS_DEBUG_OPTION)
CFLAGS_COMMON += -Xa $(CFLAGS_REQUIRED)
# Required C compiler flags
CFLAGS_COMMON += -Xa $(CFLAGS_REQUIRED)
# Maximum warnings all the time
CXXFLAGS_COMMON += +w
CFLAGS_COMMON += -v
# Assume MT behavior all the time (important)
CXXFLAGS_COMMON = -mt
CXXFLAGS_COMMON += -mt
CFLAGS_COMMON += -mt
# Assume no C++ exceptions are used
CXXFLAGS_COMMON += -features=no%except -DCC_NOEX
@ -237,8 +263,8 @@ LINTFLAGS_COMMON += $(LINT_XARCH_OPTION)
# OTHER_CFLAGS += -DPERTURBALOT
#
CPPFLAGS_COMMON = -D$(ARCH_FAMILY) -D__solaris__ -D_REENTRANT
CPPFLAGS_OPT =
CPPFLAGS_COMMON = -D__solaris__ -D$(ARCH_FAMILY)
CPPFLAGS_OPT = -DNDEBUG
CPPFLAGS_DBG = -DDEBUG
ifeq ($(ARCH_FAMILY), i586)

View File

@ -283,7 +283,7 @@ CPPFLAGS_COMMON = -DWIN32 -DIAL -D_LITTLE_ENDIAN
ifeq ($(ARCH), amd64)
CPPFLAGS_COMMON += -D_AMD64_ -Damd64
else
CPPFLAGS_COMMON += -DWIN32 -D_X86_ -Dx86
CPPFLAGS_COMMON += -D_X86_ -Dx86
endif
CPPFLAGS_COMMON += -DWIN32_LEAN_AND_MEAN
@ -292,17 +292,24 @@ CPPFLAGS_COMMON += -DWIN32_LEAN_AND_MEAN
#
CFLAGS_COMMON += -Fd$(OBJDIR)/$(basename $(@F)).pdb -Fm$(OBJDIR)/$(basename $(@F)).map
#
# Use -wdNNNN to disable warning NNNN.
# C4800 is a warning about bool performance casts (can't make go away)
#
COMPILER_WARNINGS_TO_IGNORE = 4800
CFLAGS_COMMON += $(COMPILER_WARNINGS_TO_IGNORE:%=-wd%)
#
# Add warnings and extra on 64bit issues
#
ifeq ($(ARCH_DATA_MODEL), 64)
CFLAGS_COMMON += -Wp64
endif
CFLAGS_COMMON += -W$(COMPILER_WARNING_LEVEL)
#
# Treat compiler warnings as errors, if requested
#
CFLAGS_COMMON += -W$(COMPILER_WARNING_LEVEL)
ifeq ($(COMPILER_WARNINGS_FATAL),true)
CFLAGS_COMMON += -WX
endif
@ -352,17 +359,9 @@ else
# BUILD_WIN_SA=1
# on the make command.
ifdef BUILD_WIN_SA
ifeq ($(ARCH), amd64)
INCLUDE_SA = true
else
INCLUDE_SA = true
endif
INCLUDE_SA = true
else
ifeq ($(ARCH), amd64)
INCLUDE_SA = false
else
INCLUDE_SA = false
endif
INCLUDE_SA = false
endif
endif
@ -404,7 +403,6 @@ ifdef JDK_UPDATE_VERSION
else
JDK_UPDATE_VER := 0
endif
JDK_VER = $(JDK_MINOR_VERSION),$(JDK_MICRO_VERSION),$(JDK_UPDATE_VER),$(COOKED_BUILD_NUMBER)
RC_FLAGS = /l 0x409 /r
@ -414,15 +412,23 @@ else
RC_FLAGS += $(MS_RC_DEBUG_OPTION)
endif
ifndef COPYRIGHT_YEAR
COPYRIGHT_YEAR = 2007
endif
# Values for the RC variables defined in RC_FLAGS
JDK_RC_BUILD_ID = $(FULL_VERSION)
JDK_RC_COMPANY = $(COMPANY_NAME)
JDK_RC_COMPONENT = $(PRODUCT_NAME) $(JDK_RC_PLATFORM_NAME) binary
JDK_RC_VER = \
$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VER).$(COOKED_BUILD_NUMBER)
JDK_RC_COPYRIGHT = Copyright \xA9 $(COPYRIGHT_YEAR)
JDK_RC_NAME = \
$(PRODUCT_NAME) $(JDK_RC_PLATFORM_NAME) $(JDK_MINOR_VERSION) $(JDK_UPDATE_META_TAG)
JDK_RC_FVER = \
$(JDK_MINOR_VERSION),$(JDK_MICRO_VERSION),$(JDK_UPDATE_VER),$(COOKED_BUILD_NUMBER)
# J2SE name required here
RC_FLAGS += -d "J2SE_BUILD_ID=$(FULL_VERSION)" \
-d "J2SE_COMPANY=$(COMPANY_NAME)" \
-d "J2SE_COMPONENT=$(PRODUCT_NAME) Platform SE binary" \
-d "J2SE_VER=$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VER).$(COOKED_BUILD_NUMBER)" \
-d "J2SE_COPYRIGHT=Copyright \xA9 $(COPYRIGHT_YEAR)" \
-d "J2SE_NAME=$(PRODUCT_NAME) Platform SE $(JDK_MINOR_VERSION) $(JDK_UPDATE_META_TAG)" \
-d "J2SE_FVER=$(JDK_VER)"
RC_FLAGS += -d "J2SE_BUILD_ID=$(JDK_RC_BUILD_ID)" \
-d "J2SE_COMPANY=$(JDK_RC_COMPANY)" \
-d "J2SE_COMPONENT=$(JDK_RC_COMPONENT)" \
-d "J2SE_VER=$(JDK_RC_VER)" \
-d "J2SE_COPYRIGHT=$(JDK_RC_COPYRIGHT)" \
-d "J2SE_NAME=$(JDK_RC_NAME)" \
-d "J2SE_FVER=$(JDK_RC_FVER)"

View File

@ -703,7 +703,7 @@ endif
ifdef ALT_COPYRIGHT_YEAR
COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR)
else
COPYRIGHT_YEAR = $(shell $(DATE) '+%Y')
COPYRIGHT_YEAR := $(shell $(DATE) '+%Y')
endif
# Install of imported file (JDK_IMPORT_PATH, or some other external location)

View File

@ -73,23 +73,18 @@ ifeq ($(PLATFORM), linux)
REQUIRED_CC_VER = 4.0
REQUIRED_GCC_VER = 4.0.*
else
ifeq ($(ARCH_DATA_MODEL), 32)
# i586
REQUIRED_CC_VER = 3.2
REQUIRED_GCC_VER = 3.2.1*
REQUIRED_GCC_VER_INT = 3.2.1-7a
else
ifeq ($(ARCH), amd64)
# amd64
REQUIRED_CC_VER = 3.2
REQUIRED_GCC_VER = 3.2.*
endif
ifeq ($(ARCH), ia64)
# ia64
REQUIRED_CC_VER = 3.2
REQUIRED_GCC_VER = 2.9[56789].*
endif
endif
ifeq ($(ARCH_DATA_MODEL), 32)
REQUIRED_GCC_VER = 3.2.1*
REQUIRED_GCC_VER_INT = 3.2.1-7a
else
ifeq ($(ARCH), amd64)
REQUIRED_GCC_VER = 3.2.*
endif
ifeq ($(ARCH), ia64)
REQUIRED_GCC_VER = 2.9[56789].*
endif
endif
endif
# Option used to create a shared library
SHARED_LIBRARY_FLAG = -shared -mimpure-text

View File

@ -107,7 +107,10 @@ JAVACFLAGS =
ifeq ($(DEBUG_CLASSFILES),true)
JAVACFLAGS += -g
endif
ifeq ($(COMPILER_WARNINGS_FATAL), true)
ifeq ($(JAVAC_MAX_WARNINGS), true)
JAVACFLAGS += -Xlint:all
endif
ifeq ($(JAVAC_WARNINGS_FATAL), true)
JAVACFLAGS += -Werror
endif
@ -180,7 +183,10 @@ endif
# The javac options supplied to the boot javac is limited. This compiler
# should only be used to build the 'make/tools' sources, which are not
# class files that end up in the classes directory.
ifeq ($(COMPILER_WARNINGS_FATAL), true)
ifeq ($(JAVAC_MAX_WARNINGS), true)
BOOT_JAVACFLAGS += -Xlint:all
endif
ifeq ($(JAVAC_WARNINGS_FATAL), true)
BOOT_JAVACFLAGS += -Werror
endif
BOOT_JAVACFLAGS += -encoding ascii

View File

@ -188,16 +188,18 @@ ifndef MILESTONE
endif
# Default names
LAUNCHER_NAME = java
PRODUCT_NAME = Java(TM)
PRODUCT_SUFFIX = SE Runtime Environment
COMPANY_NAME = Sun Microsystems, Inc.
ifdef OPENJDK
LAUNCHER_NAME = openjdk
PRODUCT_NAME = OpenJDK
PRODUCT_SUFFIX = Runtime Environment
COMPANY_NAME =
JDK_RC_PLATFORM_NAME = Platform
COMPANY_NAME = N/A
else
LAUNCHER_NAME = java
PRODUCT_NAME = Java(TM)
PRODUCT_SUFFIX = SE Runtime Environment
JDK_RC_PLATFORM_NAME = Platform SE
COMPANY_NAME = Sun Microsystems, Inc.
endif
RUNTIME_NAME = $(PRODUCT_NAME) $(PRODUCT_SUFFIX)

View File

@ -373,34 +373,40 @@ ifeq ($(PLATFORM), windows)
REQUIRED_DXSDK_VER = 0x0700
OS_VENDOR = Microsoft
# How much RAM does this machine have:
ifeq ($(USING_CYGWIN),true)
# CYGWIN has the 'free' utility
_MB_OF_MEMORY := \
$(shell free -m | grep Mem: | awk '{print $$2;}' )
else
# Windows 2000 has the mem utility, but two memory areas
# extended memory is what is beyond 1024M
_B_OF_EXT_MEMORY := \
$(shell mem 2> $(DEV_NULL) | grep 'total contiguous extended memory' | awk '{print $$1;}')
ifeq ($(_B_OF_EXT_MEMORY),)
_B_OF_MEMORY := \
$(shell mem 2> $(DEV_NULL) | grep 'total conventional memory' | awk '{print $$1;}')
else
_B_OF_MEMORY := \
$(shell expr 1048576 '+' $(_B_OF_EXT_MEMORY) 2> $(DEV_NULL))
endif
ifeq ($(_B_OF_MEMORY),)
# Windows 2003 has the systeminfo utility use it if mem doesn't work
ifeq ($(JDK_HAS_MEM_INFO),)
ifeq ($(USING_CYGWIN),true)
# CYGWIN has the 'free' utility
_MB_OF_MEMORY := \
$(shell systeminfo 2> $(DEV_NULL) | grep 'Total Physical Memory:' | awk '{print $$4;}' | sed -e 's@,@@')
$(shell free -m | grep Mem: | awk '{print $$2;}' )
else
_MB_OF_MEMORY := $(shell expr $(_B_OF_MEMORY) '/' 1024 2> $(DEV_NULL))
# Windows 2000 has the mem utility, but two memory areas
# extended memory is what is beyond 1024M
_B_OF_EXT_MEMORY := \
$(shell mem 2> $(DEV_NULL) | \
grep 'total contiguous extended memory' | awk '{print $$1;}')
ifeq ($(_B_OF_EXT_MEMORY),)
_B_OF_MEMORY := \
$(shell mem 2> $(DEV_NULL) | \
grep 'total conventional memory' | awk '{print $$1;}')
else
_B_OF_MEMORY := \
$(shell expr 1048576 '+' $(_B_OF_EXT_MEMORY) 2> $(DEV_NULL))
endif
ifeq ($(_B_OF_MEMORY),)
# Windows 2003 has the systeminfo utility use it if mem doesn't work
_MB_OF_MEMORY := \
$(shell systeminfo 2> $(DEV_NULL) | \
grep 'Total Physical Memory:' | \
awk '{print $$4;}' | sed -e 's@,@@')
else
_MB_OF_MEMORY := $(shell expr $(_B_OF_MEMORY) '/' 1024 2> $(DEV_NULL))
endif
endif
ifeq ($(shell expr $(_MB_OF_MEMORY) '+' 0 2> $(DEV_NULL)), $(_MB_OF_MEMORY))
MB_OF_MEMORY := $(_MB_OF_MEMORY)
else
MB_OF_MEMORY := 512
endif
endif
ifeq ($(shell expr $(_MB_OF_MEMORY) '+' 0 2> $(DEV_NULL)), $(_MB_OF_MEMORY))
MB_OF_MEMORY := $(_MB_OF_MEMORY)
else
MB_OF_MEMORY := 512
endif
endif
@ -446,30 +452,38 @@ endif
# system swapping during the build.
# If we don't know, assume 512. Subtract 128 from MB for VM MAX.
# Don't set VM max over 1024-128=896.
ifneq ($(MB_OF_MEMORY),)
LOW_MEMORY_MACHINE := $(shell \
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
echo "true"; \
else \
echo "false"; \
fi)
MAX_VM_MEMORY := $(shell \
if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
expr $(MB_OF_MEMORY) '-' 128 2> $(DEV_NULL) ; \
else \
echo "896"; \
fi)
MIN_VM_MEMORY := $(shell \
if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
expr $(MAX_VM_MEMORY) '-' 8 2> $(DEV_NULL) ; \
else \
echo "128"; \
fi)
else
MB_OF_MEMORY := unknown
LOW_MEMORY_MACHINE := true
MAX_VM_MEMORY := 384
MIN_VM_MEMORY := 128
ifeq ($(JDK_HAS_MEM_INFO),)
JDK_HAS_MEM_INFO=true
export JDK_HAS_MEM_INFO
ifneq ($(MB_OF_MEMORY),)
LOW_MEMORY_MACHINE := $(shell \
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
echo "true"; \
else \
echo "false"; \
fi)
MAX_VM_MEMORY := $(shell \
if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
expr $(MB_OF_MEMORY) '-' 128 2> $(DEV_NULL) ; \
else \
echo "896"; \
fi)
MIN_VM_MEMORY := $(shell \
if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
expr $(MAX_VM_MEMORY) '-' 8 2> $(DEV_NULL) ; \
else \
echo "128"; \
fi)
else
MB_OF_MEMORY := unknown
LOW_MEMORY_MACHINE := true
MAX_VM_MEMORY := 384
MIN_VM_MEMORY := 128
endif
export MB_OF_MEMORY
export LOW_MEMORY_MACHINE
export MAX_VM_MEMORY
export MIN_VM_MEMORY
endif
# If blanks in the username, use the first 4 words and pack them together

View File

@ -46,8 +46,6 @@ ifeq ($(PLATFORM),windows)
_OPT = $(CC_NO_OPT)
OTHER_CFLAGS =
CPPFLAGS_DBG += -DLOGGING
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
#

View File

@ -37,8 +37,6 @@ include $(BUILDDIR)/common/Defs.gmk
# windows compiler flags
ifeq ($(PLATFORM),windows)
CPPFLAGS_DBG += -DLOGGING
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
FILES_c = \

View File

@ -37,8 +37,6 @@ include $(BUILDDIR)/common/Defs.gmk
# windows compiler flags
ifeq ($(PLATFORM),windows)
OTHER_CFLAGS =
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
# build directly into BINDIR...
LIB_LOCATION = $(BINDIR)
# Exported functions

View File

@ -47,11 +47,6 @@ FILES_c = java_crw_demo.c
OTHER_INCLUDES = -I$(SRCDIR)
#
# This removes all asserts in the optimized version
#
CPPFLAGS_OPT += -DNDEBUG
#
# Library to compile.
#

View File

@ -91,11 +91,6 @@ endif
#
INIT += $(LIBDIR)/jvm.hprof.txt
#
# This removes all asserts in the optimized version
#
CPPFLAGS_OPT += -DNDEBUG
#
# This puts logging code in
#

View File

@ -115,9 +115,6 @@ ifeq ($(PLATFORM), windows)
-export:JLI_ManifestIterate \
-export:JLI_SetTraceLauncher
# Files from zlib built here do not compile with warning level 3
# if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
OTHER_INCLUDES += -I$(LAUNCHER_SHARE_SRC)

View File

@ -94,8 +94,6 @@ include $(BUILDDIR)/common/Library.gmk
ifeq ($(PLATFORM), windows)
OTHER_LDLIBS = ws2_32.lib $(JVMLIB)
# Will not compile at warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
else
OTHER_LDLIBS = $(LIBSOCKET) -lnsl -ldl $(JVMLIB)
endif

View File

@ -134,7 +134,6 @@ ifeq ($(PLATFORM),windows)
$(OBJDIR)/../../../java.lang/java/$(OBJDIRNAME)/FileDescriptor_md.obj
endif
ifeq ($(PLATFORM), linux)
COMPILER_WARNINGS_FATAL=true
OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl
endif
ifeq ($(PLATFORM), solaris)

View File

@ -52,11 +52,6 @@ FILES_c = \
OTHER_INCLUDES = -I$(SRCDIR) -I$(PSRCDIR)
#
# This removes all asserts in the optimized version
#
CPPFLAGS_OPT += -DNDEBUG
#
# Library to compile.
#

View File

@ -43,8 +43,6 @@ ifeq ($(PLATFORM), windows)
#
JAVALIB =
EXTRA_LIBS =
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
#

View File

@ -49,9 +49,6 @@ FILES_export = \
ifneq ($(PLATFORM), windows)
OTHER_CFLAGS += -DUSE_MMAP
else
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
#

View File

@ -52,11 +52,6 @@ ifneq ($(PLATFORM), windows)
OTHER_LDLIBS += -ldl
endif # PLATFORM
#
# This turns off all assert() checking in the optimized library
#
CPPFLAGS_OPT += -DNDEBUG
#
# This controls the ability to do logging in the library.
#

View File

@ -36,13 +36,6 @@ FILES_m = mapfile-vers
include $(BUILDDIR)/common/Defs.gmk
# 64-bit windows does not build at -W3 if warnings are fatal
ifeq ($(PLATFORM), windows)
ifeq ($(ARCH_DATA_MODEL), 64)
COMPILER_WARNINGS_FATAL=false
endif
endif
FILES_c = \
SharedMemoryTransport.c \
SharedMemoryConnection.c \

View File

@ -36,11 +36,6 @@ FILES_m = mapfile-vers
include $(BUILDDIR)/common/Defs.gmk
ifeq ($(PLATFORM), windows)
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
ifeq ($(PLATFORM), linux)
OTHER_LDLIBS += -lnsl $(LIBSOCKET) -lpthread
endif

View File

@ -47,8 +47,6 @@ FILES_export = \
ifeq ($(PLATFORM), windows)
# Override the default version info with our own resource file (see 5043594)
VERSIONINFO_RESOURCE = $(CLOSED_SRC)/share/native/sun/java2d/cmm/kcms/cmm.rc
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
# Rules

View File

@ -77,9 +77,6 @@ FILES_export = \
ifeq ($(PLATFORM), windows)
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
LDLIBS += user32.lib gdi32.lib $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
OTHER_CFLAGS += -DCC_NOEX

View File

@ -64,9 +64,6 @@ FILES_export = \
ifeq ($(PLATFORM), windows)
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
# t2k imports several shared methods from fontmanager.dll
LDLIBS += user32.lib $(OBJDIR)/../../../sun.font/fontmanager/$(OBJDIRNAME)/fontmanager.lib

View File

@ -69,11 +69,6 @@ ifneq ($(PLATFORM), windows)
INIT += $(ODBC_FAKE_LIBRARIES)
endif
ifeq ($(PLATFORM),windows)
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif
#
# Rules
#

View File

@ -73,10 +73,5 @@ include $(BUILDDIR)/common/Library.gmk
#
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
ifeq ($(PLATFORM), windows)
# Files built here do not compile with warning level 3 if warnings are fatal
COMPILER_WARNINGS_FATAL=false
endif # PLATFORM
CLASSES.export += java.io.InputStream

View File

@ -492,14 +492,17 @@ eventFilterRestricted_passesFilter(JNIEnv *env,
char *sourceName = 0;
jvmtiError error = JVMTI_FUNC_PTR(gdata->jvmti,GetSourceFileName)
(gdata->jvmti, clazz, &sourceName);
if (error == JVMTI_ERROR_NONE) {
if (sourceName == 0 || !patternStringMatch(sourceName, desiredNamePattern)) {
/* We have no match */
jvmtiDeallocate(sourceName);
return JNI_FALSE;
}
if (error == JVMTI_ERROR_NONE &&
sourceName != 0 &&
patternStringMatch(sourceName, desiredNamePattern)) {
// got a hit - report the event
jvmtiDeallocate(sourceName);
break;
}
// We have no match, we have no source file name,
// or we got a JVM TI error. Don't report the event.
jvmtiDeallocate(sourceName);
return JNI_FALSE;
}
break;
}

View File

@ -84,8 +84,13 @@ import com.sun.jmx.mbeanserver.MBeanInstantiator;
import com.sun.jmx.mbeanserver.Repository;
import com.sun.jmx.mbeanserver.NamedObject;
import com.sun.jmx.mbeanserver.Introspector;
import com.sun.jmx.mbeanserver.MBeanInjector;
import com.sun.jmx.mbeanserver.NotifySupport;
import com.sun.jmx.mbeanserver.Repository.RegistrationContext;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.remote.util.EnvHelp;
import javax.management.DynamicWrapperMBean;
import javax.management.NotificationBroadcasterSupport;
/**
* This is the default class for MBean manipulation on the agent side. It
@ -433,36 +438,26 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
if (instance instanceof MBeanRegistration)
preDeregisterInvoke((MBeanRegistration) instance);
repository.remove(name);
// may throw InstanceNotFoundException
final Object resource = getResource(instance);
/**
* Checks if the unregistered MBean is a ClassLoader
* If so, it removes the MBean from the default loader repository.
*/
// Unregisters the MBean from the repository.
// Returns the resource context that was used.
// The returned context does nothing for regular MBeans.
// For ClassLoader MBeans and JMXNamespace (and JMXDomain)
// MBeans - the context makes it possible to unregister these
// objects from the appropriate framework artifacts, such as
// the CLR or the dispatcher, from within the repository lock.
// In case of success, we also need to call context.done() at the
// end of this method.
//
final ResourceContext context =
unregisterFromRepository(resource, instance, name);
Object resource = getResource(instance);
if (resource instanceof ClassLoader
&& resource != server.getClass().getClassLoader()) {
final ModifiableClassLoaderRepository clr =
instantiator.getClassLoaderRepository();
if (clr != null) clr.removeClassLoader(name);
}
// ---------------------
// Send deletion event
// ---------------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"unregisterMBean", "Send delete notification of object " +
name.getCanonicalName());
}
sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
name);
if (instance instanceof MBeanRegistration)
postDeregisterInvoke((MBeanRegistration) instance);
context.done();
}
public ObjectInstance getObjectInstance(ObjectName name)
@ -939,15 +934,22 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
ObjectName logicalName = name;
logicalName = preRegister(mbean, server, name);
// preRegister returned successfully, so from this point on we
// must call postRegister(false) if there is any problem.
boolean registered = false;
boolean registerFailed = false;
ResourceContext context = null;
try {
mbean = injectResources(mbean, server, logicalName);
if (mbean instanceof MBeanRegistration) {
MBeanRegistration reg = (MBeanRegistration) mbean;
logicalName = preRegisterInvoke(reg, name, server);
if (mbean instanceof DynamicMBean2) {
try {
((DynamicMBean2) mbean).preRegister2(server, logicalName);
registerFailed = true; // until we succeed
} catch (Exception e) {
postRegisterInvoke(reg, false, false);
if (e instanceof RuntimeException)
throw (RuntimeException) e;
if (e instanceof InstanceAlreadyExistsException)
@ -960,86 +962,102 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
logicalName =
ObjectName.getInstance(nonDefaultDomain(logicalName));
}
}
checkMBeanPermission(classname, null, logicalName, "registerMBean");
checkMBeanPermission(classname, null, logicalName, "registerMBean");
final ObjectInstance result;
if (logicalName!=null) {
result = new ObjectInstance(logicalName, classname);
internal_addObject(mbean, logicalName);
} else {
if (mbean instanceof MBeanRegistration)
postRegisterInvoke((MBeanRegistration) mbean, false, true);
final RuntimeException wrapped =
new IllegalArgumentException("No object name specified");
throw new RuntimeOperationsException(wrapped,
"Exception occurred trying to register the MBean");
}
if (mbean instanceof MBeanRegistration)
postRegisterInvoke((MBeanRegistration) mbean, true, false);
/**
* Checks if the newly registered MBean is a ClassLoader
* If so, tell the ClassLoaderRepository (CLR) about it. We do
* this even if the object is a PrivateClassLoader. In that
* case, the CLR remembers the loader for use when it is
* explicitly named (e.g. as the loader in createMBean) but
* does not add it to the list that is consulted by
* ClassLoaderRepository.loadClass.
*/
final Object resource = getResource(mbean);
if (resource instanceof ClassLoader) {
final ModifiableClassLoaderRepository clr =
instantiator.getClassLoaderRepository();
if (clr == null) {
if (logicalName == null) {
final RuntimeException wrapped =
new IllegalArgumentException(
"Dynamic addition of class loaders is not supported");
new IllegalArgumentException("No object name specified");
throw new RuntimeOperationsException(wrapped,
"Exception occurred trying to register the MBean as a class loader");
"Exception occurred trying to register the MBean");
}
clr.addClassLoader(logicalName, (ClassLoader) resource);
final Object resource = getResource(mbean);
// Register the MBean with the repository.
// Returns the resource context that was used.
// The returned context does nothing for regular MBeans.
// For ClassLoader MBeans and JMXNamespace (and JMXDomain)
// MBeans - the context makes it possible to register these
// objects with the appropriate framework artifacts, such as
// the CLR or the dispatcher, from within the repository lock.
// In case of success, we also need to call context.done() at the
// end of this method.
//
context = registerWithRepository(resource, mbean, logicalName);
registerFailed = false;
registered = true;
} finally {
postRegister(mbean, registered, registerFailed);
}
return result;
context.done();
return new ObjectInstance(logicalName, classname);
}
private static ObjectName preRegisterInvoke(MBeanRegistration moi,
ObjectName name,
MBeanServer mbs)
throws InstanceAlreadyExistsException, MBeanRegistrationException {
final ObjectName newName;
private static void throwMBeanRegistrationException(Throwable t, String where)
throws MBeanRegistrationException {
try {
newName = moi.preRegister(mbs, name);
throw t;
} catch (RuntimeException e) {
throw new RuntimeMBeanException(e,
"RuntimeException thrown in preRegister method");
throw new RuntimeMBeanException(
e, "RuntimeException thrown " + where);
} catch (Error er) {
throw new RuntimeErrorException(er,
"Error thrown in preRegister method");
throw new RuntimeErrorException(er, "Error thrown " + where);
} catch (MBeanRegistrationException r) {
throw r;
} catch (Exception ex) {
throw new MBeanRegistrationException(ex,
"Exception thrown in preRegister method");
throw new MBeanRegistrationException(ex, "Exception thrown " + where);
} catch (Throwable t1) {
throw new RuntimeException(t); // neither Error nor Exception??
}
}
private static ObjectName preRegister(
DynamicMBean mbean, MBeanServer mbs, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException {
ObjectName newName = null;
try {
if (mbean instanceof MBeanRegistration)
newName = ((MBeanRegistration) mbean).preRegister(mbs, name);
} catch (Throwable t) {
throwMBeanRegistrationException(t, "in preRegister method");
}
if (newName != null) return newName;
else return name;
}
private static void postRegisterInvoke(MBeanRegistration moi,
boolean registrationDone,
boolean registerFailed) {
if (registerFailed && moi instanceof DynamicMBean2)
((DynamicMBean2) moi).registerFailed();
private static DynamicMBean injectResources(
DynamicMBean mbean, MBeanServer mbs, ObjectName name)
throws MBeanRegistrationException {
try {
moi.postRegister(registrationDone);
Object resource = getResource(mbean);
MBeanInjector.inject(resource, mbs, name);
if (MBeanInjector.injectsSendNotification(resource)) {
NotificationBroadcasterSupport nbs =
new NotificationBroadcasterSupport();
MBeanInjector.injectSendNotification(resource, nbs);
mbean = NotifySupport.wrap(mbean, nbs);
}
return mbean;
} catch (Throwable t) {
throwMBeanRegistrationException(t, "injecting @Resources");
return null; // not reached
}
}
private static void postRegister(
DynamicMBean mbean, boolean registrationDone, boolean registerFailed) {
if (registerFailed && mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).registerFailed();
try {
if (mbean instanceof MBeanRegistration)
((MBeanRegistration) mbean).postRegister(registrationDone);
} catch (RuntimeException e) {
throw new RuntimeMBeanException(e,
"RuntimeException thrown in postRegister method");
@ -1053,17 +1071,8 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
throws MBeanRegistrationException {
try {
moi.preDeregister();
} catch (RuntimeException e) {
throw new RuntimeMBeanException(e,
"RuntimeException thrown in preDeregister method");
} catch (Error er) {
throw new RuntimeErrorException(er,
"Error thrown in preDeregister method");
} catch (MBeanRegistrationException t) {
throw t;
} catch (Exception ex) {
throw new MBeanRegistrationException(ex,
"Exception thrown in preDeregister method");
} catch (Throwable t) {
throwMBeanRegistrationException(t, "in preDeregister method");
}
}
@ -1104,12 +1113,19 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
private static Object getResource(DynamicMBean mbean) {
if (mbean instanceof DynamicMBean2)
return ((DynamicMBean2) mbean).getResource();
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedObject();
else
return mbean;
}
private static ClassLoader getResourceLoader(DynamicMBean mbean) {
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
else
return mbean.getClass().getClassLoader();
}
private ObjectName nonDefaultDomain(ObjectName name) {
if (name == null || name.getDomain().length() > 0)
return name;
@ -1123,14 +1139,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
if one is supplied where it shouldn't be). */
final String completeName = domain + name;
try {
return new ObjectName(completeName);
} catch (MalformedObjectNameException e) {
final String msg =
"Unexpected default domain problem: " + completeName + ": " +
e;
throw EnvHelp.initCause(new IllegalArgumentException(msg), e);
}
return Util.newObjectName(completeName);
}
public String getDefaultDomain() {
@ -1211,7 +1220,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
NotificationListener listenerWrapper =
getListenerWrapper(listener, name, broadcaster, true);
getListenerWrapper(listener, name, instance, true);
broadcaster.addNotificationListener(listenerWrapper, filter, handback);
}
@ -1335,7 +1344,6 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
DynamicMBean instance = getMBean(name);
checkMBeanPermission(instance, null, name,
"removeNotificationListener");
Object resource = getResource(instance);
/* We could simplify the code by assigning broadcaster after
assigning listenerWrapper, but that would change the error
@ -1348,7 +1356,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
getNotificationBroadcaster(name, instance, reqClass);
NotificationListener listenerWrapper =
getListenerWrapper(listener, name, resource, false);
getListenerWrapper(listener, name, instance, false);
if (listenerWrapper == null)
throw new ListenerNotFoundException("Unknown listener");
@ -1366,8 +1374,10 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
private static <T extends NotificationBroadcaster>
T getNotificationBroadcaster(ObjectName name, Object instance,
Class<T> reqClass) {
if (instance instanceof DynamicMBean2)
instance = ((DynamicMBean2) instance).getResource();
if (reqClass.isInstance(instance))
return reqClass.cast(instance);
if (instance instanceof DynamicWrapperMBean)
instance = ((DynamicWrapperMBean) instance).getWrappedObject();
if (reqClass.isInstance(instance))
return reqClass.cast(instance);
final RuntimeException exc =
@ -1415,24 +1425,31 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
checkMBeanPermission(instance, null, name, "isInstanceOf");
try {
if (instance instanceof DynamicMBean2) {
Object resource = ((DynamicMBean2) instance).getResource();
ClassLoader loader = resource.getClass().getClassLoader();
Class<?> c = Class.forName(className, false, loader);
return c.isInstance(resource);
}
Object resource = getResource(instance);
final String cn = getClassName(instance);
if (cn.equals(className))
final String resourceClassName =
(resource instanceof DynamicMBean) ?
getClassName((DynamicMBean) resource) :
resource.getClass().getName();
if (resourceClassName.equals(className))
return true;
final ClassLoader cl = instance.getClass().getClassLoader();
final ClassLoader cl = getResourceLoader(instance);
final Class<?> classNameClass = Class.forName(className, false, cl);
if (classNameClass.isInstance(instance))
if (classNameClass.isInstance(resource))
return true;
final Class<?> instanceClass = Class.forName(cn, false, cl);
return classNameClass.isAssignableFrom(instanceClass);
// Ensure that isInstanceOf(NotificationEmitter) is true when
// the MBean is a NotificationEmitter by virtue of a @Resource
// annotation specifying a SendNotification resource.
// This is a hack.
if (instance instanceof NotificationBroadcaster &&
classNameClass.isAssignableFrom(NotificationEmitter.class))
return true;
final Class<?> resourceClass = Class.forName(resourceClassName, false, cl);
return classNameClass.isAssignableFrom(resourceClass);
} catch (Exception x) {
/* Could be SecurityException or ClassNotFoundException */
if (MBEANSERVER_LOGGER.isLoggable(Level.FINEST)) {
@ -1457,7 +1474,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
DynamicMBean instance = getMBean(mbeanName);
checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor");
return getResource(instance).getClass().getClassLoader();
return getResourceLoader(instance);
}
/**
@ -1488,40 +1505,6 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
return (ClassLoader) resource;
}
/**
* Adds a MBean in the repository
*/
private void internal_addObject(DynamicMBean object, ObjectName logicalName)
throws InstanceAlreadyExistsException {
// ------------------------------
// ------------------------------
// Let the repository do the work.
try {
repository.addMBean(object, logicalName);
} catch (InstanceAlreadyExistsException e) {
if (object instanceof MBeanRegistration) {
postRegisterInvoke((MBeanRegistration) object, false, true);
}
throw e;
}
// ---------------------
// Send create event
// ---------------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"addObject", "Send create notification of object " +
logicalName.getCanonicalName());
}
sendNotification(MBeanServerNotification.REGISTRATION_NOTIFICATION,
logicalName ) ;
}
/**
* Sends an MBeanServerNotifications with the specified type for the
* MBean with the specified ObjectName
@ -1712,9 +1695,10 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
*/
private NotificationListener getListenerWrapper(NotificationListener l,
ObjectName name,
Object mbean,
DynamicMBean mbean,
boolean create) {
ListenerWrapper wrapper = new ListenerWrapper(l, name, mbean);
Object resource = getResource(mbean);
ListenerWrapper wrapper = new ListenerWrapper(l, name, resource);
synchronized (listenerWrappers) {
WeakReference<ListenerWrapper> ref = listenerWrappers.get(wrapper);
if (ref != null) {
@ -1758,6 +1742,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
listener.handleNotification(notification, handback);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ListenerWrapper))
return false;
@ -1774,6 +1759,7 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
*/
}
@Override
public int hashCode() {
return (System.identityHashCode(listener) ^
System.identityHashCode(mbean));
@ -1851,4 +1837,213 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
}
}
// ------------------------------------------------------------------
//
// Dealing with registration of special MBeans in the repository.
//
// ------------------------------------------------------------------
/**
* A RegistrationContext that makes it possible to perform additional
* post registration actions (or post unregistration actions) outside
* of the repository lock, once postRegister (or postDeregister) has
* been called.
* The method {@code done()} will be called in registerMBean or
* unregisterMBean, at the end.
*/
private static interface ResourceContext extends RegistrationContext {
public void done();
/** An empty ResourceContext which does nothing **/
public static final ResourceContext NONE = new ResourceContext() {
public void done() {}
public void registering() {}
public void unregistered() {}
};
}
/**
* Adds a MBean in the repository,
* sends MBeanServerNotification.REGISTRATION_NOTIFICATION,
* returns ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces. For regular MBean this method returns
* ResourceContext.NONE.
* @return a ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces.
*/
private ResourceContext registerWithRepository(
final Object resource,
final DynamicMBean object,
final ObjectName logicalName)
throws InstanceAlreadyExistsException,
MBeanRegistrationException {
// Creates a registration context, if needed.
//
final ResourceContext context =
makeResourceContextFor(resource, logicalName);
repository.addMBean(object, logicalName, context);
// May throw InstanceAlreadyExistsException
// ---------------------
// Send create event
// ---------------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"addObject", "Send create notification of object " +
logicalName.getCanonicalName());
}
sendNotification(
MBeanServerNotification.REGISTRATION_NOTIFICATION,
logicalName);
return context;
}
/**
* Removes a MBean in the repository,
* sends MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
* returns ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces, or null. For regular MBean this method returns
* ResourceContext.NONE.
*
* @return a ResourceContext for special resources such as ClassLoaders
* or JMXNamespaces.
*/
private ResourceContext unregisterFromRepository(
final Object resource,
final DynamicMBean object,
final ObjectName logicalName)
throws InstanceNotFoundException {
// Creates a registration context, if needed.
//
final ResourceContext context =
makeResourceContextFor(resource, logicalName);
repository.remove(logicalName, context);
// ---------------------
// Send deletion event
// ---------------------
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
MBEANSERVER_LOGGER.logp(Level.FINER,
DefaultMBeanServerInterceptor.class.getName(),
"unregisterMBean", "Send delete notification of object " +
logicalName.getCanonicalName());
}
sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
logicalName);
return context;
}
/**
* Registers a ClassLoader with the CLR.
* This method is called by the ResourceContext from within the
* repository lock.
* @param loader The ClassLoader.
* @param logicalName The ClassLoader MBean ObjectName.
*/
private void addClassLoader(ClassLoader loader,
final ObjectName logicalName) {
/**
* Called when the newly registered MBean is a ClassLoader
* If so, tell the ClassLoaderRepository (CLR) about it. We do
* this even if the loader is a PrivateClassLoader. In that
* case, the CLR remembers the loader for use when it is
* explicitly named (e.g. as the loader in createMBean) but
* does not add it to the list that is consulted by
* ClassLoaderRepository.loadClass.
*/
final ModifiableClassLoaderRepository clr =
instantiator.getClassLoaderRepository();
if (clr == null) {
final RuntimeException wrapped =
new IllegalArgumentException(
"Dynamic addition of class loaders" +
" is not supported");
throw new RuntimeOperationsException(wrapped,
"Exception occurred trying to register" +
" the MBean as a class loader");
}
clr.addClassLoader(logicalName, loader);
}
/**
* Unregisters a ClassLoader from the CLR.
* This method is called by the ResourceContext from within the
* repository lock.
* @param loader The ClassLoader.
* @param logicalName The ClassLoader MBean ObjectName.
*/
private void removeClassLoader(ClassLoader loader,
final ObjectName logicalName) {
/**
* Removes the MBean from the default loader repository.
*/
if (loader != server.getClass().getClassLoader()) {
final ModifiableClassLoaderRepository clr =
instantiator.getClassLoaderRepository();
if (clr != null) {
clr.removeClassLoader(logicalName);
}
}
}
/**
* Creates a ResourceContext for a ClassLoader MBean.
* The resource context makes it possible to add the ClassLoader to
* (ResourceContext.registering) or resp. remove the ClassLoader from
* (ResourceContext.unregistered) the CLR
* when the associated MBean is added to or resp. removed from the
* repository.
*
* @param loader The ClassLoader MBean being registered or
* unregistered.
* @param logicalName The name of the ClassLoader MBean.
* @return a ResourceContext that takes in charge the addition or removal
* of the loader to or from the CLR.
*/
private ResourceContext createClassLoaderContext(
final ClassLoader loader,
final ObjectName logicalName) {
return new ResourceContext() {
public void registering() {
addClassLoader(loader, logicalName);
}
public void unregistered() {
removeClassLoader(loader, logicalName);
}
public void done() {
}
};
}
/**
* Creates a ResourceContext for the given resource.
* If the resource does not need a ResourceContext, returns
* ResourceContext.NONE.
* At this time, only JMXNamespaces and ClassLoaders need a
* ResourceContext.
*
* @param resource The resource being registered or unregistered.
* @param logicalName The name of the associated MBean.
* @return
*/
private ResourceContext makeResourceContextFor(Object resource,
ObjectName logicalName) {
if (resource instanceof ClassLoader) {
return createClassLoaderContext((ClassLoader) resource,
logicalName);
}
return ResourceContext.NONE;
}
}

View File

@ -686,7 +686,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final String msg =
"Cannot convert SortedSet with non-null comparator: " +
comparator;
throw new OpenDataException(msg);
throw openDataException(msg, new IllegalArgumentException(msg));
}
}
final Object[] openArray = (Object[])
@ -800,7 +800,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final String msg =
"Cannot convert SortedMap with non-null comparator: " +
comparator;
throw new OpenDataException(msg);
throw openDataException(msg, new IllegalArgumentException(msg));
}
}
final TabularType tabularType = (TabularType) getOpenType();

View File

@ -25,7 +25,7 @@
package com.sun.jmx.mbeanserver;
import javax.management.DynamicMBean;
import javax.management.DynamicWrapperMBean;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@ -35,17 +35,7 @@ import javax.management.ObjectName;
*
* @since 1.6
*/
public interface DynamicMBean2 extends DynamicMBean {
/**
* The resource corresponding to this MBean. This is the object whose
* class name should be reflected by the MBean's
* getMBeanInfo().getClassName() for example. For a "plain"
* DynamicMBean it will be "this". For an MBean that wraps another
* object, like javax.management.StandardMBean, it will be the wrapped
* object.
*/
public Object getResource();
public interface DynamicMBean2 extends DynamicWrapperMBean {
/**
* The name of this MBean's class, as used by permission checks.
* This is typically equal to getResource().getClass().getName().

View File

@ -25,23 +25,39 @@
package com.sun.jmx.mbeanserver;
import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import javax.management.AttributeNotFoundException;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.DescriptorFields;
import javax.management.DescriptorKey;
import javax.management.DynamicMBean;
import javax.management.ImmutableDescriptor;
import javax.management.MBean;
import javax.management.MBeanInfo;
import javax.management.MXBean;
import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
@ -133,8 +149,12 @@ public class Introspector {
}
}
public static void checkCompliance(Class mbeanClass)
throws NotCompliantMBeanException {
public static void checkCompliance(Class<?> mbeanClass)
throws NotCompliantMBeanException {
// Check that @Resource is used correctly (if it used).
MBeanInjector.validate(mbeanClass);
// Is DynamicMBean?
//
if (DynamicMBean.class.isAssignableFrom(mbeanClass))
@ -157,21 +177,39 @@ public class Introspector {
} catch (NotCompliantMBeanException e) {
mxbeanException = e;
}
// Is @MBean or @MXBean class?
// In fact we find @MBean or @MXBean as a hacky variant of
// getStandardMBeanInterface or getMXBeanInterface. If we get here
// then nothing worked.
final String msg =
"MBean class " + mbeanClass.getName() + " does not implement " +
"DynamicMBean, neither follows the Standard MBean conventions (" +
mbeanException.toString() + ") nor the MXBean conventions (" +
mxbeanException.toString() + ")";
"DynamicMBean; does not follow the Standard MBean conventions (" +
mbeanException.toString() + "); does not follow the MXBean conventions (" +
mxbeanException.toString() + "); and does not have or inherit the @" +
MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() +
" annotation";
throw new NotCompliantMBeanException(msg);
}
/**
* <p>Make a DynamicMBean out of the existing MBean object. The object
* may already be a DynamicMBean, or it may be a Standard MBean or
* MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p>
* @param mbean the object to convert to a DynamicMBean.
* @param <T> a type parameter defined for implementation convenience
* (which would have to be removed if this method were part of the public
* API).
* @return the converted DynamicMBean.
* @throws NotCompliantMBeanException if {@code mbean} is not a compliant
* MBean object, including the case where it is null.
*/
public static <T> DynamicMBean makeDynamicMBean(T mbean)
throws NotCompliantMBeanException {
if (mbean == null)
throw new NotCompliantMBeanException("Null MBean object");
if (mbean instanceof DynamicMBean)
return (DynamicMBean) mbean;
final Class mbeanClass = mbean.getClass();
final Class<?> mbeanClass = mbean.getClass();
Class<? super T> c = null;
try {
c = Util.cast(getStandardMBeanInterface(mbeanClass));
@ -270,7 +308,7 @@ public class Introspector {
* Return <code>null</code> if the MBean is a DynamicMBean,
* or if no MBean interface is found.
*/
public static Class getMBeanInterface(Class baseClass) {
public static Class<?> getMBeanInterface(Class<?> baseClass) {
// Check if the given class implements the MBean interface
// or the Dynamic MBean interface
if (isDynamic(baseClass)) return null;
@ -291,10 +329,12 @@ public class Introspector {
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant Standard MBean.
*/
public static Class getStandardMBeanInterface(Class baseClass)
throws NotCompliantMBeanException {
Class current = baseClass;
Class mbeanInterface = null;
public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException {
if (baseClass.isAnnotationPresent(MBean.class))
return baseClass;
Class<? super T> current = baseClass;
Class<? super T> mbeanInterface = null;
while (current != null) {
mbeanInterface =
findMBeanInterface(current, current.getName());
@ -321,8 +361,10 @@ public class Introspector {
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant MXBean.
*/
public static Class getMXBeanInterface(Class baseClass)
public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException {
if (hasMXBeanAnnotation(baseClass))
return baseClass;
try {
return MXBeanSupport.findMXBeanInterface(baseClass);
} catch (Exception e) {
@ -345,19 +387,24 @@ public class Introspector {
* ------------------------------------------
*/
static boolean hasMXBeanAnnotation(Class<?> c) {
MXBean m = c.getAnnotation(MXBean.class);
return (m != null && m.value());
}
/**
* Try to find the MBean interface corresponding to the class aName
* - i.e. <i>aName</i>MBean, from within aClass and its superclasses.
**/
private static Class findMBeanInterface(Class aClass, String aName) {
Class current = aClass;
private static <T> Class<? super T> findMBeanInterface(
Class<T> aClass, String aName) {
Class<? super T> current = aClass;
while (current != null) {
final Class[] interfaces = current.getInterfaces();
final Class<?>[] interfaces = current.getInterfaces();
final int len = interfaces.length;
for (int i=0;i<len;i++) {
final Class inter =
implementsMBean(interfaces[i], aName);
Class<? super T> inter = Util.cast(interfaces[i]);
inter = implementsMBean(inter, aName);
if (inter != null) return inter;
}
current = current.getSuperclass();
@ -365,6 +412,48 @@ public class Introspector {
return null;
}
public static String descriptionForElement(AnnotatedElement elmt) {
if (elmt == null)
return null;
Description d = elmt.getAnnotation(Description.class);
if (d == null)
return null;
return d.value();
}
public static String descriptionForParameter(
Annotation[] parameterAnnotations) {
for (Annotation a : parameterAnnotations) {
if (a instanceof Description)
return ((Description) a).value();
}
return null;
}
public static String nameForParameter(
Annotation[] parameterAnnotations) {
for (Annotation a : parameterAnnotations) {
Class<? extends Annotation> ac = a.annotationType();
// You'd really have to go out of your way to have more than
// one @Name annotation, so we don't check for that.
if (ac.getSimpleName().equals("Name")) {
try {
Method value = ac.getMethod("value");
if (value.getReturnType() == String.class &&
value.getParameterTypes().length == 0) {
return (String) value.invoke(a);
}
} catch (Exception e) {
MBEANSERVER_LOGGER.log(
Level.WARNING,
"Unexpected exception getting @" + ac.getName(),
e);
}
}
}
return null;
}
public static Descriptor descriptorForElement(final AnnotatedElement elmt) {
if (elmt == null)
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
@ -372,41 +461,18 @@ public class Introspector {
return descriptorForAnnotations(annots);
}
public static Descriptor descriptorForAnnotation(Annotation annot) {
return descriptorForAnnotations(new Annotation[] {annot});
}
public static Descriptor descriptorForAnnotations(Annotation[] annots) {
if (annots.length == 0)
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
Map<String, Object> descriptorMap = new HashMap<String, Object>();
for (Annotation a : annots) {
Class<? extends Annotation> c = a.annotationType();
Method[] elements = c.getMethods();
for (Method element : elements) {
DescriptorKey key = element.getAnnotation(DescriptorKey.class);
if (key != null) {
String name = key.value();
Object value;
try {
value = element.invoke(a);
} catch (RuntimeException e) {
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
//
throw e;
} catch (Exception e) {
// we don't expect this
throw new UndeclaredThrowableException(e);
}
value = annotationToField(value);
Object oldValue = descriptorMap.put(name, value);
if (oldValue != null && !equals(oldValue, value)) {
final String msg =
"Inconsistent values for descriptor field " + name +
" from annotations: " + value + " :: " + oldValue;
throw new IllegalArgumentException(msg);
}
}
}
if (a instanceof DescriptorFields)
addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a);
addAnnotationFieldsToMap(descriptorMap, a);
}
if (descriptorMap.isEmpty())
@ -415,6 +481,62 @@ public class Introspector {
return new ImmutableDescriptor(descriptorMap);
}
private static void addDescriptorFieldsToMap(
Map<String, Object> descriptorMap, DescriptorFields df) {
for (String field : df.value()) {
int eq = field.indexOf('=');
if (eq < 0) {
throw new IllegalArgumentException(
"@DescriptorFields string must contain '=': " +
field);
}
String name = field.substring(0, eq);
String value = field.substring(eq + 1);
addToMap(descriptorMap, name, value);
}
}
private static void addAnnotationFieldsToMap(
Map<String, Object> descriptorMap, Annotation a) {
Class<? extends Annotation> c = a.annotationType();
Method[] elements = c.getMethods();
for (Method element : elements) {
DescriptorKey key = element.getAnnotation(DescriptorKey.class);
if (key != null) {
String name = key.value();
Object value;
try {
value = element.invoke(a);
} catch (RuntimeException e) {
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
throw e;
} catch (Exception e) {
// we don't expect this
throw new UndeclaredThrowableException(e);
}
if (!key.omitIfDefault() ||
!equals(value, element.getDefaultValue())) {
value = annotationToField(value);
addToMap(descriptorMap, name, value);
}
}
}
}
private static void addToMap(
Map<String, Object> descriptorMap, String name, Object value) {
Object oldValue = descriptorMap.put(name, value);
if (oldValue != null && !equals(oldValue, value)) {
final String msg =
"Inconsistent values for descriptor field " + name +
" from annotations: " + value + " :: " + oldValue;
throw new IllegalArgumentException(msg);
}
}
/**
* Throws a NotCompliantMBeanException or a SecurityException.
* @param notCompliant the class which was under examination
@ -473,8 +595,13 @@ public class Introspector {
// The only other possibility is that the value is another
// annotation, or that the language has evolved since this code
// was written. We don't allow for either of those currently.
// If it is indeed another annotation, then x will be a proxy
// with an unhelpful name like $Proxy2. So we extract the
// proxy's interface to use that in the exception message.
if (Proxy.isProxyClass(c))
c = c.getInterfaces()[0]; // array "can't be empty"
throw new IllegalArgumentException("Illegal type for annotation " +
"element: " + x.getClass().getName());
"element using @DescriptorKey: " + c.getName());
}
// This must be consistent with the check for duplicate field values in
@ -490,15 +617,15 @@ public class Introspector {
* @param c The interface to be tested
* @param clName The name of the class implementing this interface
*/
private static Class implementsMBean(Class c, String clName) {
private static <T> Class<? super T> implementsMBean(Class<T> c, String clName) {
String clMBeanName = clName + "MBean";
if (c.getName().equals(clMBeanName)) {
return c;
}
Class[] interfaces = c.getInterfaces();
Class<?>[] interfaces = c.getInterfaces();
for (int i = 0;i < interfaces.length; i++) {
if (interfaces[i].getName().equals(clMBeanName))
return interfaces[i];
return Util.cast(interfaces[i]);
}
return null;

View File

@ -33,6 +33,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.MBean;
import javax.management.MXBean;
import javax.management.ManagedAttribute;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
/**
@ -125,18 +129,26 @@ class MBeanAnalyzer<M> {
for (Method m : methods) {
final String name = m.getName();
final int nParams = m.getParameterTypes().length;
final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class);
final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class);
if (managedOp && managedAttr) {
throw new NotCompliantMBeanException("Method " + name +
" has both @ManagedOperation and @ManagedAttribute");
}
final M cm = introspector.mFrom(m);
String attrName = "";
if (name.startsWith("get"))
attrName = name.substring(3);
else if (name.startsWith("is")
&& m.getReturnType() == boolean.class)
attrName = name.substring(2);
if (!managedOp) {
if (name.startsWith("get"))
attrName = name.substring(3);
else if (name.startsWith("is")
&& m.getReturnType() == boolean.class)
attrName = name.substring(2);
}
if (attrName.length() != 0 && nParams == 0
&& m.getReturnType() != void.class) {
&& m.getReturnType() != void.class && !managedOp) {
// It's a getter
// Check we don't have both isX and getX
AttrMethods<M> am = attrMap.get(attrName);
@ -153,7 +165,7 @@ class MBeanAnalyzer<M> {
attrMap.put(attrName, am);
} else if (name.startsWith("set") && name.length() > 3
&& nParams == 1 &&
m.getReturnType() == void.class) {
m.getReturnType() == void.class && !managedOp) {
// It's a setter
attrName = name.substring(3);
AttrMethods<M> am = attrMap.get(attrName);
@ -166,6 +178,9 @@ class MBeanAnalyzer<M> {
}
am.setter = cm;
attrMap.put(attrName, am);
} else if (managedAttr) {
throw new NotCompliantMBeanException("Method " + name +
" has @ManagedAttribute but is not a valid getter or setter");
} else {
// It's an operation
List<M> cms = opMap.get(name);

View File

@ -0,0 +1,291 @@
/*
* Copyright 2007 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.mbeanserver;
import java.lang.ref.WeakReference;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.Resource;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import static com.sun.jmx.mbeanserver.Util.newMap;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.SendNotification;
public class MBeanInjector {
private static Class<?>[] injectedClasses = {
MBeanServer.class, ObjectName.class, SendNotification.class,
};
public static void inject(Object mbean, MBeanServer mbs, ObjectName name)
throws Exception {
ClassInjector injector = injectorForClass(mbean.getClass());
injector.inject(mbean, MBeanServer.class, mbs);
injector.inject(mbean, ObjectName.class, name);
}
public static boolean injectsSendNotification(Object mbean)
throws NotCompliantMBeanException {
ClassInjector injector = injectorForClass(mbean.getClass());
return injector.injects(SendNotification.class);
}
public static void injectSendNotification(Object mbean, SendNotification sn)
throws Exception {
ClassInjector injector = injectorForClass(mbean.getClass());
injector.inject(mbean, SendNotification.class, sn);
}
public static void validate(Class<?> c) throws NotCompliantMBeanException {
injectorForClass(c);
}
private static class ClassInjector {
private Map<Class<?>, List<Field>> fields;
private Map<Class<?>, List<Method>> methods;
ClassInjector(Class<?> c) throws NotCompliantMBeanException {
fields = newMap();
methods = newMap();
Class<?> sup = c.getSuperclass();
ClassInjector supInjector;
if (sup == null) {
supInjector = null;
} else {
supInjector = injectorForClass(sup);
fields.putAll(supInjector.fields);
methods.putAll(supInjector.methods);
}
addMembers(c);
eliminateOverriddenMethods();
// If we haven't added any new fields or methods to what we
// inherited, then we can share the parent's maps.
if (supInjector != null) {
if (fields.equals(supInjector.fields))
fields = supInjector.fields;
if (methods.equals(supInjector.methods))
methods = supInjector.methods;
}
}
boolean injects(Class<?> c) {
return (fields.get(c) != null || methods.get(c) != null);
}
<T> void inject(Object instance, Class<T> type, T resource)
throws Exception {
List<Field> fs = fields.get(type);
if (fs != null) {
for (Field f : fs)
f.set(instance, resource);
}
List<Method> ms = methods.get(type);
if (ms != null) {
for (Method m : ms) {
try {
m.invoke(instance, resource);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof Error)
throw (Error) cause;
else
throw (Exception) cause;
}
}
}
}
private void eliminateOverriddenMethods() {
/* Covariant overriding is unlikely, but it is possible that the
* parent has a @Resource method that we override with another
* @Resource method. We don't want to invoke both methods,
* because polymorphism means we would actually invoke the same
* method twice.
*/
for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) {
List<Method> list = entry.getValue();
list = MBeanAnalyzer.eliminateCovariantMethods(list);
entry.setValue(list);
}
}
/*
* Find Fields or Methods within the given Class that we can inject
* resource references into. Suppose we want to know if a Field can get
* a reference to an ObjectName. We'll accept fields like this:
*
* @Resource
* private transient ObjectName name;
*
* or like this:
*
* @Resource(type = ObjectName.class)
* private transient Object name;
*
* but not like this:
*
* @Resource
* private transient Object name;
*
* (Plain @Resource is equivalent to @Resource(type = Object.class).)
*
* We don't want to inject into everything that might possibly accept
* an ObjectName reference, because examples like the last one above
* could also accept an MBeanServer reference or any other sort of
* reference.
*
* So we accept a Field if it has a @Resource annotation and either
* (a) its type is ObjectName or a subclass and its @Resource type is
* compatible with ObjectName (e.g. it is Object); or
* (b) its type is compatible with ObjectName and its @Resource type
* is exactly ObjectName. Fields that meet these criteria will not
* meet the same criteria with respect to other types such as MBeanServer.
*
* The same logic applies mutatis mutandis to Methods such as this:
*
* @Resource
* private void setObjectName1(ObjectName name)
* @Resource(type = Object.class)
* private void setObjectName2(Object name)
*/
private void addMembers(final Class<?> c)
throws NotCompliantMBeanException {
AccessibleObject[][] memberArrays =
AccessController.doPrivileged(
new PrivilegedAction<AccessibleObject[][]>() {
public AccessibleObject[][] run() {
return new AccessibleObject[][] {
c.getDeclaredFields(), c.getDeclaredMethods()
};
}
});
for (AccessibleObject[] members : memberArrays) {
for (final AccessibleObject member : members) {
Resource res = member.getAnnotation(Resource.class);
if (res == null)
continue;
final Field field;
final Method method;
final Class<?> memberType;
final int modifiers;
if (member instanceof Field) {
field = (Field) member;
memberType = field.getType();
modifiers = field.getModifiers();
method = null;
} else {
field = null;
method = (Method) member;
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new NotCompliantMBeanException(
"@Resource method must have exactly 1 " +
"parameter: " + method);
}
if (method.getReturnType() != void.class) {
throw new NotCompliantMBeanException(
"@Resource method must return void: " +
method);
}
memberType = paramTypes[0];
modifiers = method.getModifiers();
}
if (Modifier.isStatic(modifiers)) {
throw new NotCompliantMBeanException(
"@Resource method or field cannot be static: " +
member);
}
for (Class<?> injectedClass : injectedClasses) {
Class<?>[] types = {memberType, res.type()};
boolean accept = false;
for (int i = 0; i < 2; i++) {
if (types[i] == injectedClass &&
types[1 - i].isAssignableFrom(injectedClass)) {
accept = true;
break;
}
}
if (accept) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
member.setAccessible(true);
return null;
}
});
addToMap(fields, injectedClass, field);
addToMap(methods, injectedClass, method);
}
}
}
}
}
private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
if (value == null)
return;
List<V> list = map.get(key);
if (list == null)
list = Collections.singletonList(value);
else {
if (list.size() == 1)
list = new ArrayList<V>(list);
list.add(value);
}
map.put(key, list);
}
}
private static synchronized ClassInjector injectorForClass(Class<?> c)
throws NotCompliantMBeanException {
WeakReference<ClassInjector> wr = injectorMap.get(c);
ClassInjector ci = (wr == null) ? null : wr.get();
if (ci == null) {
ci = new ClassInjector(c);
injectorMap.put(c, new WeakReference<ClassInjector>(ci));
}
return ci;
}
private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap =
new WeakHashMap<Class<?>, WeakReference<ClassInjector>>();
}

View File

@ -36,20 +36,28 @@ import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBean;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MXBean;
import javax.management.ManagedAttribute;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationInfo;
import javax.management.NotificationInfos;
import javax.management.ReflectionException;
/**
@ -153,6 +161,25 @@ abstract class MBeanIntrospector<M> {
abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
M getter, M setter) throws IntrospectionException;
final String getAttributeDescription(
String attributeName, String defaultDescription,
Method getter, Method setter) throws IntrospectionException {
String g = Introspector.descriptionForElement(getter);
String s = Introspector.descriptionForElement(setter);
if (g == null) {
if (s == null)
return defaultDescription;
else
return s;
} else if (s == null || g.equals(s)) {
return g;
} else {
throw new IntrospectionException(
"Inconsistent @Description on getter and setter for " +
"attribute " + attributeName);
}
}
/**
* Construct an MBeanOperationInfo for the given operation based on
* the M it was derived from.
@ -184,8 +211,12 @@ abstract class MBeanIntrospector<M> {
}
void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException {
if (!mbeanType.isInterface()) {
throw new NotCompliantMBeanException("Not an interface: " +
if (!mbeanType.isInterface() &&
!mbeanType.isAnnotationPresent(MBean.class) &&
!Introspector.hasMXBeanAnnotation(mbeanType)) {
throw new NotCompliantMBeanException("Not an interface and " +
"does not have @" + MBean.class.getSimpleName() +
" or @" + MXBean.class.getSimpleName() + " annotation: " +
mbeanType.getName());
}
}
@ -194,7 +225,12 @@ abstract class MBeanIntrospector<M> {
* Get the methods to be analyzed to build the MBean interface.
*/
List<Method> getMethods(final Class<?> mbeanType) throws Exception {
return Arrays.asList(mbeanType.getMethods());
if (mbeanType.isInterface())
return Arrays.asList(mbeanType.getMethods());
final List<Method> methods = newList();
getAnnotatedMethods(mbeanType, methods);
return methods;
}
final PerInterface<M> getPerInterface(Class<?> mbeanInterface)
@ -232,8 +268,11 @@ abstract class MBeanIntrospector<M> {
MBeanAnalyzer<M> analyzer) throws IntrospectionException {
final MBeanInfoMaker maker = new MBeanInfoMaker();
analyzer.visit(maker);
final String description =
final String defaultDescription =
"Information on the management interface of the MBean";
String description = Introspector.descriptionForElement(mbeanInterface);
if (description == null)
description = defaultDescription;
return maker.makeMBeanInfo(mbeanInterface, description);
}
@ -407,7 +446,15 @@ abstract class MBeanIntrospector<M> {
throws NotCompliantMBeanException {
MBeanInfo mbi =
getClassMBeanInfo(resource.getClass(), perInterface);
MBeanNotificationInfo[] notifs = findNotifications(resource);
MBeanNotificationInfo[] notifs;
try {
notifs = findNotifications(resource);
} catch (RuntimeException e) {
NotCompliantMBeanException x =
new NotCompliantMBeanException(e.getMessage());
x.initCause(e);
throw x;
}
Descriptor d = getSpecificMBeanDescriptor();
boolean anyNotifs = (notifs != null && notifs.length > 0);
if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d))
@ -460,13 +507,43 @@ abstract class MBeanIntrospector<M> {
}
}
/*
* Add to "methods" every public method that has the @ManagedAttribute
* or @ManagedOperation annotation, in the given class or any of
* its superclasses or superinterfaces.
*
* We always add superclass or superinterface methods first, so that
* the stable sort used by eliminateCovariantMethods will put the
* method from the most-derived class last. This means that we will
* see the version of the @ManagedAttribute (or ...Operation) annotation
* from that method, which might have a different description or whatever.
*/
private static void getAnnotatedMethods(Class<?> c, List<Method> methods)
throws Exception {
Class<?> sup = c.getSuperclass();
if (sup != null)
getAnnotatedMethods(sup, methods);
Class<?>[] intfs = c.getInterfaces();
for (Class<?> intf : intfs)
getAnnotatedMethods(intf, methods);
for (Method m : c.getMethods()) {
// We are careful not to add m if it is inherited from a parent
// class or interface, because duplicate methods lead to nasty
// behaviour in eliminateCovariantMethods.
if (m.getDeclaringClass() == c &&
(m.isAnnotationPresent(ManagedAttribute.class) ||
m.isAnnotationPresent(ManagedOperation.class)))
methods.add(m);
}
}
static MBeanNotificationInfo[] findNotifications(Object moi) {
if (!(moi instanceof NotificationBroadcaster))
return null;
MBeanNotificationInfo[] mbn =
((NotificationBroadcaster) moi).getNotificationInfo();
if (mbn == null || mbn.length == 0)
return null;
return findNotificationsFromAnnotations(moi.getClass());
MBeanNotificationInfo[] result =
new MBeanNotificationInfo[mbn.length];
for (int i = 0; i < mbn.length; i++) {
@ -478,11 +555,81 @@ abstract class MBeanIntrospector<M> {
return result;
}
private static MBeanNotificationInfo[] findNotificationsFromAnnotations(
Class<?> mbeanClass) {
Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass);
if (c == null)
return null;
NotificationInfo ni = c.getAnnotation(NotificationInfo.class);
NotificationInfos nis = c.getAnnotation(NotificationInfos.class);
List<NotificationInfo> list = newList();
if (ni != null)
list.add(ni);
if (nis != null)
list.addAll(Arrays.asList(nis.value()));
if (list.isEmpty())
return null;
List<MBeanNotificationInfo> mbnis = newList();
for (NotificationInfo x : list) {
// The Descriptor includes any fields explicitly specified by
// x.descriptorFields(), plus any fields from the contained
// @Description annotation.
Descriptor d = new ImmutableDescriptor(x.descriptorFields());
d = ImmutableDescriptor.union(
d, Introspector.descriptorForAnnotation(x.description()));
MBeanNotificationInfo mbni = new MBeanNotificationInfo(
x.types(), x.notificationClass().getName(),
x.description().value(), d);
mbnis.add(mbni);
}
return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]);
}
private static final Map<Class<?>, WeakReference<Class<?>>>
annotatedNotificationInfoClasses = newWeakHashMap();
private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) {
synchronized (annotatedNotificationInfoClasses) {
WeakReference<Class<?>> wr =
annotatedNotificationInfoClasses.get(baseClass);
if (wr != null)
return wr.get();
Class<?> c = null;
if (baseClass.isAnnotationPresent(NotificationInfo.class) ||
baseClass.isAnnotationPresent(NotificationInfos.class)) {
c = baseClass;
} else {
Class<?>[] intfs = baseClass.getInterfaces();
for (Class<?> intf : intfs) {
Class<?> c1 = getAnnotatedNotificationInfoClass(intf);
if (c1 != null) {
if (c != null) {
throw new IllegalArgumentException(
"Class " + baseClass.getName() + " inherits " +
"@NotificationInfo(s) from both " +
c.getName() + " and " + c1.getName());
}
c = c1;
}
}
}
// Record the result of the search. If no @NotificationInfo(s)
// were found, c is null, and we store a WeakReference(null).
// This prevents us from having to search again and fail again.
annotatedNotificationInfoClasses.put(baseClass,
new WeakReference<Class<?>>(c));
return c;
}
}
private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
Constructor[] cons = c.getConstructors();
MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
for (int i = 0; i < cons.length; i++) {
final String descr = "Public constructor of the MBean";
String descr = "Public constructor of the MBean";
Description d = cons[i].getAnnotation(Description.class);
if (d != null)
descr = d.value();
mbc[i] = new MBeanConstructorInfo(descr, cons[i]);
}
return mbc;

View File

@ -263,10 +263,14 @@ public abstract class MBeanSupport<M>
return resource.getClass().getName();
}
public final Object getResource() {
public final Object getWrappedObject() {
return resource;
}
public final ClassLoader getWrappedClassLoader() {
return resource.getClass().getClassLoader();
}
public final Class<?> getMBeanInterface() {
return perInterface.getMBeanInterface();
}

View File

@ -35,6 +35,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.WeakHashMap;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.IntrospectionException;
@ -43,6 +44,7 @@ import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
@ -180,7 +182,10 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
final boolean isWritable = (setter != null);
final boolean isIs = isReadable && getName(getter).startsWith("is");
final String description = attributeName;
final String description = getAttributeDescription(
attributeName, attributeName,
getter == null ? null : getter.getMethod(),
setter == null ? null : setter.getMethod());
final OpenType<?> openType;
final Type originalType;
@ -229,13 +234,17 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
MBeanOperationInfo getMBeanOperationInfo(String operationName,
ConvertingMethod operation) {
final Method method = operation.getMethod();
final String description = operationName;
String description = operationName;
/* Ideally this would be an empty string, but
OMBOperationInfo constructor forbids that. Also, we
could consult an annotation to get a useful
description. */
OMBOperationInfo constructor forbids that. */
Description d = method.getAnnotation(Description.class);
if (d != null)
description = d.value();
final int impact = MBeanOperationInfo.UNKNOWN;
int impact = MBeanOperationInfo.UNKNOWN;
ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
if (annot != null)
impact = annot.impact().getCode();
final OpenType<?> returnType = operation.getOpenReturnType();
final Type originalReturnType = operation.getGenericReturnType();
@ -247,8 +256,15 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
boolean openParameterTypes = true;
Annotation[][] annots = method.getParameterAnnotations();
for (int i = 0; i < paramTypes.length; i++) {
final String paramName = "p" + i;
final String paramDescription = paramName;
String paramName = Introspector.nameForParameter(annots[i]);
if (paramName == null)
paramName = "p" + i;
String paramDescription =
Introspector.descriptionForParameter(annots[i]);
if (paramDescription == null)
paramDescription = paramName;
final OpenType<?> openType = paramTypes[i];
final Type originalType = originalParamTypes[i];
Descriptor descriptor =

View File

@ -161,7 +161,7 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
synchronized (lock) {
this.mxbeanLookup = MXBeanLookup.Plain.lookupFor(server);
this.mxbeanLookup.addReference(name, getResource());
this.mxbeanLookup.addReference(name, getWrappedObject());
this.objectName = name;
}
}
@ -170,7 +170,7 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
public void unregister() {
synchronized (lock) {
if (mxbeanLookup != null) {
if (mxbeanLookup.removeReference(objectName, getResource()))
if (mxbeanLookup.removeReference(objectName, getWrappedObject()))
objectName = null;
}
// XXX: need to revisit the whole register/unregister logic in

View File

@ -0,0 +1,186 @@
/*
* Copyright 2007 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.mbeanserver;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.DynamicWrapperMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;
/**
* Create wrappers for DynamicMBean that implement NotificationEmitter
* and SendNotification.
*/
public class NotifySupport
implements DynamicMBean2, NotificationEmitter, MBeanRegistration {
private final DynamicMBean mbean;
private final NotificationBroadcasterSupport nbs;
public static DynamicMBean wrap(
DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
return new NotifySupport(mbean, nbs);
}
private NotifySupport(DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
this.mbean = mbean;
this.nbs = nbs;
}
public static NotificationBroadcasterSupport getNB(DynamicMBean mbean) {
if (mbean instanceof NotifySupport)
return ((NotifySupport) mbean).nbs;
else
return null;
}
public String getClassName() {
if (mbean instanceof DynamicMBean2)
return ((DynamicMBean2) mbean).getClassName();
Object w = mbean;
if (w instanceof DynamicWrapperMBean)
w = ((DynamicWrapperMBean) w).getWrappedObject();
return w.getClass().getName();
}
public void preRegister2(MBeanServer mbs, ObjectName name) throws Exception {
if (mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).preRegister2(mbs, name);
}
public void registerFailed() {
if (mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).registerFailed();
}
public Object getWrappedObject() {
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedObject();
else
return mbean;
}
public ClassLoader getWrappedClassLoader() {
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
else
return mbean.getClass().getClassLoader();
}
public Object getAttribute(String attribute) throws AttributeNotFoundException,
MBeanException,
ReflectionException {
return mbean.getAttribute(attribute);
}
public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException,
ReflectionException {
mbean.setAttribute(attribute);
}
public AttributeList setAttributes(AttributeList attributes) {
return mbean.setAttributes(attributes);
}
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
return mbean.invoke(actionName, params, signature);
}
public MBeanInfo getMBeanInfo() {
return mbean.getMBeanInfo();
}
public AttributeList getAttributes(String[] attributes) {
return mbean.getAttributes(attributes);
}
public void removeNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback) throws ListenerNotFoundException {
nbs.removeNotificationListener(listener, filter, handback);
}
public void removeNotificationListener(NotificationListener listener)
throws ListenerNotFoundException {
nbs.removeNotificationListener(listener);
}
public MBeanNotificationInfo[] getNotificationInfo() {
return nbs.getNotificationInfo();
}
public void addNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback) {
nbs.addNotificationListener(listener, filter, handback);
}
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
if (mbr() != null)
return mbr().preRegister(server, name);
else
return name;
}
public void postRegister(Boolean registrationDone) {
if (mbr() != null)
mbr().postRegister(registrationDone);
}
public void preDeregister() throws Exception {
if (mbr() != null)
mbr().preDeregister();
}
public void postDeregister() {
if (mbr() != null)
mbr().postDeregister();
}
private MBeanRegistration mbr() {
if (mbean instanceof MBeanRegistration)
return (MBeanRegistration) mbean;
else
return null;
}
}

View File

@ -29,6 +29,7 @@ import com.sun.jmx.defaults.ServiceName;
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -39,7 +40,6 @@ import java.util.Set;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.RuntimeOperationsException;
@ -52,6 +52,27 @@ import javax.management.RuntimeOperationsException;
*/
public class Repository {
/**
* An interface that allows the caller to get some control
* over the registration.
* @see #addMBean
* @see #remove
*/
public interface RegistrationContext {
/**
* Called by {@link #addMBean}.
* Can throw a RuntimeOperationsException to cancel the
* registration.
*/
public void registering();
/**
* Called by {@link #remove}.
* Any exception thrown by this method will be ignored.
*/
public void unregistered();
}
// Private fields -------------------------------------------->
/**
@ -115,7 +136,6 @@ public class Repository {
/**
* Builds a new ObjectNamePattern object from an ObjectName pattern
* constituents.
* @param domain pattern.getDomain().
* @param propertyListPattern pattern.isPropertyListPattern().
* @param propertyValuePattern pattern.isPropertyValuePattern().
* @param canonicalProps pattern.getCanonicalKeyPropertyListString().
@ -216,16 +236,6 @@ public class Repository {
}
}
private void addNewDomMoi(final DynamicMBean object, final String dom,
final ObjectName name) {
final Map<String,NamedObject> moiTb =
new HashMap<String,NamedObject>();
moiTb.put(name.getCanonicalKeyPropertyListString(),
new NamedObject(name, object));
domainTb.put(dom, moiTb);
nbElements++;
}
/** Match a string against a shell-style pattern. The only pattern
characters recognised are <code>?</code>, standing for any one
character, and <code>*</code>, standing for any string of
@ -306,6 +316,50 @@ public class Repository {
}
}
private void addNewDomMoi(final DynamicMBean object,
final String dom,
final ObjectName name,
final RegistrationContext context) {
final Map<String,NamedObject> moiTb =
new HashMap<String,NamedObject>();
final String key = name.getCanonicalKeyPropertyListString();
addMoiToTb(object,name,key,moiTb,context);
domainTb.put(dom, moiTb);
nbElements++;
}
private void registering(RegistrationContext context) {
if (context == null) return;
try {
context.registering();
} catch (RuntimeOperationsException x) {
throw x;
} catch (RuntimeException x) {
throw new RuntimeOperationsException(x);
}
}
private void unregistering(RegistrationContext context, ObjectName name) {
if (context == null) return;
try {
context.unregistered();
} catch (Exception x) {
// shouldn't come here...
MBEANSERVER_LOGGER.log(Level.FINE,
"Unexpected exception while unregistering "+name,
x);
}
}
private void addMoiToTb(final DynamicMBean object,
final ObjectName name,
final String key,
final Map<String,NamedObject> moiTb,
final RegistrationContext context) {
registering(context);
moiTb.put(key,new NamedObject(name, object));
}
/**
* Retrieves the named object contained in repository
* from the given objectname.
@ -355,12 +409,12 @@ public class Repository {
domainTb = new HashMap<String,Map<String,NamedObject>>(5);
if (domain != null && domain.length() != 0)
this.domain = domain;
this.domain = domain.intern(); // we use == domain later on...
else
this.domain = ServiceName.DOMAIN;
// Creates an new hastable for the default domain
domainTb.put(this.domain.intern(), new HashMap<String,NamedObject>());
// Creates a new hashtable for the default domain
domainTb.put(this.domain, new HashMap<String,NamedObject>());
}
/**
@ -395,10 +449,21 @@ public class Repository {
/**
* Stores an MBean associated with its object name in the repository.
*
* @param object MBean to be stored in the repository.
* @param name MBean object name.
* @param object MBean to be stored in the repository.
* @param name MBean object name.
* @param context A registration context. If non null, the repository
* will call {@link RegistrationContext#registering()
* context.registering()} from within the repository
* lock, when it has determined that the {@code object}
* can be stored in the repository with that {@code name}.
* If {@link RegistrationContext#registering()
* context.registering()} throws an exception, the
* operation is abandonned, the MBean is not added to the
* repository, and a {@link RuntimeOperationsException}
* is thrown.
*/
public void addMBean(final DynamicMBean object, ObjectName name)
public void addMBean(final DynamicMBean object, ObjectName name,
final RegistrationContext context)
throws InstanceAlreadyExistsException {
if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
@ -431,7 +496,7 @@ public class Repository {
lock.writeLock().lock();
try {
// Domain cannot be JMImplementation if entry does not exists
// Domain cannot be JMImplementation if entry does not exist
if ( !to_default_domain &&
dom.equals("JMImplementation") &&
domainTb.containsKey("JMImplementation")) {
@ -440,21 +505,21 @@ public class Repository {
"Repository: domain name cannot be JMImplementation"));
}
// If domain not already exists, add it to the hash table
// If domain does not already exist, add it to the hash table
final Map<String,NamedObject> moiTb = domainTb.get(dom);
if (moiTb == null) {
addNewDomMoi(object, dom, name);
addNewDomMoi(object, dom, name, context);
return;
}
// Add instance if not already present
String cstr = name.getCanonicalKeyPropertyListString();
NamedObject elmt= moiTb.get(cstr);
if (elmt != null) {
throw new InstanceAlreadyExistsException(name.toString());
} else {
nbElements++;
moiTb.put(cstr, new NamedObject(name, object));
// Add instance if not already present
String cstr = name.getCanonicalKeyPropertyListString();
NamedObject elmt= moiTb.get(cstr);
if (elmt != null) {
throw new InstanceAlreadyExistsException(name.toString());
} else {
nbElements++;
addMoiToTb(object,name,cstr,moiTb,context);
}
}
} finally {
@ -533,7 +598,7 @@ public class Repository {
// ":*", ":[key=value],*" : names in defaultDomain
// "domain:*", "domain:[key=value],*" : names in the specified domain
// Surely one of the most frequent case ... query on the whole world
// Surely one of the most frequent cases ... query on the whole world
ObjectName name;
if (pattern == null ||
pattern.getCanonicalName().length() == 0 ||
@ -546,8 +611,7 @@ public class Repository {
// If pattern is not a pattern, retrieve this mbean !
if (!name.isPattern()) {
final NamedObject no;
no = retrieveNamedObject(name);
final NamedObject no = retrieveNamedObject(name);
if (no != null) result.add(no);
return result;
}
@ -577,12 +641,22 @@ public class Repository {
return result;
}
if (!name.isDomainPattern()) {
final Map<String,NamedObject> moiTb = domainTb.get(name.getDomain());
if (moiTb == null) return Collections.emptySet();
if (allNames)
result.addAll(moiTb.values());
else
addAllMatching(moiTb, result, namePattern);
return result;
}
// Pattern matching in the domain name (*, ?)
char[] dom2Match = name.getDomain().toCharArray();
for (String domain : domainTb.keySet()) {
char[] theDom = domain.toCharArray();
for (String dom : domainTb.keySet()) {
char[] theDom = dom.toCharArray();
if (wildmatch(theDom, dom2Match)) {
final Map<String,NamedObject> moiTb = domainTb.get(domain);
final Map<String,NamedObject> moiTb = domainTb.get(dom);
if (allNames)
result.addAll(moiTb.values());
else
@ -599,11 +673,21 @@ public class Repository {
* Removes an MBean from the repository.
*
* @param name name of the MBean to remove.
* @param context A registration context. If non null, the repository
* will call {@link RegistrationContext#unregistered()
* context.unregistered()} from within the repository
* lock, just after the mbean associated with
* {@code name} is removed from the repository.
* If {@link RegistrationContext#unregistered()
* context.unregistered()} is not expected to throw any
* exception. If it does, the exception is logged
* and swallowed.
*
* @exception InstanceNotFoundException The MBean does not exist in
* the repository.
*/
public void remove(final ObjectName name)
public void remove(final ObjectName name,
final RegistrationContext context)
throws InstanceNotFoundException {
// Debugging stuff
@ -645,6 +729,9 @@ public class Repository {
if (dom == domain)
domainTb.put(domain, new HashMap<String,NamedObject>());
}
unregistering(context,name);
} finally {
lock.writeLock().unlock();
}

View File

@ -35,6 +35,7 @@ import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport;
@ -118,22 +119,32 @@ class StandardMBeanIntrospector extends MBeanIntrospector<Method> {
@Override
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
Method getter, Method setter) {
Method getter, Method setter) throws IntrospectionException {
final String description = "Attribute exposed for management";
try {
return new MBeanAttributeInfo(attributeName, description,
getter, setter);
} catch (IntrospectionException e) {
throw new RuntimeException(e); // should not happen
}
String description = getAttributeDescription(
attributeName, "Attribute exposed for management",
getter, setter);
return new MBeanAttributeInfo(attributeName, description,
getter, setter);
}
@Override
MBeanOperationInfo getMBeanOperationInfo(String operationName,
Method operation) {
final String description = "Operation exposed for management";
return new MBeanOperationInfo(description, operation);
final String defaultDescription = "Operation exposed for management";
String description = Introspector.descriptionForElement(operation);
if (description == null)
description = defaultDescription;
int impact = MBeanOperationInfo.UNKNOWN;
ManagedOperation annot = operation.getAnnotation(ManagedOperation.class);
if (annot != null)
impact = annot.impact().getCode();
MBeanOperationInfo mboi = new MBeanOperationInfo(description, operation);
return new MBeanOperationInfo(
mboi.getName(), mboi.getDescription(), mboi.getSignature(),
mboi.getReturnType(), impact, mboi.getDescriptor());
}
@Override

View File

@ -41,26 +41,24 @@ import javax.management.openmbean.MXBeanMappingFactory;
public class StandardMBeanSupport extends MBeanSupport<Method> {
/**
<p>Construct a Standard MBean that wraps the given resource using the
given Standard MBean interface.</p>
@param resource the underlying resource for the new MBean.
@param mbeanInterface the interface to be used to determine
the MBean's management interface.
@param <T> a type parameter that allows the compiler to check
that {@code resource} implements {@code mbeanInterface},
provided that {@code mbeanInterface} is a class constant like
{@code SomeMBean.class}.
@throws IllegalArgumentException if {@code resource} is null or
if it does not implement the class {@code mbeanInterface} or if
that class is not a valid Standard MBean interface.
*/
public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterface)
* <p>Construct a Standard MBean that wraps the given resource using the
* given Standard MBean interface.</p>
*
* @param resource the underlying resource for the new MBean.
* @param mbeanInterfaceType the class or interface to be used to determine
* the MBean's management interface. An interface if this is a
* classic Standard MBean; a class if this is a {@code @ManagedResource}.
* @param <T> a type parameter that allows the compiler to check
* that {@code resource} implements {@code mbeanInterfaceType},
* provided that {@code mbeanInterfaceType} is a class constant like
* {@code SomeMBean.class}.
* @throws IllegalArgumentException if {@code resource} is null or
* if it does not implement the class {@code mbeanInterfaceType} or if
* that class is not a valid Standard MBean interface.
*/
public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterfaceType)
throws NotCompliantMBeanException {
super(resource, mbeanInterface, (MXBeanMappingFactory) null);
super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null);
}
@Override
@ -86,13 +84,14 @@ public class StandardMBeanSupport extends MBeanSupport<Method> {
@Override
public MBeanInfo getMBeanInfo() {
MBeanInfo mbi = super.getMBeanInfo();
Class<?> resourceClass = getResource().getClass();
if (StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
Class<?> resourceClass = getWrappedObject().getClass();
if (!getMBeanInterface().isInterface() ||
StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
return mbi;
return new MBeanInfo(mbi.getClassName(), mbi.getDescription(),
mbi.getAttributes(), mbi.getConstructors(),
mbi.getOperations(),
MBeanIntrospector.findNotifications(getResource()),
MBeanIntrospector.findNotifications(getWrappedObject()),
mbi.getDescriptor());
}
}

View File

@ -38,6 +38,7 @@ import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.WeakHashMap;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
@ -71,6 +72,10 @@ public class Util {
return new LinkedHashMap<K, V>();
}
static <K, V> WeakHashMap<K, V> newWeakHashMap() {
return new WeakHashMap<K, V>();
}
static <E> Set<E> newSet() {
return new HashSet<E>();
}

View File

@ -208,8 +208,9 @@ public class EventSetImpl extends ArrayList<Event> implements EventSet {
}
public String toString() {
return eventName() + "@" + location().toString() +
" in thread " + thread().name();
return eventName() + "@" +
((location() == null) ? " null" : location().toString()) +
" in thread " + thread().name();
}
}

View File

@ -40,11 +40,12 @@ public class MonitorInfoImpl extends MirrorImpl
int stack_depth;
MonitorInfoImpl(VirtualMachine vm, ObjectReference mon,
ThreadReference thread, int dpth) {
ThreadReferenceImpl thread, int dpth) {
super(vm);
this.monitor = mon;
this.thread = thread;
this.stack_depth = dpth;
thread.addListener(this);
}

View File

@ -35,12 +35,34 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
static final int SUSPEND_STATUS_SUSPENDED = 0x1;
static final int SUSPEND_STATUS_BREAK = 0x2;
private ThreadGroupReference threadGroup;
private int suspendedZombieCount = 0;
// This is cached only while the VM is suspended
private static class Cache extends ObjectReferenceImpl.Cache {
String name = null;
/*
* Some objects can only be created while a thread is suspended and are valid
* only while the thread remains suspended. Examples are StackFrameImpl
* and MonitorInfoImpl. When the thread resumes, these objects have to be
* marked as invalid so that their methods can throw
* InvalidStackFrameException if they are called. To do this, such objects
* register themselves as listeners of the associated thread. When the
* thread is resumed, its listeners are notified and mark themselves
* invalid.
* Also, note that ThreadReferenceImpl itself caches some info that
* is valid only as long as the thread is suspended. When the thread
* is resumed, that cache must be purged.
* Lastly, note that ThreadReferenceImpl and its super, ObjectReferenceImpl
* cache some info that is only valid as long as the entire VM is suspended.
* If _any_ thread is resumed, this cache must be purged. To handle this,
* both ThreadReferenceImpl and ObjectReferenceImpl register themselves as
* VMListeners so that they get notified when all threads are suspended and
* when any thread is resumed.
*/
// This is cached for the life of the thread
private ThreadGroupReference threadGroup;
// This is cached only while this one thread is suspended. Each time
// the thread is resumed, we clear this and start with a fresh one.
private static class LocalCache {
JDWP.ThreadReference.Status status = null;
List<StackFrame> frames = null;
int framesStart = -1;
@ -52,6 +74,17 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
boolean triedCurrentContended = false;
}
private LocalCache localCache;
private void resetLocalCache() {
localCache = new LocalCache();
}
// This is cached only while all threads in the VM are suspended
// Yes, someone could change the name of a thread while it is suspended.
private static class Cache extends ObjectReferenceImpl.Cache {
String name = null;
}
protected ObjectReferenceImpl.Cache newCache() {
return new Cache();
}
@ -59,8 +92,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
// Listeners - synchronized on vm.state()
private List<WeakReference<ThreadListener>> listeners = new ArrayList<WeakReference<ThreadListener>>();
ThreadReferenceImpl(VirtualMachine aVm, long aRef) {
super(aVm,aRef);
resetLocalCache();
vm.state().addListener(this);
}
@ -72,10 +107,24 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
* VMListener implementation
*/
public boolean vmNotSuspended(VMAction action) {
synchronized (vm.state()) {
processThreadAction(new ThreadAction(this,
ThreadAction.THREAD_RESUMABLE));
if (action.resumingThread() == null) {
// all threads are being resumed
synchronized (vm.state()) {
processThreadAction(new ThreadAction(this,
ThreadAction.THREAD_RESUMABLE));
}
}
/*
* Othewise, only one thread is being resumed:
* if it is us,
* we have already done our processThreadAction to notify our
* listeners when we processed the resume.
* if it is not us,
* we don't want to notify our listeners
* because we are not being resumed.
*/
return super.vmNotSuspended(action);
}
@ -191,23 +240,19 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
private JDWP.ThreadReference.Status jdwpStatus() {
JDWP.ThreadReference.Status status = null;
JDWP.ThreadReference.Status myStatus = localCache.status;
try {
Cache local = (Cache)getCache();
if (local != null) {
status = local.status;
}
if (status == null) {
status = JDWP.ThreadReference.Status.process(vm, this);
if (local != null) {
local.status = status;
if (myStatus == null) {
myStatus = JDWP.ThreadReference.Status.process(vm, this);
if ((myStatus.suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0) {
// thread is suspended, we can cache the status.
localCache.status = myStatus;
}
}
} catch (JDWPException exc) {
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return status;
return myStatus;
}
public int status() {
@ -245,8 +290,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
public ThreadGroupReference threadGroup() {
/*
* Thread group can't change, so it's cached more conventionally
* than other things in this class.
* Thread group can't change, so it's cached once and for all.
*/
if (threadGroup == null) {
try {
@ -260,19 +304,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
public int frameCount() throws IncompatibleThreadStateException {
int frameCount = -1;
try {
Cache local = (Cache)getCache();
if (local != null) {
frameCount = local.frameCount;
}
if (frameCount == -1) {
frameCount = JDWP.ThreadReference.FrameCount
if (localCache.frameCount == -1) {
localCache.frameCount = JDWP.ThreadReference.FrameCount
.process(vm, this).frameCount;
if (local != null) {
local.frameCount = frameCount;
}
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
@ -283,7 +318,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw exc.toJDIException();
}
}
return frameCount;
return localCache.frameCount;
}
public List<StackFrame> frames() throws IncompatibleThreadStateException {
@ -297,23 +332,25 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
/**
* Is the requested subrange within what has been retrieved?
* local is known to be non-null
* local is known to be non-null. Should only be called from
* a sync method.
*/
private boolean isSubrange(Cache local,
int start, int length, List frames) {
if (start < local.framesStart) {
private boolean isSubrange(LocalCache localCache,
int start, int length) {
if (start < localCache.framesStart) {
return false;
}
if (length == -1) {
return (local.framesLength == -1);
return (localCache.framesLength == -1);
}
if (local.framesLength == -1) {
if ((start + length) > (local.framesStart + frames.size())) {
if (localCache.framesLength == -1) {
if ((start + length) > (localCache.framesStart +
localCache.frames.size())) {
throw new IndexOutOfBoundsException();
}
return true;
}
return ((start + length) <= (local.framesStart + local.framesLength));
return ((start + length) <= (localCache.framesStart + localCache.framesLength));
}
public List<StackFrame> frames(int start, int length)
@ -329,51 +366,42 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
* Private version of frames() allows "-1" to specify all
* remaining frames.
*/
private List<StackFrame> privateFrames(int start, int length)
synchronized private List<StackFrame> privateFrames(int start, int length)
throws IncompatibleThreadStateException {
List<StackFrame> frames = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
frames = local.frames;
}
if (frames == null || !isSubrange(local, start, length, frames)) {
// Lock must be held while creating stack frames so if that two threads
// do this at the same time, one won't clobber the subset created by the other.
try {
if (localCache.frames == null || !isSubrange(localCache, start, length)) {
JDWP.ThreadReference.Frames.Frame[] jdwpFrames
= JDWP.ThreadReference.Frames.
process(vm, this, start, length).frames;
process(vm, this, start, length).frames;
int count = jdwpFrames.length;
frames = new ArrayList<StackFrame>(count);
localCache.frames = new ArrayList<StackFrame>(count);
// Lock must be held while creating stack frames.
// so that a resume will not resume a partially
// created stack.
synchronized (vm.state()) {
for (int i = 0; i<count; i++) {
if (jdwpFrames[i].location == null) {
throw new InternalException("Invalid frame location");
}
StackFrame frame = new StackFrameImpl(vm, this,
jdwpFrames[i].frameID,
jdwpFrames[i].location);
// Add to the frame list
frames.add(frame);
for (int i = 0; i<count; i++) {
if (jdwpFrames[i].location == null) {
throw new InternalException("Invalid frame location");
}
StackFrame frame = new StackFrameImpl(vm, this,
jdwpFrames[i].frameID,
jdwpFrames[i].location);
// Add to the frame list
localCache.frames.add(frame);
}
if (local != null) {
local.frames = frames;
local.framesStart = start;
local.framesLength = length;
}
localCache.framesStart = start;
localCache.framesLength = length;
return Collections.unmodifiableList(localCache.frames);
} else {
int fromIndex = start - local.framesStart;
int fromIndex = start - localCache.framesStart;
int toIndex;
if (length == -1) {
toIndex = frames.size() - fromIndex;
toIndex = localCache.frames.size() - fromIndex;
} else {
toIndex = fromIndex + length;
}
frames = frames.subList(fromIndex, toIndex);
return Collections.unmodifiableList(localCache.frames.subList(fromIndex, toIndex));
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
@ -384,28 +412,18 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw exc.toJDIException();
}
}
return Collections.unmodifiableList(frames);
}
public List<ObjectReference> ownedMonitors() throws IncompatibleThreadStateException {
List<ObjectReference> monitors = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
monitors = local.ownedMonitors;
}
if (monitors == null) {
monitors = Arrays.asList(
if (localCache.ownedMonitors == null) {
localCache.ownedMonitors = Arrays.asList(
(ObjectReference[])JDWP.ThreadReference.OwnedMonitors.
process(vm, this).owned);
if (local != null) {
local.ownedMonitors = monitors;
if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + monitors.size() + ")");
}
if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + localCache.ownedMonitors.size() + ")");
}
}
} catch (JDWPException exc) {
@ -417,29 +435,22 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw exc.toJDIException();
}
}
return monitors;
return localCache.ownedMonitors;
}
public ObjectReference currentContendedMonitor()
throws IncompatibleThreadStateException {
ObjectReference monitor = null;
try {
Cache local = (Cache)getCache();
if (local != null && local.triedCurrentContended) {
monitor = local.contendedMonitor;
} else {
monitor = JDWP.ThreadReference.CurrentContendedMonitor.
if (localCache.contendedMonitor == null &&
!localCache.triedCurrentContended) {
localCache.contendedMonitor = JDWP.ThreadReference.CurrentContendedMonitor.
process(vm, this).monitor;
if (local != null) {
local.triedCurrentContended = true;
local.contendedMonitor = monitor;
if ((monitor != null) &&
((vm.traceFlags & vm.TRACE_OBJREFS) != 0)) {
vm.printTrace(description() +
" temporarily caching contended monitor"+
" (id = " + monitor.uniqueID() + ")");
}
localCache.triedCurrentContended = true;
if ((localCache.contendedMonitor != null) &&
((vm.traceFlags & vm.TRACE_OBJREFS) != 0)) {
vm.printTrace(description() +
" temporarily caching contended monitor"+
" (id = " + localCache.contendedMonitor.uniqueID() + ")");
}
}
} catch (JDWPException exc) {
@ -450,40 +461,31 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw exc.toJDIException();
}
}
return monitor;
return localCache.contendedMonitor;
}
public List<MonitorInfo> ownedMonitorsAndFrames() throws IncompatibleThreadStateException {
List<MonitorInfo> monitors = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
monitors = local.ownedMonitorsInfo;
}
if (monitors == null) {
if (localCache.ownedMonitorsInfo == null) {
JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor[] minfo;
minfo = JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.process(vm, this).owned;
monitors = new ArrayList<MonitorInfo>(minfo.length);
localCache.ownedMonitorsInfo = new ArrayList<MonitorInfo>(minfo.length);
for (int i=0; i < minfo.length; i++) {
JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor mi =
minfo[i];
MonitorInfo mon = new MonitorInfoImpl(vm, minfo[i].monitor, this, minfo[i].stack_depth);
monitors.add(mon);
localCache.ownedMonitorsInfo.add(mon);
}
if (local != null) {
local.ownedMonitorsInfo = monitors;
if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + monitors.size() + ")");
if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + localCache.ownedMonitorsInfo.size() + ")");
}
}
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
@ -493,7 +495,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
throw exc.toJDIException();
}
}
return monitors;
return localCache.ownedMonitorsInfo;
}
public void popFrames(StackFrame frame) throws IncompatibleThreadStateException {
@ -511,7 +513,7 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
}
public void forceEarlyReturn(Value returnValue) throws InvalidTypeException,
ClassNotLoadedException,
ClassNotLoadedException,
IncompatibleThreadStateException {
if (!vm.canForceEarlyReturn()) {
throw new UnsupportedOperationException(
@ -604,6 +606,9 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
iter.remove();
}
}
// Discard our local cache
resetLocalCache();
}
}
}

View File

@ -38,10 +38,18 @@ class VMAction extends EventObject {
static final int VM_NOT_SUSPENDED = 2;
int id;
ThreadReference resumingThread;
VMAction(VirtualMachine vm, int id) {
this(vm, null, id);
}
// For id = VM_NOT_SUSPENDED, if resumingThread != null, then it is
// the only thread that is being resumed.
VMAction(VirtualMachine vm, ThreadReference resumingThread, int id) {
super(vm);
this.id = id;
this.resumingThread = resumingThread;
}
VirtualMachine vm() {
return (VirtualMachine)getSource();
@ -49,4 +57,8 @@ class VMAction extends EventObject {
int id() {
return id;
}
ThreadReference resumingThread() {
return resumingThread;
}
}

View File

@ -116,16 +116,25 @@ class VMState {
}
/**
* Tell listeners to invalidate suspend-sensitive caches.
* All threads are resuming
*/
synchronized void thaw() {
void thaw() {
thaw(null);
}
/**
* Tell listeners to invalidate suspend-sensitive caches.
* If resumingThread != null, then only that thread is being
* resumed.
*/
synchronized void thaw(ThreadReference resumingThread) {
if (cache != null) {
if ((vm.traceFlags & vm.TRACE_OBJREFS) != 0) {
vm.printTrace("Clearing VM suspended cache");
}
disableCache();
}
processVMAction(new VMAction(vm, VMAction.VM_NOT_SUSPENDED));
processVMAction(new VMAction(vm, resumingThread, VMAction.VM_NOT_SUSPENDED));
}
private synchronized void processVMAction(VMAction action) {

View File

@ -146,8 +146,9 @@ class VirtualMachineImpl extends MirrorImpl
public boolean threadResumable(ThreadAction action) {
/*
* If any thread is resumed, the VM is considered not suspended.
* Just one thread is being resumed so pass it to thaw.
*/
state.thaw();
state.thaw(action.thread());
return true;
}

View File

@ -191,7 +191,7 @@ public abstract class SelectionKey {
* @throws IllegalArgumentException
* If a bit in the set does not correspond to an operation that
* is supported by this key's channel, that is, if
* <tt>set & ~(channel().validOps()) != 0</tt>
* <tt>(ops & ~channel().validOps()) != 0</tt>
*
* @throws CancelledKeyException
* If this key has been cancelled

View File

@ -192,6 +192,7 @@ class BinaryRelQueryExp extends QueryEval implements QueryExp {
return "(" + exp1 + ") " + relOpString() + " (" + exp2 + ")";
}
@Override
String toQueryString() {
return exp1 + " " + relOpString() + " " + exp2;
}

View File

@ -0,0 +1,180 @@
/*
* Copyright 2007 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 javax.management;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ResourceBundle;
/**
* <p>The textual description of an MBean or part of an MBean. This
* description is intended to be displayed to users to help them
* understand what the MBean does. Ultimately it will be the value of
* the {@code getDescription()} method of an {@link MBeanInfo}, {@link
* MBeanAttributeInfo}, or similar.</p>
*
* <p>This annotation applies to Standard MBean interfaces and to
* MXBean interfaces, as well as to MBean classes defined using the
* {@link MBean @MBean} or {@link MXBean @MXBean} annotations. For
* example, a Standard MBean might be defined like this:</p>
*
* <pre>
* <b>{@code @Description}</b>("Application configuration")
* public interface ConfigurationMBean {
* <b>{@code @Description}</b>("Cache size in bytes")
* public int getCacheSize();
* public void setCacheSize(int size);
*
* <b>{@code @Description}</b>("Last time the configuration was changed, " +
* "in milliseconds since 1 Jan 1970")
* public long getLastChangedTime();
*
* <b>{@code @Description}</b>("Save the configuration to a file")
* public void save(
* <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
* String fileName);
* }
* </pre>
*
* <p>The {@code MBeanInfo} for this MBean will have a {@link
* MBeanInfo#getDescription() getDescription()} that is {@code
* "Application configuration"}. It will contain an {@code
* MBeanAttributeInfo} for the {@code CacheSize} attribute that is
* defined by the methods {@code getCacheSize} and {@code
* setCacheSize}, and another {@code MBeanAttributeInfo} for {@code
* LastChangedTime}. The {@link MBeanAttributeInfo#getDescription()
* getDescription()} for {@code CacheSize} will be {@code "Cache size
* in bytes"}. Notice that there is no need to add a
* {@code @Description} to both {@code getCacheSize} and {@code
* setCacheSize} - either alone will do. But if you do add a
* {@code @Description} to both, it must be the same.</p>
*
* <p>The {@code MBeanInfo} will also contain an {@link
* MBeanOperationInfo} where {@link
* MBeanOperationInfo#getDescription() getDescription()} is {@code
* "Save the configuration to a file"}. This {@code
* MBeanOperationInfo} will contain an {@link MBeanParameterInfo}
* where {@link MBeanParameterInfo#getDescription() getDescription()}
* is {@code "Optional name of the file, or null for the default
* name"}.</p>
*
* <p>The {@code @Description} annotation can also be applied to the
* public constructors of the implementation class. Continuing the
* above example, the {@code Configuration} class implementing {@code
* ConfigurationMBean} might look like this:</p>
*
* <pre>
* public class Configuration implements ConfigurationMBean {
* <b>{@code @Description}</b>("A Configuration MBean with the default file name")
* public Configuration() {
* this(DEFAULT_FILE_NAME);
* }
*
* <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
* public Configuration(
* <b>{@code @Description}</b>("Name of the file the configuration is stored in")
* String fileName) {...}
* ...
* }
* </pre>
*
* <p>The {@code @Description} annotation also works in MBeans that
* are defined using the {@code @MBean} or {@code @MXBean} annotation
* on classes. Here is an alternative implementation of {@code
* Configuration} that does not use an {@code ConfigurationMBean}
* interface.</p>
*
* <pre>
* <b>{@code @MBean}</b>
* <b>{@code @Description}</b>("Application configuration")
* public class Configuration {
* <b>{@code @Description}</b>("A Configuration MBean with the default file name")
* public Configuration() {
* this(DEFAULT_FILE_NAME);
* }
*
* <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
* public Configuration(
* <b>{@code @Description}</b>("Name of the file the configuration is stored in")
* String fileName) {...}
*
* <b>{@code @ManagedAttribute}</b>
* <b>{@code @Description}</b>("Cache size in bytes")
* public int getCacheSize() {...}
* <b>{@code @ManagedAttribute}</b>
* public void setCacheSize(int size) {...}
*
* <b>{@code @ManagedOperation}</b>
* <b>{@code @Description}</b>("Last time the configuration was changed, " +
* "in milliseconds since 1 Jan 1970")
* public long getLastChangedTime() {...}
*
* <b>{@code @ManagedOperation}</b>
* <b>{@code @Description}</b>("Save the configuration to a file")
* public void save(
* <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
* String fileName) {...}
* ...
* }
* </pre>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE})
public @interface Description {
/**
* <p>The description.</p>
*/
String value();
/**
* <p>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}. If a non-default value
* is supplied for this element, it will appear in the
* <a href="Descriptor.html#descriptionResourceBundleBaseName"><!--
* -->{@code Descriptor}</a> for the annotated item.</p>
*/
@DescriptorKey(
value = "descriptionResourceBundleBaseName", omitIfDefault = true)
String bundleBaseName() default "";
/**
* <p>A resource key for the description of this element. In
* conjunction with the {@link #bundleBaseName bundleBaseName},
* this can be used to find a localized version of the description.
* If a non-default value
* is supplied for this element, it will appear in the
* <a href="Descriptor.html#descriptionResourceKey"><!--
* -->{@code Descriptor}</a> for the annotated item.</p>
*/
@DescriptorKey(value = "descriptionResourceKey", omitIfDefault = true)
String key() default "";
}

View File

@ -38,6 +38,7 @@ import java.util.Arrays;
import java.util.ResourceBundle;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
import javax.management.openmbean.OpenMBeanOperationInfoSupport;
import javax.management.openmbean.OpenMBeanParameterInfoSupport;
@ -117,21 +118,19 @@ import javax.management.openmbean.OpenType;
* deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td>
*
* <tr><td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
* <tr id="descriptionResourceBundleBaseName">
* <td>descriptionResource<br>BundleBaseName</td><td>String</td><td>Any</td>
*
* <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}. The meaning of this
* field is defined by this specification but the field is not set or
* used by the JMX API itself.</td>
* {@code "com.example.myapp.MBeanResources"}.</td>
*
* <tr><td>descriptionResourceKey</td><td>String</td><td>Any</td>
* <tr id="descriptionResourceKey">
* <td>descriptionResourceKey</td><td>String</td><td>Any</td>
*
* <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName},
* this can be used to find a localized version of the description.
* The meaning of this field is defined by this specification but the
* field is not set or used by the JMX API itself.</td>
* this can be used to find a localized version of the description.</td>
*
* <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
@ -216,6 +215,14 @@ import javax.management.openmbean.OpenType;
* StandardMBean} class will have this field in its MBeanInfo
* Descriptor.</td>
*
* <tr><td id="mxbeanMappingFactoryClass"><i>mxbeanMappingFactoryClass</i>
* </td><td>String</td>
* <td>MBeanInfo</td>
*
* <td>The name of the {@link MXBeanMappingFactory} class that was used for this
* MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default}
* one.</td>
*
* <tr><td><a name="openType"><i>openType</i></a><td>{@link OpenType}</td>
* <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
*

View File

@ -0,0 +1,137 @@
/*
* Copyright 2007 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 javax.management;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>Annotation that adds fields to a {@link Descriptor}. This can be the
* Descriptor for an MBean, or for an attribute, operation, or constructor
* in an MBean, or for a parameter of an operation or constructor.</p>
*
* <p>Consider this Standard MBean interface, for example:</p>
*
* <pre>
* public interface CacheControlMBean {
* <b>&#64;DescriptorFields("units=bytes")</b>
* public long getCacheSize();
* }
* </pre>
*
* <p>When a Standard MBean is made using this interface, the usual rules
* mean that it will have an attribute called {@code CacheSize} of type
* {@code long}. The {@code DescriptorFields} annotation will ensure
* that the {@link MBeanAttributeInfo} for this attribute will have a
* {@code Descriptor} that has a field called {@code units} with
* corresponding value {@code bytes}.</p>
*
* <p>Similarly, if the interface looks like this:</p>
*
* <pre>
* public interface CacheControlMBean {
* <b>&#64;DescriptorFields({"units=bytes", "since=1.5"})</b>
* public long getCacheSize();
* }
* </pre>
*
* <p>then the resulting {@code Descriptor} will contain the following
* fields:</p>
*
* <table border="2">
* <tr><th>Name</th><th>Value</th></tr>
* <tr><td>units</td><td>"bytes"</td></tr>
* <tr><td>since</td><td>"1.5"</td></tr>
* </table>
*
* <p>The {@code @DescriptorFields} annotation can be applied to:</p>
*
* <ul>
* <li>a Standard MBean or MXBean interface;
* <li>a method in such an interface;
* <li>a parameter of a method in a Standard MBean or MXBean interface
* when that method is an operation (not a getter or setter for an attribute);
* <li>a public constructor in the class that implements a Standard MBean
* or MXBean;
* <li>a parameter in such a constructor.
* </ul>
*
* <p>Other uses of the annotation will either fail to compile or be
* ignored.</p>
*
* <p>Interface annotations are checked only on the exact interface
* that defines the management interface of a Standard MBean or an
* MXBean, not on its parent interfaces. Method annotations are
* checked only in the most specific interface in which the method
* appears; in other words, if a child interface overrides a method
* from a parent interface, only {@code @DescriptorFields} annotations in
* the method in the child interface are considered.
*
* <p>The Descriptor fields contributed in this way must be consistent
* with each other and with any fields contributed by {@link
* DescriptorKey &#64;DescriptorKey} annotations. That is, two
* different annotations, or two members of the same annotation, must
* not define a different value for the same Descriptor field. Fields
* from annotations on a getter method must also be consistent with
* fields from annotations on the corresponding setter method.</p>
*
* <p>The Descriptor resulting from these annotations will be merged
* with any Descriptor fields provided by the implementation, such as
* the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field for an MBean. The fields from the annotations
* must be consistent with these fields provided by the implementation.</p>
*
* <h4>{@literal @DescriptorFields and @DescriptorKey}</h4>
*
* <p>The {@link DescriptorKey @DescriptorKey} annotation provides
* another way to use annotations to define Descriptor fields.
* <code>&#64;DescriptorKey</code> requires more work but is also more
* robust, because there is less risk of mistakes such as misspelling
* the name of the field or giving an invalid value.
* <code>&#64;DescriptorFields</code> is more convenient but includes
* those risks. <code>&#64;DescriptorFields</code> is more
* appropriate for occasional use, but for a Descriptor field that you
* add in many places, you should consider a purpose-built annotation
* using <code>&#64;DescriptorKey</code>.
*
* @since 1.7
*/
@Documented
@Inherited // for @MBean and @MXBean classes
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,
ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DescriptorFields {
/**
* <p>The descriptor fields. Each element of the string looks like
* {@code "name=value"}.</p>
*/
public String[] value();
}

View File

@ -33,6 +33,11 @@ import java.lang.annotation.*;
* an MBean, or for an attribute, operation, or constructor in an
* MBean, or for a parameter of an operation or constructor.</p>
*
* <p>(The {@link DescriptorFields @DescriptorFields} annotation
* provides another way to add fields to a {@code Descriptor}. See
* the documentation for that annotation for a comparison of the
* two possibilities.)</p>
*
* <p>Consider this annotation for example:</p>
*
* <pre>
@ -57,7 +62,7 @@ import java.lang.annotation.*;
* <p>When a Standard MBean is made from the {@code CacheControlMBean},
* the usual rules mean that it will have an attribute called
* {@code CacheSize} of type {@code long}. The {@code @Units}
* attribute, given the above definition, will ensure that the
* annotation, given the above definition, will ensure that the
* {@link MBeanAttributeInfo} for this attribute will have a
* {@code Descriptor} that has a field called {@code units} with
* corresponding value {@code bytes}.</p>
@ -125,12 +130,13 @@ import java.lang.annotation.*;
* the method in the child interface are considered.
*
* <p>The Descriptor fields contributed in this way by different
* annotations on the same program element must be consistent. That
* is, two different annotations, or two members of the same
* annotation, must not define a different value for the same
* Descriptor field. Fields from annotations on a getter method must
* also be consistent with fields from annotations on the
* corresponding setter method.</p>
* annotations on the same program element must be consistent with
* each other and with any fields contributed by a {@link
* DescriptorFields &#64;DescriptorFields} annotation. That is, two
* different annotations, or two members of the same annotation, must
* not define a different value for the same Descriptor field. Fields
* from annotations on a getter method must also be consistent with
* fields from annotations on the corresponding setter method.</p>
*
* <p>The Descriptor resulting from these annotations will be merged
* with any Descriptor fields provided by the implementation, such as
@ -169,4 +175,36 @@ import java.lang.annotation.*;
@Target(ElementType.METHOD)
public @interface DescriptorKey {
String value();
/**
* <p>Do not include this field in the Descriptor if the annotation
* element has its default value. For example, suppose {@code @Units} is
* defined like this:</p>
*
* <pre>
* &#64;Documented
* &#64;Target(ElementType.METHOD)
* &#64;Retention(RetentionPolicy.RUNTIME)
* public &#64;interface Units {
* &#64;DescriptorKey("units")
* String value();
*
* <b>&#64;DescriptorKey(value = "descriptionResourceKey",
* omitIfDefault = true)</b>
* String resourceKey() default "";
*
* <b>&#64;DescriptorKey(value = "descriptionResourceBundleBaseName",
* omitIfDefault = true)</b>
* String resourceBundleBaseName() default "";
* }
* </pre>
*
* <p>Then consider a usage such as {@code @Units("bytes")} or
* {@code @Units(value = "bytes", resourceKey = "")}, where the
* {@code resourceKey} and {@code resourceBundleBaseNames} elements
* have their default values. In this case the Descriptor resulting
* from these annotations will not include a {@code descriptionResourceKey}
* or {@code descriptionResourceBundleBaseName} field.</p>
*/
boolean omitIfDefault() default false;
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 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. 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 javax.management;
/**
* <p>An MBean can implement this interface to affect how the MBeanServer's
* {@link MBeanServer#getClassLoaderFor getClassLoaderFor} and
* {@link MBeanServer#isInstanceOf isInstanceOf} methods behave.
* If these methods should refer to a wrapped object rather than the
* MBean object itself, then the {@link #getWrappedObject} method should
* return that wrapped object.</p>
*
* @see MBeanServer#getClassLoaderFor
* @see MBeanServer#isInstanceOf
*/
public interface DynamicWrapperMBean extends DynamicMBean {
/**
* <p>The resource corresponding to this MBean. This is the object whose
* class name should be reflected by the MBean's
* {@link MBeanServer#getMBeanInfo getMBeanInfo()}.<!--
* -->{@link MBeanInfo#getClassName getClassName()} for example. For a "plain"
* DynamicMBean it will be "this". For an MBean that wraps another
* object, in the manner of {@link javax.management.StandardMBean}, it will be the
* wrapped object.</p>
*
* @return The resource corresponding to this MBean.
*/
public Object getWrappedObject();
/**
* <p>The {@code ClassLoader} for this MBean, which can be used to
* retrieve resources associated with the MBean for example. Usually,
* it will be
* {@link #getWrappedObject()}.{@code getClass().getClassLoader()}.
*
* @return The {@code ClassLoader} for this MBean.
*/
public ClassLoader getWrappedClassLoader();
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 2007 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 javax.management;
/**
* <p>Defines the impact of an MBean operation, in particular whether it
* has an effect on the MBean or simply returns information. This enum
* is used in the {@link ManagedOperation @ManagedOperation} annotation.
* Its {@link #getCode()} method can be used to get an {@code int} suitable
* for use as the {@code impact} parameter in an {@link MBeanOperationInfo}
* constructor.</p>
*/
public enum Impact {
/**
* The operation is read-like: it returns information but does not change
* any state.
* @see MBeanOperationInfo#INFO
*/
INFO(MBeanOperationInfo.INFO),
/**
* The operation is write-like: it has an effect but does not return
* any information from the MBean.
* @see MBeanOperationInfo#ACTION
*/
ACTION(MBeanOperationInfo.ACTION),
/**
* The operation is both read-like and write-like: it has an effect,
* and it also returns information from the MBean.
* @see MBeanOperationInfo#ACTION_INFO
*/
ACTION_INFO(MBeanOperationInfo.ACTION_INFO),
/**
* The impact of the operation is unknown or cannot be expressed
* using one of the other values.
* @see MBeanOperationInfo#UNKNOWN
*/
UNKNOWN(MBeanOperationInfo.UNKNOWN);
private final int code;
/**
* An instance of this enumeration, with the corresponding {@code int}
* code used by the {@link MBeanOperationInfo} constructors.
*
* @param code the code used by the {@code MBeanOperationInfo} constructors.
*/
Impact(int code) {
this.code = code;
}
/**
* The equivalent {@code int} code used by the {@link MBeanOperationInfo}
* constructors.
* @return the {@code int} code.
*/
public int getCode() {
return code;
}
/**
* Return the {@code Impact} value corresponding to the given {@code int}
* code. The {@code code} is the value that would be used in an
* {@code MBeanOperationInfo} constructor.
*
* @param code the {@code int} code.
*
* @return an {@code Impact} value {@code x} such that
* {@code code == x.}{@link #getCode()}, or {@code Impact.UNKNOWN}
* if there is no such value.
*/
public static Impact forCode(int code) {
switch (code) {
case MBeanOperationInfo.ACTION: return ACTION;
case MBeanOperationInfo.INFO: return INFO;
case MBeanOperationInfo.ACTION_INFO: return ACTION_INFO;
default: return UNKNOWN;
}
}
}

View File

@ -26,6 +26,7 @@
package javax.management;
import com.sun.jmx.mbeanserver.Introspector;
import com.sun.jmx.mbeanserver.MBeanInjector;
import com.sun.jmx.remote.util.ClassLogger;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
@ -130,6 +131,7 @@ public class JMX {
* </pre>
*
* @see javax.management.JMX.ProxyOptions
* @see javax.management.StandardMBean.Options
*/
public static class MBeanOptions implements Serializable, Cloneable {
private static final long serialVersionUID = -6380842449318177843L;
@ -739,4 +741,28 @@ public class JMX {
// exactly the string "MXBean" since that would mean there
// was no package name, which is pretty unlikely in practice.
}
/**
* <p>Test if an MBean can emit notifications. An MBean can emit
* notifications if either it implements {@link NotificationBroadcaster}
* (perhaps through its child interface {@link NotificationEmitter}), or
* it uses <a href="MBeanRegistration.html#injection">resource
* injection</a> to obtain an instance of {@link SendNotification}
* through which it can send notifications.</p>
*
* @param mbean an MBean object.
* @return true if the given object is a valid MBean that can emit
* notifications; false if the object is a valid MBean but that
* cannot emit notifications.
* @throws NotCompliantMBeanException if the given object is not
* a valid MBean.
*/
public static boolean isNotificationSource(Object mbean)
throws NotCompliantMBeanException {
if (mbean instanceof NotificationBroadcaster)
return true;
Object resource = (mbean instanceof DynamicWrapperMBean) ?
((DynamicWrapperMBean) mbean).getWrappedObject() : mbean;
return (MBeanInjector.injectsSendNotification(resource));
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright 2007 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 javax.management;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>Indicates that the annotated class is a Standard MBean. A Standard
* MBean class can be defined as in this example:</p>
*
* <pre>
* {@code @MBean}
* public class Configuration {
* {@link ManagedAttribute @ManagedAttribute}
* public int getCacheSize() {...}
* {@code @ManagedAttribute}
* public void setCacheSize(int size);
*
* {@code @ManagedAttribute}
* public long getLastChangedTime();
*
* {@link ManagedOperation @ManagedOperation}
* public void save();
* }
* </pre>
*
* <p>The class must be public. Public methods within the class can be
* annotated with {@code @ManagedOperation} to indicate that they are
* MBean operations. Public getter and setter methods within the class
* can be annotated with {@code @ManagedAttribute} to indicate that they define
* MBean attributes.</p>
*
* <p>If the MBean is to be an MXBean rather than a Standard MBean, then
* the {@link MXBean @MXBean} annotation must be used instead of
* {@code @MBean}.</p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface MBean {
}

View File

@ -46,25 +46,30 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
new MBeanOperationInfo[0];
/**
* Indicates that the operation is read-like,
* it basically returns information.
* Indicates that the operation is read-like:
* it returns information but does not change any state.
* @see Impact#INFO
*/
public static final int INFO = 0;
/**
* Indicates that the operation is a write-like,
* and would modify the MBean in some way, typically by writing some value
* or changing a configuration.
* Indicates that the operation is write-like: it has an effect but does
* not return any information from the MBean.
* @see Impact#ACTION
*/
public static final int ACTION = 1;
/**
* Indicates that the operation is both read-like and write-like.
* Indicates that the operation is both read-like and write-like:
* it has an effect, and it also returns information from the MBean.
* @see Impact#ACTION_INFO
*/
public static final int ACTION_INFO = 2;
/**
* Indicates that the operation has an "unknown" nature.
* Indicates that the impact of the operation is unknown or cannot be
* expressed using one of the other values.
* @see Impact#UNKNOWN
*/
public static final int UNKNOWN = 3;
@ -120,8 +125,9 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
* describing the parameters(arguments) of the method. This may be
* null with the same effect as a zero-length array.
* @param type The type of the method's return value.
* @param impact The impact of the method, one of <CODE>INFO,
* ACTION, ACTION_INFO, UNKNOWN</CODE>.
* @param impact The impact of the method, one of
* {@link #INFO}, {@link #ACTION}, {@link #ACTION_INFO},
* {@link #UNKNOWN}.
*/
public MBeanOperationInfo(String name,
String description,
@ -140,8 +146,9 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
* describing the parameters(arguments) of the method. This may be
* null with the same effect as a zero-length array.
* @param type The type of the method's return value.
* @param impact The impact of the method, one of <CODE>INFO,
* ACTION, ACTION_INFO, UNKNOWN</CODE>.
* @param impact The impact of the method, one of
* {@link #INFO}, {@link #ACTION}, {@link #ACTION_INFO},
* {@link #UNKNOWN}.
* @param descriptor The descriptor for the operation. This may be null
* which is equivalent to an empty descriptor.
*
@ -319,9 +326,14 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable {
for (int i = 0; i < classes.length; i++) {
Descriptor d = Introspector.descriptorForAnnotations(annots[i]);
final String pn = "p" + (i + 1);
params[i] =
new MBeanParameterInfo(pn, classes[i].getName(), "", d);
String description = Introspector.descriptionForParameter(annots[i]);
if (description == null)
description = "";
String name = Introspector.nameForParameter(annots[i]);
if (name == null)
name = "p" + (i + 1);
params[i] = new MBeanParameterInfo(
name, classes[i].getName(), description, d);
}
return params;

View File

@ -27,9 +27,101 @@ package javax.management;
/**
* Can be implemented by an MBean in order to
* <p>Can be implemented by an MBean in order to
* carry out operations before and after being registered or unregistered from
* the MBean server.
* the MBean Server. An MBean can also implement this interface in order
* to get a reference to the MBean Server and/or its name within that
* MBean Server.</p>
*
* <h4 id="injection">Resource injection</h4>
*
* <p>As an alternative to implementing {@code MBeanRegistration}, if all that
* is needed is the MBean Server or ObjectName then an MBean can use
* <em>resource injection</em>.</p>
*
* <p>If a field in the MBean object has type {@link ObjectName} and has
* the {@link javax.annotation.Resource &#64;Resource} annotation,
* then the {@code ObjectName} under which the MBean is registered is
* assigned to that field during registration. Likewise, if a field has type
* {@link MBeanServer} and the <code>&#64;Resource</code> annotation, then it will
* be set to the {@code MBeanServer} in which the MBean is registered.</p>
*
* <p>For example:</p>
*
* <pre>
* public Configuration implements ConfigurationMBean {
* &#64;Resource
* private volatile MBeanServer mbeanServer;
* &#64;Resource
* private volatile ObjectName objectName;
* ...
* void unregisterSelf() throws Exception {
* mbeanServer.unregisterMBean(objectName);
* }
* }
* </pre>
*
* <p>Resource injection can also be used on fields of type
* {@link SendNotification} to simplify notification sending. Such a field
* will get a reference to an object of type {@code SendNotification} when
* the MBean is registered, and it can use this reference to send notifications.
* For example:</p>
*
* <pre>
* public Configuration implements ConfigurationMBean {
* &#64;Resource
* private volatile SendNotification sender;
* ...
* private void updated() {
* Notification n = new Notification(...);
* sender.sendNotification(n);
* }
* }
* </pre>
*
* <p>A field to be injected must not be static. It is recommended that
* such fields be declared {@code volatile}.</p>
*
* <p>It is also possible to use the <code>&#64;Resource</code> annotation on
* methods. Such a method must have a {@code void} return type and a single
* argument of the appropriate type, for example {@code ObjectName}.</p>
*
* <p>Any number of fields and methods may have the <code>&#64;Resource</code>
* annotation. All fields and methods with type {@code ObjectName}
* (for example) will receive the same {@code ObjectName} value.</p>
*
* <p>Resource injection is available for all types of MBeans, not just
* Standard MBeans.</p>
*
* <p>If an MBean implements the {@link DynamicWrapperMBean} interface then
* resource injection happens on the object returned by that interface's
* {@link DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method
* rather than on the MBean object itself.
*
* <p>Resource injection happens after the {@link #preRegister preRegister}
* method is called (if any), and before the MBean is actually registered
* in the MBean Server. If a <code>&#64;Resource</code> method throws
* an exception, the effect is the same as if {@code preRegister} had
* thrown the exception. In particular it will prevent the MBean from being
* registered.</p>
*
* <p>Resource injection can be used on a field or method where the type
* is a parent of the injected type, if the injected type is explicitly
* specified in the <code>&#64;Resource</code> annotation. For example:</p>
*
* <pre>
* &#64;Resource(type = MBeanServer.class)
* private volatile MBeanServerConnection mbsc;
* </pre>
*
* <p>Formally, suppose <em>R</em> is the type in the <code>&#64;Resource</code>
* annotation and <em>T</em> is the type of the method parameter or field.
* Then one of <em>R</em> and <em>T</em> must be a subtype of the other
* (or they must be the same type). Injection happens if this subtype
* is {@code MBeanServer}, {@code ObjectName}, or {@code SendNotification}.
* Otherwise the <code>&#64;Resource</code> annotation is ignored.</p>
*
* <p>Resource injection in MBeans is new in version 2.0 of the JMX API.</p>
*
* @since 1.5
*/
@ -38,12 +130,12 @@ public interface MBeanRegistration {
/**
* Allows the MBean to perform any operations it needs before
* being registered in the MBean server. If the name of the MBean
* being registered in the MBean Server. If the name of the MBean
* is not specified, the MBean can provide a name for its
* registration. If any exception is raised, the MBean will not be
* registered in the MBean server.
* registered in the MBean Server.
*
* @param server The MBean server in which the MBean will be registered.
* @param server The MBean Server in which the MBean will be registered.
*
* @param name The object name of the MBean. This name is null if
* the name parameter to one of the <code>createMBean</code> or
@ -57,7 +149,7 @@ public interface MBeanRegistration {
* the returned value.
*
* @exception java.lang.Exception This exception will be caught by
* the MBean server and re-thrown as an {@link
* the MBean Server and re-thrown as an {@link
* MBeanRegistrationException}.
*/
public ObjectName preRegister(MBeanServer server,

View File

@ -61,7 +61,7 @@ import javax.management.loading.ClassLoaderRepository;
* <CODE>ObjectName</CODE> is: <BR>
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.</p>
*
* <p>An object obtained from the {@link
* <p id="security">An object obtained from the {@link
* MBeanServerFactory#createMBeanServer(String) createMBeanServer} or
* {@link MBeanServerFactory#newMBeanServer(String) newMBeanServer}
* methods of the {@link MBeanServerFactory} class applies security
@ -661,13 +661,16 @@ public interface MBeanServer extends MBeanServerConnection {
ReflectionException;
/**
* <p>Return the {@link java.lang.ClassLoader} that was used for
* loading the class of the named MBean.</p>
* <p>Return the {@link java.lang.ClassLoader} that was used for loading
* the class of the named MBean. If the MBean implements the {@link
* DynamicWrapperMBean} interface, then the returned value is the
* result of the {@link DynamicWrapperMBean#getWrappedClassLoader()}
* method.</p>
*
* @param mbeanName The ObjectName of the MBean.
*
* @return The ClassLoader used for that MBean. If <var>l</var>
* is the MBean's actual ClassLoader, and <var>r</var> is the
* is the value specified by the rules above, and <var>r</var> is the
* returned value, then either:
*
* <ul>

View File

@ -839,6 +839,12 @@ public interface MBeanServerConnection {
*
* <p>Otherwise, the result is false.</p>
*
* <p>If the MBean implements the {@link DynamicWrapperMBean}
* interface, then in the above rules X is the result of the MBean's {@link
* DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method and L
* is the result of its {@link DynamicWrapperMBean#getWrappedClassLoader()
* getWrappedClassLoader()} method.
*
* @param name The <CODE>ObjectName</CODE> of the MBean.
* @param className The name of the class.
*

View File

@ -27,6 +27,7 @@ package javax.management;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@ -57,11 +58,13 @@ import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
/**
<p>Annotation to mark an interface explicitly as being an MXBean
interface, or as not being an MXBean interface. By default, an
<p>Annotation to mark a class or interface explicitly as being an MXBean,
or as not being an MXBean. By default, an
interface is an MXBean interface if its name ends with {@code
MXBean}, as in {@code SomethingMXBean}. The following interfaces
are MXBean interfaces:</p>
MXBean}, as in {@code SomethingMXBean}. A class is never an MXBean by
default.</p>
<p>The following interfaces are MXBean interfaces:</p>
<pre>
public interface WhatsitMXBean {}
@ -82,6 +85,11 @@ import javax.management.openmbean.TabularType;
public interface MisleadingMXBean {}
</pre>
<p>A class can be annotated with {@code @MXBean} to indicate that it
is an MXBean. In this case, its methods should have <code>&#64;{@link
ManagedAttribute}</code> or <code>&#64;{@link ManagedOperation}</code>
annotations, as described for <code>&#64;{@link MBean}</code>.</p>
<h3 id="MXBean-spec">MXBean specification</h3>
<p>The MXBean concept provides a simple way to code an MBean
@ -1246,9 +1254,24 @@ public interface Node {
@since 1.6
*/
/*
* This annotation is @Inherited because if an MXBean is defined as a
* class using annotations, then its subclasses are also MXBeans.
* For example:
* @MXBean
* public class Super {
* @ManagedAttribute
* public String getName() {...}
* }
* public class Sub extends Super {}
* Here Sub is an MXBean.
*
* The @Inherited annotation has no effect when applied to an interface.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface MXBean {
/**
True if the annotated interface is an MXBean interface.

View File

@ -0,0 +1,64 @@
/*
* Copyright 2007 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 javax.management;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>Indicates that a method in an MBean class defines an MBean attribute.
* This annotation must be applied to a public method of a public class
* that is itself annotated with an {@link MBean @MBean} or
* {@link MXBean @MXBean} annotation, or inherits such an annotation from
* a superclass.</p>
*
* <p>The annotated method must be a getter or setter. In other words,
* it must look like one of the following...</p>
*
* <pre>
* <i>T</i> get<i>Foo</i>()
* void set<i>Foo</i>(<i>T</i> param)
* </pre>
*
* <p>...where <i>{@code T}</i> is any type and <i>{@code Foo}</i> is the
* name of the attribute. For any attribute <i>{@code Foo}</i>, if only
* a {@code get}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
* annotation, then <i>{@code Foo}</i> is a read-only attribute. If only
* a {@code set}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
* annotation, then <i>{@code Foo}</i> is a write-only attribute. If
* both {@code get}<i>{@code Foo}</i> and {@code set}<i>{@code Foo}</i>
* methods have the annotation, then <i>{@code Foo}</i> is a read-write
* attribute. In this last case, the type <i>{@code T}</i> must be the
* same in both methods.</p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ManagedAttribute {
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2007 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 javax.management;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>Indicates that a method in an MBean class defines an MBean operation.
* This annotation can be applied to:</p>
*
* <ul>
* <li>A public method of a public class
* that is itself annotated with an {@link MBean @MBean} or
* {@link MXBean @MXBean} annotation, or inherits such an annotation from
* a superclass.</li>
* <li>A method of an MBean or MXBean interface.
* </ul>
*
* <p>Every method in an MBean or MXBean interface defines an MBean
* operation even without this annotation, but the annotation allows
* you to specify the impact of the operation:</p>
*
* <pre>
* public interface ConfigurationMBean {
* {@code @ManagedOperation}(impact = {@link Impact#ACTION Impact.ACTION})
* public void save();
* ...
* }
* </pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ManagedOperation {
/**
* <p>The impact of this operation, as shown by
* {@link MBeanOperationInfo#getImpact()}.
*/
Impact impact() default Impact.UNKNOWN;
}

View File

@ -91,6 +91,7 @@ class NotQueryExp extends QueryEval implements QueryExp {
return "not (" + exp + ")";
}
@Override
String toQueryString() {
return "not (" + Query.toString(exp) + ")";
}

View File

@ -58,7 +58,8 @@ import com.sun.jmx.remote.util.ClassLogger;
*
* @since 1.5
*/
public class NotificationBroadcasterSupport implements NotificationEmitter {
public class NotificationBroadcasterSupport
implements NotificationEmitter, SendNotification {
/**
* Constructs a NotificationBroadcasterSupport where each listener is invoked by the
* thread sending the notification. This constructor is equivalent to

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