提交 0b6e29e7 编写于 作者: V vinnie

Merge

...@@ -48,7 +48,6 @@ FILES_c = \ ...@@ -48,7 +48,6 @@ FILES_c = \
Proxy.c \ Proxy.c \
RandomAccessFile.c \ RandomAccessFile.c \
RandomAccessFile_md.c \ RandomAccessFile_md.c \
ResourceBundle.c \
Runtime.c \ Runtime.c \
SecurityManager.c \ SecurityManager.c \
Shutdown.c \ Shutdown.c \
......
...@@ -134,7 +134,6 @@ SUNWprivate_1.1 { ...@@ -134,7 +134,6 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_longBitsToDouble;
...@@ -233,7 +232,6 @@ SUNWprivate_1.1 { ...@@ -233,7 +232,6 @@ SUNWprivate_1.1 {
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext;
Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
......
...@@ -73,7 +73,6 @@ text: .text%writeBytes; ...@@ -73,7 +73,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -78,7 +78,6 @@ text: .text%writeBytes; ...@@ -78,7 +78,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -74,7 +74,6 @@ text: .text%writeBytes; ...@@ -74,7 +74,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -106,7 +106,21 @@ FILES_cpp_shared = \ ...@@ -106,7 +106,21 @@ FILES_cpp_shared = \
OpenTypeLayoutEngine.cpp \ OpenTypeLayoutEngine.cpp \
ThaiLayoutEngine.cpp \ ThaiLayoutEngine.cpp \
ScriptAndLanguageTags.cpp \ ScriptAndLanguageTags.cpp \
FontInstanceAdapter.cpp FontInstanceAdapter.cpp \
ContextualGlyphInsertionProc2.cpp \
ContextualGlyphSubstProc2.cpp \
GXLayoutEngine2.cpp \
IndicRearrangementProcessor2.cpp \
LigatureSubstProc2.cpp \
MorphTables2.cpp \
NonContextualGlyphSubstProc2.cpp \
SegmentArrayProcessor2.cpp \
SegmentSingleProcessor2.cpp \
SimpleArrayProcessor2.cpp \
SingleTableProcessor2.cpp \
StateTableProcessor2.cpp \
SubtableProcessor2.cpp \
TrimmedArrayProcessor2.cpp
ifeq ($(PLATFORM),windows) ifeq ($(PLATFORM),windows)
......
...@@ -134,7 +134,6 @@ SUNWprivate_1.1 { ...@@ -134,7 +134,6 @@ SUNWprivate_1.1 {
Java_java_lang_ClassLoader_00024NativeLibrary_load; Java_java_lang_ClassLoader_00024NativeLibrary_load;
Java_java_lang_ClassLoader_00024NativeLibrary_unload; Java_java_lang_ClassLoader_00024NativeLibrary_unload;
Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib; Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib;
Java_java_lang_ClassLoader_getCaller;
Java_java_lang_ClassLoader_registerNatives; Java_java_lang_ClassLoader_registerNatives;
Java_java_lang_Compiler_registerNatives; Java_java_lang_Compiler_registerNatives;
Java_java_lang_Double_longBitsToDouble; Java_java_lang_Double_longBitsToDouble;
...@@ -233,7 +232,6 @@ SUNWprivate_1.1 { ...@@ -233,7 +232,6 @@ SUNWprivate_1.1 {
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_getStackAccessControlContext; Java_java_security_AccessController_getStackAccessControlContext;
Java_java_security_AccessController_getInheritedAccessControlContext; Java_java_security_AccessController_getInheritedAccessControlContext;
Java_java_util_ResourceBundle_getClassContext;
Java_java_util_TimeZone_getSystemTimeZoneID; Java_java_util_TimeZone_getSystemTimeZoneID;
Java_java_util_TimeZone_getSystemGMTOffsetID; Java_java_util_TimeZone_getSystemGMTOffsetID;
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8; Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
......
...@@ -78,7 +78,6 @@ text: .text%writeBytes; ...@@ -78,7 +78,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -74,7 +74,6 @@ text: .text%writeBytes; ...@@ -74,7 +74,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -73,7 +73,6 @@ text: .text%writeBytes; ...@@ -73,7 +73,6 @@ text: .text%writeBytes;
# Test Sleep # Test Sleep
# Test IntToString # Test IntToString
# Test LoadToolkit # Test LoadToolkit
text: .text%Java_java_util_ResourceBundle_getClassContext;
text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; text: .text%Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
text: .text%JNU_GetEnv; text: .text%JNU_GetEnv;
text: .text%Java_java_io_UnixFileSystem_checkAccess; text: .text%Java_java_io_UnixFileSystem_checkAccess;
......
...@@ -170,7 +170,7 @@ public class LWWindowPeer ...@@ -170,7 +170,7 @@ public class LWWindowPeer
setTitle(((Dialog) getTarget()).getTitle()); setTitle(((Dialog) getTarget()).getTitle());
} }
setAlwaysOnTop(getTarget().isAlwaysOnTop()); updateAlwaysOnTopState();
updateMinimumSize(); updateMinimumSize();
final Shape shape = getTarget().getShape(); final Shape shape = getTarget().getShape();
...@@ -357,8 +357,8 @@ public class LWWindowPeer ...@@ -357,8 +357,8 @@ public class LWWindowPeer
} }
@Override @Override
public void setAlwaysOnTop(boolean value) { public void updateAlwaysOnTopState() {
platformWindow.setAlwaysOnTop(value); platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop());
} }
@Override @Override
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -180,7 +180,7 @@ class CFileDialog implements FileDialogPeer { ...@@ -180,7 +180,7 @@ class CFileDialog implements FileDialogPeer {
} }
@Override @Override
public void setAlwaysOnTop(boolean alwaysOnTop) { public void updateAlwaysOnTopState() {
} }
@Override @Override
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -87,7 +87,7 @@ public class CPrinterDialogPeer extends LWWindowPeer { ...@@ -87,7 +87,7 @@ public class CPrinterDialogPeer extends LWWindowPeer {
} }
// 1.6 peer method // 1.6 peer method
public void setAlwaysOnTop(boolean value) { public void updateAlwaysOnTopState() {
// no-op, since we just show the native print dialog // no-op, since we just show the native print dialog
} }
......
...@@ -243,12 +243,17 @@ public class JPEGImageReader extends ImageReader { ...@@ -243,12 +243,17 @@ public class JPEGImageReader extends ImageReader {
* sending warnings to listeners. * sending warnings to listeners.
*/ */
protected void warningOccurred(int code) { protected void warningOccurred(int code) {
cbLock.lock();
try {
if ((code < 0) || (code > MAX_WARNING)){ if ((code < 0) || (code > MAX_WARNING)){
throw new InternalError("Invalid warning index"); throw new InternalError("Invalid warning index");
} }
processWarningOccurred processWarningOccurred
("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources", ("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources",
Integer.toString(code)); Integer.toString(code));
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -265,7 +270,12 @@ public class JPEGImageReader extends ImageReader { ...@@ -265,7 +270,12 @@ public class JPEGImageReader extends ImageReader {
* library warnings from being printed to stderr. * library warnings from being printed to stderr.
*/ */
protected void warningWithMessage(String msg) { protected void warningWithMessage(String msg) {
cbLock.lock();
try {
processWarningOccurred(msg); processWarningOccurred(msg);
} finally {
cbLock.unlock();
}
} }
public void setInput(Object input, public void setInput(Object input,
...@@ -274,18 +284,55 @@ public class JPEGImageReader extends ImageReader { ...@@ -274,18 +284,55 @@ public class JPEGImageReader extends ImageReader {
{ {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.setInput(input, seekForwardOnly, ignoreMetadata); super.setInput(input, seekForwardOnly, ignoreMetadata);
this.ignoreMetadata = ignoreMetadata; this.ignoreMetadata = ignoreMetadata;
resetInternalState(); resetInternalState();
iis = (ImageInputStream) input; // Always works iis = (ImageInputStream) input; // Always works
setSource(structPointer, iis); setSource(structPointer);
} finally { } finally {
clearThreadLock(); clearThreadLock();
} }
} }
private native void setSource(long structPointer, /**
ImageInputStream source); * This method is called from native code in order to fill
* native input buffer.
*
* We block any attempt to change the reading state during this
* method, in order to prevent a corruption of the native decoder
* state.
*
* @return number of bytes read from the stream.
*/
private int readInputData(byte[] buf, int off, int len) throws IOException {
cbLock.lock();
try {
return iis.read(buf, off, len);
} finally {
cbLock.unlock();
}
}
/**
* This method is called from the native code in order to
* skip requested number of bytes in the input stream.
*
* @param n
* @return
* @throws IOException
*/
private long skipInputBytes(long n) throws IOException {
cbLock.lock();
try {
return iis.skipBytes(n);
} finally {
cbLock.unlock();
}
}
private native void setSource(long structPointer);
private void checkTablesOnly() throws IOException { private void checkTablesOnly() throws IOException {
if (debug) { if (debug) {
...@@ -337,6 +384,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -337,6 +384,8 @@ public class JPEGImageReader extends ImageReader {
public int getNumImages(boolean allowSearch) throws IOException { public int getNumImages(boolean allowSearch) throws IOException {
setThreadLock(); setThreadLock();
try { // locked thread try { // locked thread
cbLock.check();
return getNumImagesOnThread(allowSearch); return getNumImagesOnThread(allowSearch);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -536,8 +585,13 @@ public class JPEGImageReader extends ImageReader { ...@@ -536,8 +585,13 @@ public class JPEGImageReader extends ImageReader {
if (debug) { if (debug) {
System.out.println("pushing back " + num + " bytes"); System.out.println("pushing back " + num + " bytes");
} }
cbLock.lock();
try {
iis.seek(iis.getStreamPosition()-num); iis.seek(iis.getStreamPosition()-num);
// The buffer is clear after this, so no need to set haveSeeked. // The buffer is clear after this, so no need to set haveSeeked.
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -644,7 +698,12 @@ public class JPEGImageReader extends ImageReader { ...@@ -644,7 +698,12 @@ public class JPEGImageReader extends ImageReader {
* Ignore this profile. * Ignore this profile.
*/ */
iccCS = null; iccCS = null;
cbLock.lock();
try {
warningOccurred(WARNING_IGNORE_INVALID_ICC); warningOccurred(WARNING_IGNORE_INVALID_ICC);
} finally {
cbLock.unlock();
}
} }
} }
} }
...@@ -653,6 +712,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -653,6 +712,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
return width; return width;
...@@ -665,6 +725,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -665,6 +725,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
return height; return height;
...@@ -693,6 +754,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -693,6 +754,8 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
...@@ -716,6 +779,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -716,6 +779,7 @@ public class JPEGImageReader extends ImageReader {
private Iterator getImageTypesOnThread(int imageIndex) private Iterator getImageTypesOnThread(int imageIndex)
throws IOException { throws IOException {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
...@@ -931,6 +995,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -931,6 +995,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (!tablesOnlyChecked) { if (!tablesOnlyChecked) {
cbLock.check();
checkTablesOnly(); checkTablesOnly();
} }
return streamMetadata; return streamMetadata;
...@@ -951,6 +1016,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -951,6 +1016,8 @@ public class JPEGImageReader extends ImageReader {
return imageMetadata; return imageMetadata;
} }
cbLock.check();
gotoImage(imageIndex); gotoImage(imageIndex);
imageMetadata = new JPEGMetadata(false, false, iis, this); imageMetadata = new JPEGMetadata(false, false, iis, this);
...@@ -967,6 +1034,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -967,6 +1034,7 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
try { try {
readInternal(imageIndex, param, false); readInternal(imageIndex, param, false);
} catch (RuntimeException e) { } catch (RuntimeException e) {
...@@ -1196,6 +1264,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1196,6 +1264,8 @@ public class JPEGImageReader extends ImageReader {
} }
target.setRect(destROI.x, destROI.y + y, raster); target.setRect(destROI.x, destROI.y + y, raster);
cbLock.lock();
try {
processImageUpdate(image, processImageUpdate(image,
destROI.x, destROI.y+y, destROI.x, destROI.y+y,
raster.getWidth(), 1, raster.getWidth(), 1,
...@@ -1249,6 +1319,9 @@ public class JPEGImageReader extends ImageReader { ...@@ -1249,6 +1319,9 @@ public class JPEGImageReader extends ImageReader {
processImageProgress(percentOfPass * 100.0F); processImageProgress(percentOfPass * 100.0F);
} }
} }
} finally {
cbLock.unlock();
}
} }
private void initProgressData() { private void initProgressData() {
...@@ -1260,6 +1333,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1260,6 +1333,8 @@ public class JPEGImageReader extends ImageReader {
} }
private void passStarted (int pass) { private void passStarted (int pass) {
cbLock.lock();
try {
this.pass = pass; this.pass = pass;
previousPassPercentage = percentToDate; previousPassPercentage = percentToDate;
processPassStarted(image, processPassStarted(image,
...@@ -1269,24 +1344,47 @@ public class JPEGImageReader extends ImageReader { ...@@ -1269,24 +1344,47 @@ public class JPEGImageReader extends ImageReader {
0, 0, 0, 0,
1,1, 1,1,
destinationBands); destinationBands);
} finally {
cbLock.unlock();
}
} }
private void passComplete () { private void passComplete () {
cbLock.lock();
try {
processPassComplete(image); processPassComplete(image);
} finally {
cbLock.unlock();
}
} }
void thumbnailStarted(int thumbnailIndex) { void thumbnailStarted(int thumbnailIndex) {
cbLock.lock();
try {
processThumbnailStarted(currentImage, thumbnailIndex); processThumbnailStarted(currentImage, thumbnailIndex);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailProgress(float percentageDone) { void thumbnailProgress(float percentageDone) {
cbLock.lock();
try {
processThumbnailProgress(percentageDone); processThumbnailProgress(percentageDone);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailComplete() { void thumbnailComplete() {
cbLock.lock();
try {
processThumbnailComplete(); processThumbnailComplete();
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -1310,6 +1408,11 @@ public class JPEGImageReader extends ImageReader { ...@@ -1310,6 +1408,11 @@ public class JPEGImageReader extends ImageReader {
public void abort() { public void abort() {
setThreadLock(); setThreadLock();
try { try {
/**
* NB: we do not check the call back lock here,
* we allow to abort the reader any time.
*/
super.abort(); super.abort();
abortRead(structPointer); abortRead(structPointer);
} finally { } finally {
...@@ -1332,6 +1435,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -1332,6 +1435,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
Raster retval = null; Raster retval = null;
try { try {
cbLock.check();
/* /*
* This could be further optimized by not resetting the dest. * This could be further optimized by not resetting the dest.
* offset and creating a translated raster in readInternal() * offset and creating a translated raster in readInternal()
...@@ -1371,6 +1475,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1371,6 +1475,8 @@ public class JPEGImageReader extends ImageReader {
public int getNumThumbnails(int imageIndex) throws IOException { public int getNumThumbnails(int imageIndex) throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
getImageMetadata(imageIndex); // checks iis state for us getImageMetadata(imageIndex); // checks iis state for us
// Now check the jfif segments // Now check the jfif segments
JFIFMarkerSegment jfif = JFIFMarkerSegment jfif =
...@@ -1391,6 +1497,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1391,6 +1497,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1409,6 +1517,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1409,6 +1517,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1428,6 +1538,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1428,6 +1538,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1468,6 +1580,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -1468,6 +1580,7 @@ public class JPEGImageReader extends ImageReader {
public void reset() { public void reset() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.reset(); super.reset();
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1479,6 +1592,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1479,6 +1592,8 @@ public class JPEGImageReader extends ImageReader {
public void dispose() { public void dispose() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (structPointer != 0) { if (structPointer != 0) {
disposerRecord.dispose(); disposerRecord.dispose();
structPointer = 0; structPointer = 0;
...@@ -1540,6 +1655,36 @@ public class JPEGImageReader extends ImageReader { ...@@ -1540,6 +1655,36 @@ public class JPEGImageReader extends ImageReader {
theThread = null; theThread = null;
} }
} }
private CallBackLock cbLock = new CallBackLock();
private static class CallBackLock {
private State lockState;
CallBackLock() {
lockState = State.Unlocked;
}
void check() {
if (lockState != State.Unlocked) {
throw new IllegalStateException("Access to the reader is not allowed");
}
}
private void lock() {
lockState = State.Locked;
}
private void unlock() {
lockState = State.Unlocked;
}
private static enum State {
Unlocked,
Locked
}
}
} }
/** /**
......
...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter {
return null; return null;
} }
}); });
initWriterIDs(ImageOutputStream.class, initWriterIDs(JPEGQTable.class,
JPEGQTable.class,
JPEGHuffmanTable.class); JPEGHuffmanTable.class);
} }
...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter {
public void setOutput(Object output) { public void setOutput(Object output) {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.setOutput(output); // validates output super.setOutput(output); // validates output
resetInternalState(); resetInternalState();
ios = (ImageOutputStream) output; // so this will always work ios = (ImageOutputStream) output; // so this will always work
// Set the native destination // Set the native destination
setDest(structPointer, ios); setDest(structPointer);
} finally { } finally {
clearThreadLock(); clearThreadLock();
} }
...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter {
ImageWriteParam param) throws IOException { ImageWriteParam param) throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
writeOnThread(streamMetadata, image, param); writeOnThread(streamMetadata, image, param);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1082,6 +1085,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1082,6 +1085,8 @@ public class JPEGImageWriter extends ImageWriter {
haveMetadata, haveMetadata,
restartInterval); restartInterval);
cbLock.lock();
try {
if (aborted) { if (aborted) {
processWriteAborted(); processWriteAborted();
} else { } else {
...@@ -1089,6 +1094,9 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1089,6 +1094,9 @@ public class JPEGImageWriter extends ImageWriter {
} }
ios.flush(); ios.flush();
} finally {
cbLock.unlock();
}
currentImage++; // After a successful write currentImage++; // After a successful write
} }
...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
prepareWriteSequenceOnThread(streamMetadata); prepareWriteSequenceOnThread(streamMetadata);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter {
public void endWriteSequence() throws IOException { public void endWriteSequence() throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter {
public synchronized void abort() { public synchronized void abort() {
setThreadLock(); setThreadLock();
try { try {
/**
* NB: we do not check the call back lock here, we allow to abort
* the reader any time.
*/
super.abort(); super.abort();
abortWrite(structPointer); abortWrite(structPointer);
} finally { } finally {
...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter {
public void reset() { public void reset() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.reset(); super.reset();
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter {
public void dispose() { public void dispose() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (structPointer != 0) { if (structPointer != 0) {
disposerRecord.dispose(); disposerRecord.dispose();
structPointer = 0; structPointer = 0;
...@@ -1251,6 +1273,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1251,6 +1273,8 @@ public class JPEGImageWriter extends ImageWriter {
* sending warnings to listeners. * sending warnings to listeners.
*/ */
void warningOccurred(int code) { void warningOccurred(int code) {
cbLock.lock();
try {
if ((code < 0) || (code > MAX_WARNING)){ if ((code < 0) || (code > MAX_WARNING)){
throw new InternalError("Invalid warning index"); throw new InternalError("Invalid warning index");
} }
...@@ -1258,6 +1282,9 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1258,6 +1282,9 @@ public class JPEGImageWriter extends ImageWriter {
(currentImage, (currentImage,
"com.sun.imageio.plugins.jpeg.JPEGImageWriterResources", "com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
Integer.toString(code)); Integer.toString(code));
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter {
* library warnings from being printed to stderr. * library warnings from being printed to stderr.
*/ */
void warningWithMessage(String msg) { void warningWithMessage(String msg) {
cbLock.lock();
try {
processWarningOccurred(currentImage, msg); processWarningOccurred(currentImage, msg);
} finally {
cbLock.unlock();
}
} }
void thumbnailStarted(int thumbnailIndex) { void thumbnailStarted(int thumbnailIndex) {
cbLock.lock();
try {
processThumbnailStarted(currentImage, thumbnailIndex); processThumbnailStarted(currentImage, thumbnailIndex);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailProgress(float percentageDone) { void thumbnailProgress(float percentageDone) {
cbLock.lock();
try {
processThumbnailProgress(percentageDone); processThumbnailProgress(percentageDone);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailComplete() { void thumbnailComplete() {
cbLock.lock();
try {
processThumbnailComplete(); processThumbnailComplete();
} finally {
cbLock.unlock();
}
} }
///////// End of Package-access API ///////// End of Package-access API
...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter {
////////////// Native methods and callbacks ////////////// Native methods and callbacks
/** Sets up static native structures. */ /** Sets up static native structures. */
private static native void initWriterIDs(Class iosClass, private static native void initWriterIDs(Class qTableClass,
Class qTableClass,
Class huffClass); Class huffClass);
/** Sets up per-writer native structure and returns a pointer to it. */ /** Sets up per-writer native structure and returns a pointer to it. */
private native long initJPEGImageWriter(); private native long initJPEGImageWriter();
/** Sets up native structures for output stream */ /** Sets up native structures for output stream */
private native void setDest(long structPointer, private native void setDest(long structPointer);
ImageOutputStream ios);
/** /**
* Returns <code>true</code> if the write was aborted. * Returns <code>true</code> if the write was aborted.
...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter {
} }
raster.setRect(sourceLine); raster.setRect(sourceLine);
if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines
cbLock.lock();
try {
processImageProgress((float) y / (float) sourceHeight * 100.0F); processImageProgress((float) y / (float) sourceHeight * 100.0F);
} finally {
cbLock.unlock();
}
} }
} }
...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter {
} }
} }
/**
* This method is called from native code in order to write encoder
* output to the destination.
*
* We block any attempt to change the writer state during this
* method, in order to prevent a corruption of the native encoder
* state.
*/
private void writeOutputData(byte[] data, int offset, int len)
throws IOException
{
cbLock.lock();
try {
ios.write(data, offset, len);
} finally {
cbLock.unlock();
}
}
private Thread theThread = null; private Thread theThread = null;
private int theLockCount = 0; private int theLockCount = 0;
...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter {
theThread = null; theThread = null;
} }
} }
private CallBackLock cbLock = new CallBackLock();
private static class CallBackLock {
private State lockState;
CallBackLock() {
lockState = State.Unlocked;
}
void check() {
if (lockState != State.Unlocked) {
throw new IllegalStateException("Access to the writer is not allowed");
}
}
private void lock() {
lockState = State.Locked;
}
private void unlock() {
lockState = State.Unlocked;
}
private static enum State {
Unlocked,
Locked
}
}
} }
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,6 +32,7 @@ import java.io.IOException; ...@@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.security.Permission; import java.security.Permission;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
...@@ -213,7 +214,6 @@ public class MBeanInstantiator { ...@@ -213,7 +214,6 @@ public class MBeanInstantiator {
Object moi; Object moi;
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
Constructor<?> cons = findConstructor(theClass, null); Constructor<?> cons = findConstructor(theClass, null);
...@@ -224,6 +224,7 @@ public class MBeanInstantiator { ...@@ -224,6 +224,7 @@ public class MBeanInstantiator {
// Instantiate the new object // Instantiate the new object
try { try {
ReflectUtil.checkPackageAccess(theClass); ReflectUtil.checkPackageAccess(theClass);
ensureClassAccess(theClass);
moi= cons.newInstance(); moi= cons.newInstance();
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// Wrap the exception. // Wrap the exception.
...@@ -270,7 +271,6 @@ public class MBeanInstantiator { ...@@ -270,7 +271,6 @@ public class MBeanInstantiator {
checkMBeanPermission(theClass, null, null, "instantiate"); checkMBeanPermission(theClass, null, null, "instantiate");
// Instantiate the new object // Instantiate the new object
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
final Class<?>[] tab; final Class<?>[] tab;
...@@ -300,6 +300,7 @@ public class MBeanInstantiator { ...@@ -300,6 +300,7 @@ public class MBeanInstantiator {
} }
try { try {
ReflectUtil.checkPackageAccess(theClass); ReflectUtil.checkPackageAccess(theClass);
ensureClassAccess(theClass);
moi = cons.newInstance(params); moi = cons.newInstance(params);
} }
catch (NoSuchMethodError error) { catch (NoSuchMethodError error) {
...@@ -741,4 +742,13 @@ public class MBeanInstantiator { ...@@ -741,4 +742,13 @@ public class MBeanInstantiator {
sm.checkPermission(perm); sm.checkPermission(perm);
} }
} }
private static void ensureClassAccess(Class clazz)
throws IllegalAccessException
{
int mod = clazz.getModifiers();
if (!Modifier.isPublic(mod)) {
throw new IllegalAccessException("Class is not public and can't be instantiated");
}
}
} }
...@@ -56,7 +56,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -56,7 +56,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
// from simultaneous creation and destruction // from simultaneous creation and destruction
// reduces possibility of deadlock, compared to // reduces possibility of deadlock, compared to
// synchronizing to the class instance // synchronizing to the class instance
private Object traRecLock = new Object(); private final Object traRecLock = new Object();
// DEVICE ATTRIBUTES // DEVICE ATTRIBUTES
...@@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
This is necessary for Receivers retrieved via MidiSystem.getReceiver() This is necessary for Receivers retrieved via MidiSystem.getReceiver()
(which opens the device implicitely). (which opens the device implicitely).
*/ */
protected abstract class AbstractReceiver implements MidiDeviceReceiver { abstract class AbstractReceiver implements MidiDeviceReceiver {
private boolean open = true; private boolean open = true;
...@@ -483,24 +483,24 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -483,24 +483,24 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
Receiver. Therefore, subclasses should not override this method. Receiver. Therefore, subclasses should not override this method.
Instead, they should implement implSend(). Instead, they should implement implSend().
*/ */
public synchronized void send(MidiMessage message, long timeStamp) { @Override
if (open) { public final synchronized void send(final MidiMessage message,
implSend(message, timeStamp); final long timeStamp) {
} else { if (!open) {
throw new IllegalStateException("Receiver is not open"); throw new IllegalStateException("Receiver is not open");
} }
implSend(message, timeStamp);
} }
abstract void implSend(MidiMessage message, long timeStamp);
protected abstract void implSend(MidiMessage message, long timeStamp);
/** Close the Receiver. /** Close the Receiver.
* Here, the call to the magic method closeInternal() takes place. * Here, the call to the magic method closeInternal() takes place.
* Therefore, subclasses that override this method must call * Therefore, subclasses that override this method must call
* 'super.close()'. * 'super.close()'.
*/ */
public void close() { @Override
public final void close() {
open = false; open = false;
synchronized (AbstractMidiDevice.this.traRecLock) { synchronized (AbstractMidiDevice.this.traRecLock) {
AbstractMidiDevice.this.getReceiverList().remove(this); AbstractMidiDevice.this.getReceiverList().remove(this);
...@@ -508,11 +508,12 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -508,11 +508,12 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
AbstractMidiDevice.this.closeInternal(this); AbstractMidiDevice.this.closeInternal(this);
} }
public MidiDevice getMidiDevice() { @Override
public final MidiDevice getMidiDevice() {
return AbstractMidiDevice.this; return AbstractMidiDevice.this;
} }
protected boolean isOpen() { final boolean isOpen() {
return open; return open;
} }
......
...@@ -32,7 +32,7 @@ import javax.sound.midi.*; ...@@ -32,7 +32,7 @@ import javax.sound.midi.*;
* *
* @author Florian Bomers * @author Florian Bomers
*/ */
class FastShortMessage extends ShortMessage { final class FastShortMessage extends ShortMessage {
private int packedMsg; private int packedMsg;
public FastShortMessage(int packedMsg) throws InvalidMidiDataException { public FastShortMessage(int packedMsg) throws InvalidMidiDataException {
......
...@@ -32,7 +32,7 @@ import javax.sound.midi.*; ...@@ -32,7 +32,7 @@ import javax.sound.midi.*;
* *
* @author Florian Bomers * @author Florian Bomers
*/ */
class FastSysexMessage extends SysexMessage { final class FastSysexMessage extends SysexMessage {
FastSysexMessage(byte[] data) throws InvalidMidiDataException { FastSysexMessage(byte[] data) throws InvalidMidiDataException {
super(data); super(data);
......
...@@ -103,9 +103,9 @@ class MidiOutDevice extends AbstractMidiDevice { ...@@ -103,9 +103,9 @@ class MidiOutDevice extends AbstractMidiDevice {
class MidiOutReceiver extends AbstractReceiver { class MidiOutReceiver extends AbstractReceiver {
protected void implSend(MidiMessage message, long timeStamp) { void implSend(final MidiMessage message, final long timeStamp) {
int length = message.getLength(); final int length = message.getLength();
int status = message.getStatus(); final int status = message.getStatus();
if (length <= 3 && status != 0xF0 && status != 0xF7) { if (length <= 3 && status != 0xF0 && status != 0xF7) {
int packedMsg; int packedMsg;
if (message instanceof ShortMessage) { if (message instanceof ShortMessage) {
...@@ -140,11 +140,15 @@ class MidiOutDevice extends AbstractMidiDevice { ...@@ -140,11 +140,15 @@ class MidiOutDevice extends AbstractMidiDevice {
} }
nSendShortMessage(id, packedMsg, timeStamp); nSendShortMessage(id, packedMsg, timeStamp);
} else { } else {
final byte[] data;
if (message instanceof FastSysexMessage) { if (message instanceof FastSysexMessage) {
nSendLongMessage(id, ((FastSysexMessage) message).getReadOnlyMessage(), data = ((FastSysexMessage) message).getReadOnlyMessage();
length, timeStamp);
} else { } else {
nSendLongMessage(id, message.getMessage(), length, timeStamp); data = message.getMessage();
}
final int dataLength = Math.min(length, data.length);
if (dataLength > 0) {
nSendLongMessage(id, data, dataLength, timeStamp);
} }
} }
} }
......
...@@ -1026,7 +1026,7 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon ...@@ -1026,7 +1026,7 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon
class SequencerReceiver extends AbstractReceiver { class SequencerReceiver extends AbstractReceiver {
protected void implSend(MidiMessage message, long timeStamp) { void implSend(MidiMessage message, long timeStamp) {
if (recording) { if (recording) {
long tickPos = 0; long tickPos = 0;
......
/* /*
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2234,7 +2234,7 @@ public class Window extends Container implements Accessible { ...@@ -2234,7 +2234,7 @@ public class Window extends Container implements Accessible {
WindowPeer peer = (WindowPeer)this.peer; WindowPeer peer = (WindowPeer)this.peer;
synchronized(getTreeLock()) { synchronized(getTreeLock()) {
if (peer != null) { if (peer != null) {
peer.setAlwaysOnTop(alwaysOnTop); peer.updateAlwaysOnTopState();
} }
} }
} }
......
/* /*
* Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -53,15 +53,14 @@ public interface WindowPeer extends ContainerPeer { ...@@ -53,15 +53,14 @@ public interface WindowPeer extends ContainerPeer {
void toBack(); void toBack();
/** /**
* Sets if the window should always stay on top of all other windows or * Updates the window's always-on-top state.
* not. * Sets if the window should always stay
* * on top of all other windows or not.
* @param alwaysOnTop if the window should always stay on top of all other
* windows or not
* *
* @see Window#getAlwaysOnTop()
* @see Window#setAlwaysOnTop(boolean) * @see Window#setAlwaysOnTop(boolean)
*/ */
void setAlwaysOnTop(boolean alwaysOnTop); void updateAlwaysOnTopState();
/** /**
* Updates the window's focusable state. * Updates the window's focusable state.
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,7 +29,6 @@ import com.sun.beans.finder.BeanInfoFinder; ...@@ -29,7 +29,6 @@ import com.sun.beans.finder.BeanInfoFinder;
import com.sun.beans.finder.PropertyEditorFinder; import com.sun.beans.finder.PropertyEditorFinder;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
...@@ -42,7 +41,7 @@ import java.util.WeakHashMap; ...@@ -42,7 +41,7 @@ import java.util.WeakHashMap;
*/ */
final class ThreadGroupContext { final class ThreadGroupContext {
private static final Map<ThreadGroup, ThreadGroupContext> contexts = new WeakHashMap<>(); private static final WeakIdentityMap<ThreadGroupContext> contexts = new WeakIdentityMap<>();
/** /**
* Returns the appropriate {@code AppContext} for the caller, * Returns the appropriate {@code AppContext} for the caller,
...@@ -69,6 +68,8 @@ final class ThreadGroupContext { ...@@ -69,6 +68,8 @@ final class ThreadGroupContext {
private BeanInfoFinder beanInfoFinder; private BeanInfoFinder beanInfoFinder;
private PropertyEditorFinder propertyEditorFinder; private PropertyEditorFinder propertyEditorFinder;
private ThreadGroupContext() {
}
boolean isDesignTime() { boolean isDesignTime() {
return this.isDesignTime; return this.isDesignTime;
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.beans;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* Hash table based mapping, which uses weak references to store keys
* and reference-equality in place of object-equality to compare them.
* An entry will automatically be removed when its key is no longer
* in ordinary use. Both null values and the null key are supported.
*
* @see java.util.IdentityHashMap
* @see java.util.WeakHashMap
*/
final class WeakIdentityMap<T> {
private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two
private static final Object NULL = new Object(); // special object for null key
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
private Entry<T>[] table = newTable(1<<3); // table's length MUST be a power of two
private int threshold = 6; // the next size value at which to resize
private int size = 0; // the number of key-value mappings
public T get(Object key) {
removeStaleEntries();
if (key == null) {
key = NULL;
}
int hash = key.hashCode();
int index = getIndex(this.table, hash);
for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
if (entry.isMatched(key, hash)) {
return entry.value;
}
}
return null;
}
public T put(Object key, T value) {
removeStaleEntries();
if (key == null) {
key = NULL;
}
int hash = key.hashCode();
int index = getIndex(this.table, hash);
for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
if (entry.isMatched(key, hash)) {
T oldValue = entry.value;
entry.value = value;
return oldValue;
}
}
this.table[index] = new Entry<T>(key, hash, value, this.queue, this.table[index]);
if (++this.size >= this.threshold) {
if (this.table.length == MAXIMUM_CAPACITY) {
this.threshold = Integer.MAX_VALUE;
}
else {
removeStaleEntries();
Entry<T>[] table = newTable(this.table.length * 2);
transfer(this.table, table);
// If ignoring null elements and processing ref queue caused massive
// shrinkage, then restore old table. This should be rare, but avoids
// unbounded expansion of garbage-filled tables.
if (this.size >= this.threshold / 2) {
this.table = table;
this.threshold *= 2;
}
else {
transfer(table, this.table);
}
}
}
return null;
}
private void removeStaleEntries() {
for (Object ref = this.queue.poll(); ref != null; ref = this.queue.poll()) {
@SuppressWarnings("unchecked")
Entry<T> entry = (Entry<T>) ref;
int index = getIndex(this.table, entry.hash);
Entry<T> prev = this.table[index];
Entry<T> current = prev;
while (current != null) {
Entry<T> next = current.next;
if (current == entry) {
if (prev == entry) {
this.table[index] = next;
}
else {
prev.next = next;
}
entry.value = null; // Help GC
entry.next = null; // Help GC
this.size--;
break;
}
prev = current;
current = next;
}
}
}
private void transfer(Entry<T>[] oldTable, Entry<T>[] newTable) {
for (int i = 0; i < oldTable.length; i++) {
Entry<T> entry = oldTable[i];
oldTable[i] = null;
while (entry != null) {
Entry<T> next = entry.next;
Object key = entry.get();
if (key == null) {
entry.value = null; // Help GC
entry.next = null; // Help GC
this.size--;
}
else {
int index = getIndex(newTable, entry.hash);
entry.next = newTable[index];
newTable[index] = entry;
}
entry = next;
}
}
}
@SuppressWarnings("unchecked")
private Entry<T>[] newTable(int length) {
return (Entry<T>[]) new Entry<?>[length];
}
private static int getIndex(Entry<?>[] table, int hash) {
return hash & (table.length - 1);
}
private static class Entry<T> extends WeakReference<Object> {
private final int hash;
private T value;
private Entry<T> next;
Entry(Object key, int hash, T value, ReferenceQueue<Object> queue, Entry<T> next) {
super(key, queue);
this.hash = hash;
this.value = value;
this.next = next;
}
boolean isMatched(Object key, int hash) {
return (this.hash == hash) && (key == get());
}
}
}
...@@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import static java.io.ObjectStreamClass.processQueue; import static java.io.ObjectStreamClass.processQueue;
import sun.reflect.misc.ReflectUtil;
/** /**
* An ObjectInputStream deserializes primitive data and objects previously * An ObjectInputStream deserializes primitive data and objects previously
...@@ -1519,6 +1520,12 @@ public class ObjectInputStream ...@@ -1519,6 +1520,12 @@ public class ObjectInputStream
} }
} }
private boolean isCustomSubclass() {
// Return true if this class is a custom subclass of ObjectInputStream
return getClass().getClassLoader()
!= ObjectInputStream.class.getClassLoader();
}
/** /**
* Reads in and returns class descriptor for a dynamic proxy class. Sets * Reads in and returns class descriptor for a dynamic proxy class. Sets
* passHandle to proxy class descriptor's assigned handle. If proxy class * passHandle to proxy class descriptor's assigned handle. If proxy class
...@@ -1548,6 +1555,15 @@ public class ObjectInputStream ...@@ -1548,6 +1555,15 @@ public class ObjectInputStream
try { try {
if ((cl = resolveProxyClass(ifaces)) == null) { if ((cl = resolveProxyClass(ifaces)) == null) {
resolveEx = new ClassNotFoundException("null class"); resolveEx = new ClassNotFoundException("null class");
} else if (!Proxy.isProxyClass(cl)) {
throw new InvalidClassException("Not a proxy");
} else {
// ReflectUtil.checkProxyPackageAccess makes a test
// equivalent to isCustomSubclass so there's no need
// to condition this call to isCustomSubclass == true here.
ReflectUtil.checkProxyPackageAccess(
getClass().getClassLoader(),
cl.getInterfaces());
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
resolveEx = ex; resolveEx = ex;
...@@ -1589,9 +1605,12 @@ public class ObjectInputStream ...@@ -1589,9 +1605,12 @@ public class ObjectInputStream
Class<?> cl = null; Class<?> cl = null;
ClassNotFoundException resolveEx = null; ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true); bin.setBlockDataMode(true);
final boolean checksRequired = isCustomSubclass();
try { try {
if ((cl = resolveClass(readDesc)) == null) { if ((cl = resolveClass(readDesc)) == null) {
resolveEx = new ClassNotFoundException("null class"); resolveEx = new ClassNotFoundException("null class");
} else if (checksRequired) {
ReflectUtil.checkPackageAccess(cl);
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
resolveEx = ex; resolveEx = ex;
......
...@@ -53,6 +53,7 @@ import java.util.Map; ...@@ -53,6 +53,7 @@ import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool; import sun.reflect.ConstantPool;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
...@@ -250,9 +251,11 @@ public final class Class<T> implements java.io.Serializable, ...@@ -250,9 +251,11 @@ public final class Class<T> implements java.io.Serializable,
* by this method fails * by this method fails
* @exception ClassNotFoundException if the class cannot be located * @exception ClassNotFoundException if the class cannot be located
*/ */
@CallerSensitive
public static Class<?> forName(String className) public static Class<?> forName(String className)
throws ClassNotFoundException { throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader()); return forName0(className, true,
ClassLoader.getClassLoader(Reflection.getCallerClass()));
} }
...@@ -317,6 +320,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -317,6 +320,7 @@ public final class Class<T> implements java.io.Serializable,
* @see java.lang.ClassLoader * @see java.lang.ClassLoader
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public static Class<?> forName(String name, boolean initialize, public static Class<?> forName(String name, boolean initialize,
ClassLoader loader) ClassLoader loader)
throws ClassNotFoundException throws ClassNotFoundException
...@@ -324,7 +328,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -324,7 +328,7 @@ public final class Class<T> implements java.io.Serializable,
if (sun.misc.VM.isSystemDomainLoader(loader)) { if (sun.misc.VM.isSystemDomainLoader(loader)) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (!sun.misc.VM.isSystemDomainLoader(ccl)) { if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
sm.checkPermission( sm.checkPermission(
SecurityConstants.GET_CLASSLOADER_PERMISSION); SecurityConstants.GET_CLASSLOADER_PERMISSION);
...@@ -386,18 +390,14 @@ public final class Class<T> implements java.io.Serializable, ...@@ -386,18 +390,14 @@ public final class Class<T> implements java.io.Serializable,
* </ul> * </ul>
* *
*/ */
@CallerSensitive
public T newInstance() public T newInstance()
throws InstantiationException, IllegalAccessException throws InstantiationException, IllegalAccessException
{ {
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false); checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
return newInstance0();
} }
private T newInstance0()
throws InstantiationException, IllegalAccessException
{
// NOTE: the following code may not be strictly correct under // NOTE: the following code may not be strictly correct under
// the current Java memory model. // the current Java memory model.
...@@ -432,7 +432,7 @@ public final class Class<T> implements java.io.Serializable, ...@@ -432,7 +432,7 @@ public final class Class<T> implements java.io.Serializable,
// Security check (same as in java.lang.reflect.Constructor) // Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers(); int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) { if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass(3); Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) { if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers); Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller; newInstanceCallerCache = caller;
...@@ -674,16 +674,14 @@ public final class Class<T> implements java.io.Serializable, ...@@ -674,16 +674,14 @@ public final class Class<T> implements java.io.Serializable,
* @see SecurityManager#checkPermission * @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission * @see java.lang.RuntimePermission
*/ */
@CallerSensitive
public ClassLoader getClassLoader() { public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0(); ClassLoader cl = getClassLoader0();
if (cl == null) if (cl == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return cl; return cl;
} }
...@@ -1392,11 +1390,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1392,11 +1390,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Class<?>[] getClasses() { public Class<?>[] getClasses() {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), false);
// Privileged so this implementation can look at DECLARED classes, // Privileged so this implementation can look at DECLARED classes,
// something the caller might not have privilege to do. The code here // something the caller might not have privilege to do. The code here
...@@ -1467,11 +1463,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1467,11 +1463,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field[] getFields() throws SecurityException { public Field[] getFields() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetPublicFields(null)); return copyFields(privateGetPublicFields(null));
} }
...@@ -1518,11 +1512,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1518,11 +1512,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method[] getMethods() throws SecurityException { public Method[] getMethods() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetPublicMethods()); return copyMethods(privateGetPublicMethods());
} }
...@@ -1567,11 +1559,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1567,11 +1559,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException { public Constructor<?>[] getConstructors() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(true)); return copyConstructors(privateGetDeclaredConstructors(true));
} }
...@@ -1625,12 +1615,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1625,12 +1615,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field getField(String name) public Field getField(String name)
throws NoSuchFieldException, SecurityException { throws NoSuchFieldException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Field field = getField0(name); Field field = getField0(name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -1710,12 +1698,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1710,12 +1698,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes) public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
Method method = getMethod0(name, parameterTypes); Method method = getMethod0(name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -1764,12 +1750,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1764,12 +1750,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<T> getConstructor(Class<?>... parameterTypes) public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.PUBLIC); return getConstructor0(parameterTypes, Member.PUBLIC);
} }
...@@ -1807,11 +1791,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1807,11 +1791,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Class<?>[] getDeclaredClasses() throws SecurityException { public Class<?>[] getDeclaredClasses() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), false);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), false);
return getDeclaredClasses0(); return getDeclaredClasses0();
} }
...@@ -1851,11 +1833,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1851,11 +1833,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException { public Field[] getDeclaredFields() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyFields(privateGetDeclaredFields(false)); return copyFields(privateGetDeclaredFields(false));
} }
...@@ -1899,11 +1879,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1899,11 +1879,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException { public Method[] getDeclaredMethods() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyMethods(privateGetDeclaredMethods(false)); return copyMethods(privateGetDeclaredMethods(false));
} }
...@@ -1944,11 +1922,9 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1944,11 +1922,9 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<?>[] getDeclaredConstructors() throws SecurityException { public Constructor<?>[] getDeclaredConstructors() throws SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return copyConstructors(privateGetDeclaredConstructors(false)); return copyConstructors(privateGetDeclaredConstructors(false));
} }
...@@ -1987,12 +1963,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -1987,12 +1963,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Field getDeclaredField(String name) public Field getDeclaredField(String name)
throws NoSuchFieldException, SecurityException { throws NoSuchFieldException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Field field = searchFields(privateGetDeclaredFields(false), name); Field field = searchFields(privateGetDeclaredFields(false), name);
if (field == null) { if (field == null) {
throw new NoSuchFieldException(name); throw new NoSuchFieldException(name);
...@@ -2042,12 +2016,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2042,12 +2016,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) { if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
...@@ -2092,12 +2064,10 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2092,12 +2064,10 @@ public final class Class<T> implements java.io.Serializable,
* *
* @since JDK1.1 * @since JDK1.1
*/ */
@CallerSensitive
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException { throws NoSuchMethodException, SecurityException {
// be very careful not to change the stack depth of this checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
// checkMemberAccess call for security reasons
// see java.lang.SecurityManager.checkMemberAccess
checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader(), true);
return getConstructor0(parameterTypes, Member.DECLARED); return getConstructor0(parameterTypes, Member.DECLARED);
} }
...@@ -2255,23 +2225,40 @@ public final class Class<T> implements java.io.Serializable, ...@@ -2255,23 +2225,40 @@ public final class Class<T> implements java.io.Serializable,
*/ */
static native Class<?> getPrimitiveClass(String name); static native Class<?> getPrimitiveClass(String name);
private static boolean isCheckMemberAccessOverridden(SecurityManager smgr) {
if (smgr.getClass() == SecurityManager.class) return false;
Class<?>[] paramTypes = new Class<?>[] {Class.class, int.class};
return smgr.getClass().getMethod0("checkMemberAccess", paramTypes).
getDeclaringClass() != SecurityManager.class;
}
/* /*
* Check if client is allowed to access members. If access is denied, * Check if client is allowed to access members. If access is denied,
* throw a SecurityException. * throw a SecurityException.
* *
* Be very careful not to change the stack depth of this checkMemberAccess
* call for security reasons.
* See java.lang.SecurityManager.checkMemberAccess.
*
* <p> Default policy: allow all clients access with normal Java access * <p> Default policy: allow all clients access with normal Java access
* control. * control.
*/ */
private void checkMemberAccess(int which, ClassLoader ccl, boolean checkProxyInterfaces) { private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
SecurityManager s = System.getSecurityManager(); final SecurityManager s = System.getSecurityManager();
if (s != null) { if (s != null) {
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
final ClassLoader cl = getClassLoader0();
if (!isCheckMemberAccessOverridden(s)) {
// Inlined SecurityManager.checkMemberAccess
if (which != Member.PUBLIC) {
if (ccl != cl) {
s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
}
} else {
// Don't refactor; otherwise break the stack depth for
// checkMemberAccess of subclasses of SecurityManager as specified.
s.checkMemberAccess(this, which); s.checkMemberAccess(this, which);
ClassLoader cl = getClassLoader0(); }
if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) { if (ReflectUtil.needsPackageAccessCheck(ccl, cl)) {
String name = this.getName(); String name = this.getName();
int i = name.lastIndexOf('.'); int i = name.lastIndexOf('.');
......
...@@ -55,6 +55,7 @@ import sun.misc.CompoundEnumeration; ...@@ -55,6 +55,7 @@ import sun.misc.CompoundEnumeration;
import sun.misc.Resource; import sun.misc.Resource;
import sun.misc.URLClassPath; import sun.misc.URLClassPath;
import sun.misc.VM; import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -1159,11 +1160,6 @@ public abstract class ClassLoader { ...@@ -1159,11 +1160,6 @@ public abstract class ClassLoader {
return java.util.Collections.emptyEnumeration(); return java.util.Collections.emptyEnumeration();
} }
// index 0: java.lang.ClassLoader.class
// index 1: the immediate caller of index 0.
// index 2: the immediate caller of index 1.
private static native Class<? extends ClassLoader> getCaller(int index);
/** /**
* Registers the caller as parallel capable.</p> * Registers the caller as parallel capable.</p>
* The registration succeeds if and only if all of the following * The registration succeeds if and only if all of the following
...@@ -1179,8 +1175,11 @@ public abstract class ClassLoader { ...@@ -1179,8 +1175,11 @@ public abstract class ClassLoader {
* *
* @since 1.7 * @since 1.7
*/ */
@CallerSensitive
protected static boolean registerAsParallelCapable() { protected static boolean registerAsParallelCapable() {
return ParallelLoaders.register(getCaller(1)); Class<? extends ClassLoader> callerClass =
Reflection.getCallerClass().asSubclass(ClassLoader.class);
return ParallelLoaders.register(callerClass);
} }
/** /**
...@@ -1340,15 +1339,13 @@ public abstract class ClassLoader { ...@@ -1340,15 +1339,13 @@ public abstract class ClassLoader {
* *
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public final ClassLoader getParent() { public final ClassLoader getParent() {
if (parent == null) if (parent == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); checkClassLoaderPermission(this, Reflection.getCallerClass());
if (needsClassLoaderPermissionCheck(ccl, this)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return parent; return parent;
} }
...@@ -1408,6 +1405,7 @@ public abstract class ClassLoader { ...@@ -1408,6 +1405,7 @@ public abstract class ClassLoader {
* *
* @revised 1.4 * @revised 1.4
*/ */
@CallerSensitive
public static ClassLoader getSystemClassLoader() { public static ClassLoader getSystemClassLoader() {
initSystemClassLoader(); initSystemClassLoader();
if (scl == null) { if (scl == null) {
...@@ -1415,10 +1413,7 @@ public abstract class ClassLoader { ...@@ -1415,10 +1413,7 @@ public abstract class ClassLoader {
} }
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = getCallerClassLoader(); checkClassLoaderPermission(scl, Reflection.getCallerClass());
if (needsClassLoaderPermissionCheck(ccl, scl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return scl; return scl;
} }
...@@ -1471,7 +1466,7 @@ public abstract class ClassLoader { ...@@ -1471,7 +1466,7 @@ public abstract class ClassLoader {
// class loader 'from' is same as class loader 'to' or an ancestor // class loader 'from' is same as class loader 'to' or an ancestor
// of 'to'. The class loader in a system domain can access // of 'to'. The class loader in a system domain can access
// any class loader. // any class loader.
static boolean needsClassLoaderPermissionCheck(ClassLoader from, private static boolean needsClassLoaderPermissionCheck(ClassLoader from,
ClassLoader to) ClassLoader to)
{ {
if (from == to) if (from == to)
...@@ -1483,13 +1478,8 @@ public abstract class ClassLoader { ...@@ -1483,13 +1478,8 @@ public abstract class ClassLoader {
return !to.isAncestor(from); return !to.isAncestor(from);
} }
// Returns the invoker's class loader, or null if none. // Returns the class's class loader, or null if none.
// NOTE: This must always be invoked when there is exactly one intervening static ClassLoader getClassLoader(Class<?> caller) {
// frame from the core libraries on the stack between this method's
// invocation and the desired invoker.
static ClassLoader getCallerClassLoader() {
// NOTE use of more generic Reflection.getCallerClass()
Class<?> caller = Reflection.getCallerClass(3);
// This can be null if the VM is requesting it // This can be null if the VM is requesting it
if (caller == null) { if (caller == null) {
return null; return null;
...@@ -1498,6 +1488,17 @@ public abstract class ClassLoader { ...@@ -1498,6 +1488,17 @@ public abstract class ClassLoader {
return caller.getClassLoader0(); return caller.getClassLoader0();
} }
static void checkClassLoaderPermission(ClassLoader cl, Class<?> caller) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// caller can be null if the VM is requesting it
ClassLoader ccl = getClassLoader(caller);
if (needsClassLoaderPermissionCheck(ccl, cl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
}
// The class loader for the system // The class loader for the system
// @GuardedBy("ClassLoader.class") // @GuardedBy("ClassLoader.class")
private static ClassLoader scl; private static ClassLoader scl;
......
...@@ -49,6 +49,8 @@ import java.util.HashMap; ...@@ -49,6 +49,8 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import sun.net.www.ParseUtil; import sun.net.www.ParseUtil;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
...@@ -273,8 +275,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { ...@@ -273,8 +275,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
* @return the package of the requested name. It may be null if no package * @return the package of the requested name. It may be null if no package
* information is available from the archive or codebase. * information is available from the archive or codebase.
*/ */
@CallerSensitive
public static Package getPackage(String name) { public static Package getPackage(String name) {
ClassLoader l = ClassLoader.getCallerClassLoader(); ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) { if (l != null) {
return l.getPackage(name); return l.getPackage(name);
} else { } else {
...@@ -294,8 +297,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { ...@@ -294,8 +297,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
* @return a new array of packages known to the callers {@code ClassLoader} * @return a new array of packages known to the callers {@code ClassLoader}
* instance. An zero length array is returned if none are known. * instance. An zero length array is returned if none are known.
*/ */
@CallerSensitive
public static Package[] getPackages() { public static Package[] getPackages() {
ClassLoader l = ClassLoader.getCallerClassLoader(); ClassLoader l = ClassLoader.getClassLoader(Reflection.getCallerClass());
if (l != null) { if (l != null) {
return l.getPackages(); return l.getPackages();
} else { } else {
......
...@@ -30,6 +30,7 @@ import java.io.IOException; ...@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.security.AccessControlException;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -1024,13 +1025,24 @@ public final class ProcessBuilder ...@@ -1024,13 +1025,24 @@ public final class ProcessBuilder
redirects, redirects,
redirectErrorStream); redirectErrorStream);
} catch (IOException e) { } catch (IOException e) {
String exceptionInfo = ": " + e.getMessage();
Throwable cause = e;
if (security != null) {
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
} catch (AccessControlException ace) {
exceptionInfo = "";
cause = ace;
}
}
// It's much easier for us to create a high-quality error // It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem. // message than the low-level C code which found the problem.
throw new IOException( throw new IOException(
"Cannot run program \"" + prog + "\"" "Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")") + (dir == null ? "" : " (in directory \"" + dir + "\")")
+ ": " + e.getMessage(), + exceptionInfo,
e); cause);
} }
} }
} }
...@@ -27,6 +27,8 @@ package java.lang; ...@@ -27,6 +27,8 @@ package java.lang;
import java.io.*; import java.io.*;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* Every Java application has a single instance of class * Every Java application has a single instance of class
...@@ -790,8 +792,9 @@ public class Runtime { ...@@ -790,8 +792,9 @@ public class Runtime {
* @see java.lang.SecurityException * @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public void load(String filename) { public void load(String filename) {
load0(System.getCallerClass(), filename); load0(Reflection.getCallerClass(), filename);
} }
synchronized void load0(Class<?> fromClass, String filename) { synchronized void load0(Class<?> fromClass, String filename) {
...@@ -850,8 +853,9 @@ public class Runtime { ...@@ -850,8 +853,9 @@ public class Runtime {
* @see java.lang.SecurityException * @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public void loadLibrary(String libname) { public void loadLibrary(String libname) {
loadLibrary0(System.getCallerClass(), libname); loadLibrary0(Reflection.getCallerClass(), libname);
} }
synchronized void loadLibrary0(Class<?> fromClass, String libname) { synchronized void loadLibrary0(Class<?> fromClass, String libname) {
......
...@@ -36,10 +36,10 @@ import java.net.SocketPermission; ...@@ -36,10 +36,10 @@ import java.net.SocketPermission;
import java.net.NetPermission; import java.net.NetPermission;
import java.util.Hashtable; import java.util.Hashtable;
import java.net.InetAddress; import java.net.InetAddress;
import java.lang.reflect.Member;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.URL; import java.net.URL;
import sun.reflect.CallerSensitive;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
/** /**
...@@ -1679,6 +1679,7 @@ class SecurityManager { ...@@ -1679,6 +1679,7 @@ class SecurityManager {
* @since JDK1.1 * @since JDK1.1
* @see #checkPermission(java.security.Permission) checkPermission * @see #checkPermission(java.security.Permission) checkPermission
*/ */
@CallerSensitive
public void checkMemberAccess(Class<?> clazz, int which) { public void checkMemberAccess(Class<?> clazz, int which) {
if (clazz == null) { if (clazz == null) {
throw new NullPointerException("class can't be null"); throw new NullPointerException("class can't be null");
......
...@@ -35,6 +35,7 @@ import java.security.AllPermission; ...@@ -35,6 +35,7 @@ import java.security.AllPermission;
import java.nio.channels.Channel; import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
import sun.nio.ch.Interruptible; import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
import sun.reflect.annotation.AnnotationType; import sun.reflect.annotation.AnnotationType;
...@@ -1072,8 +1073,9 @@ public final class System { ...@@ -1072,8 +1073,9 @@ public final class System {
* @see java.lang.Runtime#load(java.lang.String) * @see java.lang.Runtime#load(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public static void load(String filename) { public static void load(String filename) {
Runtime.getRuntime().load0(getCallerClass(), filename); Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
} }
/** /**
...@@ -1107,8 +1109,9 @@ public final class System { ...@@ -1107,8 +1109,9 @@ public final class System {
* @see java.lang.Runtime#loadLibrary(java.lang.String) * @see java.lang.Runtime#loadLibrary(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String) * @see java.lang.SecurityManager#checkLink(java.lang.String)
*/ */
@CallerSensitive
public static void loadLibrary(String libname) { public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname); Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
} }
/** /**
...@@ -1245,10 +1248,4 @@ public final class System { ...@@ -1245,10 +1248,4 @@ public final class System {
} }
}); });
} }
/* returns the class of the caller. */
static Class<?> getCallerClass() {
// NOTE use of more generic Reflection.getCallerClass()
return Reflection.getCallerClass(3);
}
} }
...@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -37,6 +37,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.LockSupport;
import sun.nio.ch.Interruptible; import sun.nio.ch.Interruptible;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -1443,15 +1445,14 @@ class Thread implements Runnable { ...@@ -1443,15 +1445,14 @@ class Thread implements Runnable {
* *
* @since 1.2 * @since 1.2
*/ */
@CallerSensitive
public ClassLoader getContextClassLoader() { public ClassLoader getContextClassLoader() {
if (contextClassLoader == null) if (contextClassLoader == null)
return null; return null;
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
ClassLoader ccl = ClassLoader.getCallerClassLoader(); ClassLoader.checkClassLoaderPermission(contextClassLoader,
if (ClassLoader.needsClassLoaderPermissionCheck(ccl, contextClassLoader)) { Reflection.getCallerClass());
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
} }
return contextClassLoader; return contextClassLoader;
} }
......
...@@ -709,7 +709,9 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -709,7 +709,9 @@ import jdk.internal.org.objectweb.asm.Type;
InvokerBytecodeGenerator.maybeDump(className, classFile); InvokerBytecodeGenerator.maybeDump(className, classFile);
Class<? extends BoundMethodHandle> bmhClass = Class<? extends BoundMethodHandle> bmhClass =
//UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class); //UNSAFE.defineAnonymousClass(BoundMethodHandle.class, classFile, null).asSubclass(BoundMethodHandle.class);
UNSAFE.defineClass(className, classFile, 0, classFile.length).asSubclass(BoundMethodHandle.class); UNSAFE.defineClass(className, classFile, 0, classFile.length,
BoundMethodHandle.class.getClassLoader(), null)
.asSubclass(BoundMethodHandle.class);
UNSAFE.ensureClassInitialized(bmhClass); UNSAFE.ensureClassInitialized(bmhClass);
return bmhClass; return bmhClass;
......
...@@ -394,7 +394,8 @@ import java.util.Objects; ...@@ -394,7 +394,8 @@ import java.util.Objects;
IS_METHOD = MN_IS_METHOD, // method (not constructor) IS_METHOD = MN_IS_METHOD, // method (not constructor)
IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
IS_FIELD = MN_IS_FIELD, // field IS_FIELD = MN_IS_FIELD, // field
IS_TYPE = MN_IS_TYPE; // nested type IS_TYPE = MN_IS_TYPE, // nested type
CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
...@@ -430,6 +431,10 @@ import java.util.Objects; ...@@ -430,6 +431,10 @@ import java.util.Objects;
public boolean isPackage() { public boolean isPackage() {
return !testAnyFlags(ALL_ACCESS); return !testAnyFlags(ALL_ACCESS);
} }
/** Query whether this member has a CallerSensitive annotation. */
public boolean isCallerSensitive() {
return testAllFlags(CALLER_SENSITIVE);
}
/** Utility method to query whether this member is accessible from a given lookup class. */ /** Utility method to query whether this member is accessible from a given lookup class. */
public boolean isAccessibleFrom(Class<?> lookupClass) { public boolean isAccessibleFrom(Class<?> lookupClass) {
......
...@@ -34,6 +34,8 @@ import sun.invoke.empty.Empty; ...@@ -34,6 +34,8 @@ import sun.invoke.empty.Empty;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType; import sun.invoke.util.VerifyType;
import sun.invoke.util.Wrapper; import sun.invoke.util.Wrapper;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
...@@ -891,9 +893,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -891,9 +893,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
} }
} }
@CallerSensitive
private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) { private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
final int FRAME_COUNT_ARG = 2; // [0] Reflection [1] BindCaller [2] Expected // This method is called via MH_checkCallerClass and so it's
Class<?> actual = sun.reflect.Reflection.getCallerClass(FRAME_COUNT_ARG); // correct to ask for the immediate caller here.
Class<?> actual = Reflection.getCallerClass();
if (actual != expected && actual != expected2) if (actual != expected && actual != expected2)
throw new InternalError("found "+actual.getName()+", expected "+expected.getName() throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
+(expected == expected2 ? "" : ", or else "+expected2.getName())); +(expected == expected2 ? "" : ", or else "+expected2.getName()));
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
package java.lang.invoke; package java.lang.invoke;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleStatics.*;
...@@ -34,7 +33,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -34,7 +33,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
/** /**
* The JVM interface for the method handles package is all here. * The JVM interface for the method handles package is all here.
* This is an interface internal and private to an implemetantion of JSR 292. * This is an interface internal and private to an implementation of JSR 292.
* <em>This class is not part of the JSR 292 standard.</em> * <em>This class is not part of the JSR 292 standard.</em>
* @author jrose * @author jrose
*/ */
...@@ -101,6 +100,7 @@ class MethodHandleNatives { ...@@ -101,6 +100,7 @@ class MethodHandleNatives {
MN_IS_CONSTRUCTOR = 0x00020000, // constructor MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type MN_IS_TYPE = 0x00080000, // nested type
MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
MN_REFERENCE_KIND_SHIFT = 24, // refKind MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT, MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers: // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
...@@ -391,129 +391,24 @@ class MethodHandleNatives { ...@@ -391,129 +391,24 @@ class MethodHandleNatives {
* I.e., does it call Reflection.getCallerClass or a similer method * I.e., does it call Reflection.getCallerClass or a similer method
* to ask about the identity of its caller? * to ask about the identity of its caller?
*/ */
// FIXME: Replace this pattern match by an annotation @sun.reflect.CallerSensitive.
static boolean isCallerSensitive(MemberName mem) { static boolean isCallerSensitive(MemberName mem) {
if (!mem.isInvocable()) return false; // fields are not caller sensitive if (!mem.isInvocable()) return false; // fields are not caller sensitive
return mem.isCallerSensitive() || canBeCalledVirtual(mem);
}
static boolean canBeCalledVirtual(MemberName mem) {
assert(mem.isInvocable());
Class<?> defc = mem.getDeclaringClass(); Class<?> defc = mem.getDeclaringClass();
switch (mem.getName()) { switch (mem.getName()) {
case "doPrivileged":
case "doPrivilegedWithCombiner":
return defc == java.security.AccessController.class;
case "checkMemberAccess": case "checkMemberAccess":
return canBeCalledVirtual(mem, java.lang.SecurityManager.class); return canBeCalledVirtual(mem, java.lang.SecurityManager.class);
case "getUnsafe":
return defc == sun.misc.Unsafe.class;
case "lookup":
return defc == java.lang.invoke.MethodHandles.class;
case "findStatic":
case "findVirtual":
case "findConstructor":
case "findSpecial":
case "findGetter":
case "findSetter":
case "findStaticGetter":
case "findStaticSetter":
case "bind":
case "unreflect":
case "unreflectSpecial":
case "unreflectConstructor":
case "unreflectGetter":
case "unreflectSetter":
return defc == java.lang.invoke.MethodHandles.Lookup.class;
case "invoke":
return defc == java.lang.reflect.Method.class;
case "get":
case "getBoolean":
case "getByte":
case "getChar":
case "getShort":
case "getInt":
case "getLong":
case "getFloat":
case "getDouble":
case "set":
case "setBoolean":
case "setByte":
case "setChar":
case "setShort":
case "setInt":
case "setLong":
case "setFloat":
case "setDouble":
return defc == java.lang.reflect.Field.class;
case "newInstance":
if (defc == java.lang.reflect.Constructor.class) return true;
if (defc == java.lang.Class.class) return true;
break;
case "forName":
case "getClassLoader":
case "getClasses":
case "getFields":
case "getMethods":
case "getConstructors":
case "getDeclaredClasses":
case "getDeclaredFields":
case "getDeclaredMethods":
case "getDeclaredConstructors":
case "getField":
case "getMethod":
case "getConstructor":
case "getDeclaredField":
case "getDeclaredMethod":
case "getDeclaredConstructor":
return defc == java.lang.Class.class;
case "getConnection":
case "getDriver":
case "getDrivers":
case "deregisterDriver":
return defc == getClass("java.sql.DriverManager");
case "newUpdater":
if (defc == java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class) return true;
if (defc == java.util.concurrent.atomic.AtomicLongFieldUpdater.class) return true;
if (defc == java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class) return true;
break;
case "getContextClassLoader": case "getContextClassLoader":
return canBeCalledVirtual(mem, java.lang.Thread.class); return canBeCalledVirtual(mem, java.lang.Thread.class);
case "getPackage":
case "getPackages":
return defc == java.lang.Package.class;
case "getParent":
case "getSystemClassLoader":
return defc == java.lang.ClassLoader.class;
case "load":
case "loadLibrary":
if (defc == java.lang.Runtime.class) return true;
if (defc == java.lang.System.class) return true;
break;
case "getCallerClass":
if (defc == sun.reflect.Reflection.class) return true;
if (defc == java.lang.System.class) return true;
break;
case "getCallerClassLoader":
return defc == java.lang.ClassLoader.class;
case "registerAsParallelCapable":
return canBeCalledVirtual(mem, java.lang.ClassLoader.class);
case "getProxyClass":
case "newProxyInstance":
return defc == java.lang.reflect.Proxy.class;
case "asInterfaceInstance":
return defc == java.lang.invoke.MethodHandleProxies.class;
case "getBundle":
case "clearCache":
return defc == java.util.ResourceBundle.class;
} }
return false; return false;
} }
// avoid static dependency to a class in other modules
private static Class<?> getClass(String cn) {
try {
return Class.forName(cn, false,
MethodHandleNatives.class.getClassLoader());
} catch (ClassNotFoundException e) {
throw new InternalError(e);
}
}
static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) { static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
Class<?> symbolicRefClass = symbolicRef.getDeclaringClass(); Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
if (symbolicRefClass == definingClass) return true; if (symbolicRefClass == definingClass) return true;
......
...@@ -30,6 +30,7 @@ import java.security.AccessController; ...@@ -30,6 +30,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance; import sun.invoke.WrapperInstance;
import java.util.ArrayList; import java.util.ArrayList;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
...@@ -137,14 +138,14 @@ public class MethodHandleProxies { ...@@ -137,14 +138,14 @@ public class MethodHandleProxies {
// entry points, must be covered by hand-written or automatically // entry points, must be covered by hand-written or automatically
// generated adapter classes. // generated adapter classes.
// //
@CallerSensitive
public static public static
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) { <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers())) if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
throw new IllegalArgumentException("not a public interface: "+intfc.getName()); throw new IllegalArgumentException("not a public interface: "+intfc.getName());
final MethodHandle mh; final MethodHandle mh;
if (System.getSecurityManager() != null) { if (System.getSecurityManager() != null) {
final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller final Class<?> caller = Reflection.getCallerClass();
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
final ClassLoader ccl = caller != null ? caller.getClassLoader() : null; final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
ReflectUtil.checkProxyPackageAccess(ccl, intfc); ReflectUtil.checkProxyPackageAccess(ccl, intfc);
mh = ccl != null ? bindCaller(target, caller) : target; mh = ccl != null ? bindCaller(target, caller) : target;
......
...@@ -38,9 +38,9 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -38,9 +38,9 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
*/ */
static native void invokeFinalizeMethod(Object o) throws Throwable; static native void invokeFinalizeMethod(Object o) throws Throwable;
static private ReferenceQueue queue = new ReferenceQueue(); private static ReferenceQueue queue = new ReferenceQueue();
static private Finalizer unfinalized = null; private static Finalizer unfinalized = null;
static private Object lock = new Object(); private static final Object lock = new Object();
private Finalizer private Finalizer
next = null, next = null,
...@@ -142,7 +142,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -142,7 +142,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
/* Called by Runtime.runFinalization() */ /* Called by Runtime.runFinalization() */
static void runFinalization() { static void runFinalization() {
forkSecondaryFinalizer(new Runnable() { forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
Finalizer f = (Finalizer)queue.poll(); Finalizer f = (Finalizer)queue.poll();
if (f == null) break; if (f == null) break;
...@@ -155,7 +159,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -155,7 +159,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
/* Invoked by java.lang.Shutdown */ /* Invoked by java.lang.Shutdown */
static void runAllFinalizers() { static void runAllFinalizers() {
forkSecondaryFinalizer(new Runnable() { forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
Finalizer f; Finalizer f;
synchronized (lock) { synchronized (lock) {
...@@ -168,10 +176,14 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -168,10 +176,14 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
} }
private static class FinalizerThread extends Thread { private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) { FinalizerThread(ThreadGroup g) {
super(g, "Finalizer"); super(g, "Finalizer");
} }
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
try { try {
Finalizer f = (Finalizer)queue.remove(); Finalizer f = (Finalizer)queue.remove();
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.ConstructorAccessor; import sun.reflect.ConstructorAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.repository.ConstructorRepository;
...@@ -392,14 +393,14 @@ public final class Constructor<T> extends Executable { ...@@ -392,14 +393,14 @@ public final class Constructor<T> extends Executable {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public T newInstance(Object ... initargs) public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException, throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException IllegalArgumentException, InvocationTargetException
{ {
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(2); Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers); checkAccess(caller, clazz, null, modifiers);
} }
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.FieldAccessor; import sun.reflect.FieldAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.FieldRepository; import sun.reflect.generics.repository.FieldRepository;
...@@ -376,9 +377,16 @@ class Field extends AccessibleObject implements Member { ...@@ -376,9 +377,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public Object get(Object obj) public Object get(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).get(obj); return getFieldAccessor(obj).get(obj);
} }
...@@ -404,9 +412,16 @@ class Field extends AccessibleObject implements Member { ...@@ -404,9 +412,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public boolean getBoolean(Object obj) public boolean getBoolean(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getBoolean(obj); return getFieldAccessor(obj).getBoolean(obj);
} }
...@@ -432,9 +447,16 @@ class Field extends AccessibleObject implements Member { ...@@ -432,9 +447,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public byte getByte(Object obj) public byte getByte(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getByte(obj); return getFieldAccessor(obj).getByte(obj);
} }
...@@ -462,9 +484,16 @@ class Field extends AccessibleObject implements Member { ...@@ -462,9 +484,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public char getChar(Object obj) public char getChar(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getChar(obj); return getFieldAccessor(obj).getChar(obj);
} }
...@@ -492,9 +521,16 @@ class Field extends AccessibleObject implements Member { ...@@ -492,9 +521,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public short getShort(Object obj) public short getShort(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getShort(obj); return getFieldAccessor(obj).getShort(obj);
} }
...@@ -522,9 +558,16 @@ class Field extends AccessibleObject implements Member { ...@@ -522,9 +558,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public int getInt(Object obj) public int getInt(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getInt(obj); return getFieldAccessor(obj).getInt(obj);
} }
...@@ -552,9 +595,16 @@ class Field extends AccessibleObject implements Member { ...@@ -552,9 +595,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public long getLong(Object obj) public long getLong(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getLong(obj); return getFieldAccessor(obj).getLong(obj);
} }
...@@ -582,9 +632,16 @@ class Field extends AccessibleObject implements Member { ...@@ -582,9 +632,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public float getFloat(Object obj) public float getFloat(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getFloat(obj); return getFieldAccessor(obj).getFloat(obj);
} }
...@@ -612,9 +669,16 @@ class Field extends AccessibleObject implements Member { ...@@ -612,9 +669,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#get * @see Field#get
*/ */
@CallerSensitive
public double getDouble(Object obj) public double getDouble(Object obj)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).getDouble(obj); return getFieldAccessor(obj).getDouble(obj);
} }
...@@ -684,9 +748,16 @@ class Field extends AccessibleObject implements Member { ...@@ -684,9 +748,16 @@ class Field extends AccessibleObject implements Member {
* @exception ExceptionInInitializerError if the initialization provoked * @exception ExceptionInInitializerError if the initialization provoked
* by this method fails. * by this method fails.
*/ */
@CallerSensitive
public void set(Object obj, Object value) public void set(Object obj, Object value)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).set(obj, value); getFieldAccessor(obj).set(obj, value);
} }
...@@ -714,9 +785,16 @@ class Field extends AccessibleObject implements Member { ...@@ -714,9 +785,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setBoolean(Object obj, boolean z) public void setBoolean(Object obj, boolean z)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setBoolean(obj, z); getFieldAccessor(obj).setBoolean(obj, z);
} }
...@@ -744,9 +822,16 @@ class Field extends AccessibleObject implements Member { ...@@ -744,9 +822,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setByte(Object obj, byte b) public void setByte(Object obj, byte b)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setByte(obj, b); getFieldAccessor(obj).setByte(obj, b);
} }
...@@ -774,9 +859,16 @@ class Field extends AccessibleObject implements Member { ...@@ -774,9 +859,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setChar(Object obj, char c) public void setChar(Object obj, char c)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setChar(obj, c); getFieldAccessor(obj).setChar(obj, c);
} }
...@@ -804,9 +896,16 @@ class Field extends AccessibleObject implements Member { ...@@ -804,9 +896,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setShort(Object obj, short s) public void setShort(Object obj, short s)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setShort(obj, s); getFieldAccessor(obj).setShort(obj, s);
} }
...@@ -834,9 +933,16 @@ class Field extends AccessibleObject implements Member { ...@@ -834,9 +933,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setInt(Object obj, int i) public void setInt(Object obj, int i)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setInt(obj, i); getFieldAccessor(obj).setInt(obj, i);
} }
...@@ -864,9 +970,16 @@ class Field extends AccessibleObject implements Member { ...@@ -864,9 +970,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setLong(Object obj, long l) public void setLong(Object obj, long l)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setLong(obj, l); getFieldAccessor(obj).setLong(obj, l);
} }
...@@ -894,9 +1007,16 @@ class Field extends AccessibleObject implements Member { ...@@ -894,9 +1007,16 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setFloat(Object obj, float f) public void setFloat(Object obj, float f)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setFloat(obj, f); getFieldAccessor(obj).setFloat(obj, f);
} }
...@@ -924,20 +1044,26 @@ class Field extends AccessibleObject implements Member { ...@@ -924,20 +1044,26 @@ class Field extends AccessibleObject implements Member {
* by this method fails. * by this method fails.
* @see Field#set * @see Field#set
*/ */
@CallerSensitive
public void setDouble(Object obj, double d) public void setDouble(Object obj, double d)
throws IllegalArgumentException, IllegalAccessException throws IllegalArgumentException, IllegalAccessException
{ {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).setDouble(obj, d); getFieldAccessor(obj).setDouble(obj, d);
} }
// Convenience routine which performs security checks // security check is done before calling this method
private FieldAccessor getFieldAccessor(Object obj) private FieldAccessor getFieldAccessor(Object obj)
throws IllegalAccessException throws IllegalAccessException
{ {
doSecurityCheck(obj);
boolean ov = override; boolean ov = override;
FieldAccessor a = (ov)? overrideFieldAccessor : fieldAccessor; FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
return (a != null)? a : acquireFieldAccessor(ov); return (a != null) ? a : acquireFieldAccessor(ov);
} }
// NOTE that there is no synchronization used here. It is correct // NOTE that there is no synchronization used here. It is correct
...@@ -982,19 +1108,6 @@ class Field extends AccessibleObject implements Member { ...@@ -982,19 +1108,6 @@ class Field extends AccessibleObject implements Member {
} }
} }
// NOTE: be very careful if you change the stack depth of this
// routine. The depth of the "getCallerClass" call is hardwired so
// that the compiler can have an easier time if this gets inlined.
private void doSecurityCheck(Object obj) throws IllegalAccessException {
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(4);
checkAccess(caller, clazz, obj, modifiers);
}
}
}
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.5 * @since 1.5
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
package java.lang.reflect; package java.lang.reflect;
import sun.reflect.CallerSensitive;
import sun.reflect.MethodAccessor; import sun.reflect.MethodAccessor;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.generics.repository.MethodRepository; import sun.reflect.generics.repository.MethodRepository;
...@@ -472,14 +473,14 @@ public final class Method extends Executable { ...@@ -472,14 +473,14 @@ public final class Method extends Executable {
* @exception ExceptionInInitializerError if the initialization * @exception ExceptionInInitializerError if the initialization
* provoked by this method fails. * provoked by this method fails.
*/ */
@CallerSensitive
public Object invoke(Object obj, Object... args) public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException, throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException InvocationTargetException
{ {
if (!override) { if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass(1); Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers); checkAccess(caller, clazz, obj, modifiers);
} }
} }
......
...@@ -39,6 +39,8 @@ import java.util.Set; ...@@ -39,6 +39,8 @@ import java.util.Set;
import java.util.List; import java.util.List;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import sun.misc.ProxyGenerator; import sun.misc.ProxyGenerator;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants; import sun.security.util.SecurityConstants;
...@@ -408,28 +410,21 @@ public class Proxy implements java.io.Serializable { ...@@ -408,28 +410,21 @@ public class Proxy implements java.io.Serializable {
* @throws NullPointerException if the {@code interfaces} array * @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null} * argument or any of its elements are {@code null}
*/ */
@CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader, public static Class<?> getProxyClass(ClassLoader loader,
Class<?>... interfaces) Class<?>... interfaces)
throws IllegalArgumentException throws IllegalArgumentException
{
return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
}
private static void checkProxyLoader(ClassLoader ccl,
ClassLoader loader)
{ {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
if (loader == null && ccl != null) { checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
if (!ProxyAccessHelper.allowNullLoader) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
} }
return getProxyClass0(loader, interfaces);
} }
/* /*
* Generate a proxy class (caller-sensitive). * Check permissions required to create a Proxy class.
* *
* To define a proxy class, it performs the access checks as in * To define a proxy class, it performs the access checks as in
* Class.forName (VM will invoke ClassLoader.checkPackageAccess): * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
...@@ -446,17 +441,28 @@ public class Proxy implements java.io.Serializable { ...@@ -446,17 +441,28 @@ public class Proxy implements java.io.Serializable {
* will throw IllegalAccessError when the generated proxy class is * will throw IllegalAccessError when the generated proxy class is
* being defined via the defineClass0 method. * being defined via the defineClass0 method.
*/ */
private static Class<?> getProxyClass0(ClassLoader loader, private static void checkProxyAccess(Class<?> caller,
Class<?>... interfaces) { ClassLoader loader,
Class<?>... interfaces)
{
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller ClassLoader ccl = caller.getClassLoader();
final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME); if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
final ClassLoader ccl = caller.getClassLoader(); if (!ProxyAccessHelper.allowNullLoader) {
checkProxyLoader(ccl, loader); sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces); ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
} }
}
/**
* Generate a proxy class. Must call the checkProxyAccess method
* to perform permission checks before calling this.
*/
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) { if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded"); throw new IllegalArgumentException("interface limit exceeded");
} }
...@@ -698,6 +704,7 @@ public class Proxy implements java.io.Serializable { ...@@ -698,6 +704,7 @@ public class Proxy implements java.io.Serializable {
* if the invocation handler, {@code h}, is * if the invocation handler, {@code h}, is
* {@code null} * {@code null}
*/ */
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces, Class<?>[] interfaces,
InvocationHandler h) InvocationHandler h)
...@@ -707,10 +714,15 @@ public class Proxy implements java.io.Serializable { ...@@ -707,10 +714,15 @@ public class Proxy implements java.io.Serializable {
throw new NullPointerException(); throw new NullPointerException();
} }
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
/* /*
* Look up or generate the designated proxy class. * Look up or generate the designated proxy class.
*/ */
Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor Class<?> cl = getProxyClass0(loader, interfaces);
/* /*
* Invoke its constructor with the designated invocation handler. * Invoke its constructor with the designated invocation handler.
...@@ -718,7 +730,6 @@ public class Proxy implements java.io.Serializable { ...@@ -718,7 +730,6 @@ public class Proxy implements java.io.Serializable {
try { try {
final Constructor<?> cons = cl.getConstructor(constructorParams); final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h; final InvocationHandler ih = h;
SecurityManager sm = System.getSecurityManager();
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may // create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission // implement non-public interfaces that requires a special permission
......
...@@ -122,7 +122,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl ...@@ -122,7 +122,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
* not connected already. * not connected already.
*/ */
protected void disconnect() { protected void disconnect() {
disconnect0(connectedAddress.family); disconnect0(connectedAddress.holder().getFamily());
connected = false; connected = false;
connectedAddress = null; connectedAddress = null;
connectedPort = -1; connectedPort = -1;
......
...@@ -100,27 +100,28 @@ class Inet4Address extends InetAddress { ...@@ -100,27 +100,28 @@ class Inet4Address extends InetAddress {
Inet4Address() { Inet4Address() {
super(); super();
hostName = null; holder().hostName = null;
address = 0; holder().address = 0;
family = IPv4; holder().family = IPv4;
} }
Inet4Address(String hostName, byte addr[]) { Inet4Address(String hostName, byte addr[]) {
this.hostName = hostName; holder().hostName = hostName;
this.family = IPv4; holder().family = IPv4;
if (addr != null) { if (addr != null) {
if (addr.length == INADDRSZ) { if (addr.length == INADDRSZ) {
address = addr[3] & 0xFF; int address = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00); address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000); address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000); address |= ((addr[0] << 24) & 0xFF000000);
holder().address = address;
} }
} }
} }
Inet4Address(String hostName, int address) { Inet4Address(String hostName, int address) {
this.hostName = hostName; holder().hostName = hostName;
this.family = IPv4; holder().family = IPv4;
this.address = address; holder().address = address;
} }
/** /**
...@@ -134,8 +135,8 @@ class Inet4Address extends InetAddress { ...@@ -134,8 +135,8 @@ class Inet4Address extends InetAddress {
private Object writeReplace() throws ObjectStreamException { private Object writeReplace() throws ObjectStreamException {
// will replace the to be serialized 'this' object // will replace the to be serialized 'this' object
InetAddress inet = new InetAddress(); InetAddress inet = new InetAddress();
inet.hostName = this.hostName; inet.holder().hostName = holder().getHostName();
inet.address = this.address; inet.holder().address = holder().getAddress();
/** /**
* Prior to 1.4 an InetAddress was created with a family * Prior to 1.4 an InetAddress was created with a family
...@@ -143,7 +144,7 @@ class Inet4Address extends InetAddress { ...@@ -143,7 +144,7 @@ class Inet4Address extends InetAddress {
* For compatibility reasons we must therefore write the * For compatibility reasons we must therefore write the
* the InetAddress with this family. * the InetAddress with this family.
*/ */
inet.family = 2; inet.holder().family = 2;
return inet; return inet;
} }
...@@ -157,7 +158,7 @@ class Inet4Address extends InetAddress { ...@@ -157,7 +158,7 @@ class Inet4Address extends InetAddress {
* @since JDK1.1 * @since JDK1.1
*/ */
public boolean isMulticastAddress() { public boolean isMulticastAddress() {
return ((address & 0xf0000000) == 0xe0000000); return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
} }
/** /**
...@@ -167,7 +168,7 @@ class Inet4Address extends InetAddress { ...@@ -167,7 +168,7 @@ class Inet4Address extends InetAddress {
* @since 1.4 * @since 1.4
*/ */
public boolean isAnyLocalAddress() { public boolean isAnyLocalAddress() {
return address == 0; return holder().getAddress() == 0;
} }
/** /**
...@@ -195,6 +196,7 @@ class Inet4Address extends InetAddress { ...@@ -195,6 +196,7 @@ class Inet4Address extends InetAddress {
// defined in "Documenting Special Use IPv4 Address Blocks // defined in "Documenting Special Use IPv4 Address Blocks
// that have been Registered with IANA" by Bill Manning // that have been Registered with IANA" by Bill Manning
// draft-manning-dsua-06.txt // draft-manning-dsua-06.txt
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 169) return (((address >>> 24) & 0xFF) == 169)
&& (((address >>> 16) & 0xFF) == 254); && (((address >>> 16) & 0xFF) == 254);
} }
...@@ -211,6 +213,7 @@ class Inet4Address extends InetAddress { ...@@ -211,6 +213,7 @@ class Inet4Address extends InetAddress {
// 10/8 prefix // 10/8 prefix
// 172.16/12 prefix // 172.16/12 prefix
// 192.168/16 prefix // 192.168/16 prefix
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 10) return (((address >>> 24) & 0xFF) == 10)
|| ((((address >>> 24) & 0xFF) == 172) || ((((address >>> 24) & 0xFF) == 172)
&& (((address >>> 16) & 0xF0) == 16)) && (((address >>> 16) & 0xF0) == 16))
...@@ -257,6 +260,7 @@ class Inet4Address extends InetAddress { ...@@ -257,6 +260,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCLinkLocal() { public boolean isMCLinkLocal() {
// 224.0.0/24 prefix and ttl == 1 // 224.0.0/24 prefix and ttl == 1
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 224) return (((address >>> 24) & 0xFF) == 224)
&& (((address >>> 16) & 0xFF) == 0) && (((address >>> 16) & 0xFF) == 0)
&& (((address >>> 8) & 0xFF) == 0); && (((address >>> 8) & 0xFF) == 0);
...@@ -272,6 +276,7 @@ class Inet4Address extends InetAddress { ...@@ -272,6 +276,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCSiteLocal() { public boolean isMCSiteLocal() {
// 239.255/16 prefix or ttl < 32 // 239.255/16 prefix or ttl < 32
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239) return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) == 255); && (((address >>> 16) & 0xFF) == 255);
} }
...@@ -287,6 +292,7 @@ class Inet4Address extends InetAddress { ...@@ -287,6 +292,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCOrgLocal() { public boolean isMCOrgLocal() {
// 239.192 - 239.195 // 239.192 - 239.195
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239) return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) >= 192) && (((address >>> 16) & 0xFF) >= 192)
&& (((address >>> 16) & 0xFF) <= 195); && (((address >>> 16) & 0xFF) <= 195);
...@@ -300,6 +306,7 @@ class Inet4Address extends InetAddress { ...@@ -300,6 +306,7 @@ class Inet4Address extends InetAddress {
* @return the raw IP address of this object. * @return the raw IP address of this object.
*/ */
public byte[] getAddress() { public byte[] getAddress() {
int address = holder().getAddress();
byte[] addr = new byte[INADDRSZ]; byte[] addr = new byte[INADDRSZ];
addr[0] = (byte) ((address >>> 24) & 0xFF); addr[0] = (byte) ((address >>> 24) & 0xFF);
...@@ -325,7 +332,7 @@ class Inet4Address extends InetAddress { ...@@ -325,7 +332,7 @@ class Inet4Address extends InetAddress {
* @return a hash code value for this IP address. * @return a hash code value for this IP address.
*/ */
public int hashCode() { public int hashCode() {
return address; return holder().getAddress();
} }
/** /**
...@@ -346,7 +353,7 @@ class Inet4Address extends InetAddress { ...@@ -346,7 +353,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean equals(Object obj) { public boolean equals(Object obj) {
return (obj != null) && (obj instanceof Inet4Address) && return (obj != null) && (obj instanceof Inet4Address) &&
(((InetAddress)obj).address == address); (((InetAddress)obj).holder().getAddress() == holder().getAddress());
} }
// Utilities // Utilities
......
...@@ -40,7 +40,7 @@ class Inet4AddressImpl implements InetAddressImpl { ...@@ -40,7 +40,7 @@ class Inet4AddressImpl implements InetAddressImpl {
public synchronized InetAddress anyLocalAddress() { public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) { if (anyLocalAddress == null) {
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00} anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
anyLocalAddress.hostName = "0.0.0.0"; anyLocalAddress.holder().hostName = "0.0.0.0";
} }
return anyLocalAddress; return anyLocalAddress;
} }
......
...@@ -210,18 +210,18 @@ class Inet6Address extends InetAddress { ...@@ -210,18 +210,18 @@ class Inet6Address extends InetAddress {
Inet6Address() { Inet6Address() {
super(); super();
hostName = null; holder().hostName = null;
ipaddress = new byte[INADDRSZ]; ipaddress = new byte[INADDRSZ];
family = IPv6; holder().family = IPv6;
} }
/* checking of value for scope_id should be done by caller /* checking of value for scope_id should be done by caller
* scope_id must be >= 0, or -1 to indicate not being set * scope_id must be >= 0, or -1 to indicate not being set
*/ */
Inet6Address(String hostName, byte addr[], int scope_id) { Inet6Address(String hostName, byte addr[], int scope_id) {
this.hostName = hostName; holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address if (addr.length == INADDRSZ) { // normal IPv6 address
family = IPv6; holder().family = IPv6;
ipaddress = addr.clone(); ipaddress = addr.clone();
} }
if (scope_id >= 0) { if (scope_id >= 0) {
...@@ -335,9 +335,9 @@ class Inet6Address extends InetAddress { ...@@ -335,9 +335,9 @@ class Inet6Address extends InetAddress {
private void initif(String hostName, byte addr[],NetworkInterface nif) private void initif(String hostName, byte addr[],NetworkInterface nif)
throws UnknownHostException throws UnknownHostException
{ {
this.hostName = hostName; holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address if (addr.length == INADDRSZ) { // normal IPv6 address
family = IPv6; holder().family = IPv6;
ipaddress = addr.clone(); ipaddress = addr.clone();
} }
if (nif != null) { if (nif != null) {
...@@ -420,6 +420,11 @@ class Inet6Address extends InetAddress { ...@@ -420,6 +420,11 @@ class Inet6Address extends InetAddress {
*/ */
private void readObject(ObjectInputStream s) private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
s.defaultReadObject(); s.defaultReadObject();
if (ifname != null && !ifname.equals("")) { if (ifname != null && !ifname.equals("")) {
...@@ -447,7 +452,7 @@ class Inet6Address extends InetAddress { ...@@ -447,7 +452,7 @@ class Inet6Address extends InetAddress {
ipaddress.length); ipaddress.length);
} }
if (family != IPv6) { if (holder().getFamily() != IPv6) {
throw new InvalidObjectException("invalid address family type"); throw new InvalidObjectException("invalid address family type");
} }
} }
......
...@@ -81,7 +81,7 @@ class Inet6AddressImpl implements InetAddressImpl { ...@@ -81,7 +81,7 @@ class Inet6AddressImpl implements InetAddressImpl {
if (anyLocalAddress == null) { if (anyLocalAddress == null) {
if (InetAddress.preferIPv6Address) { if (InetAddress.preferIPv6Address) {
anyLocalAddress = new Inet6Address(); anyLocalAddress = new Inet6Address();
anyLocalAddress.hostName = "::"; anyLocalAddress.holder().hostName = "::";
} else { } else {
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress(); anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
} }
......
...@@ -35,8 +35,12 @@ import java.util.ArrayList; ...@@ -35,8 +35,12 @@ import java.util.ArrayList;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
import sun.security.action.*; import sun.security.action.*;
import sun.net.InetAddressCachePolicy; import sun.net.InetAddressCachePolicy;
import sun.net.util.IPAddressUtil; import sun.net.util.IPAddressUtil;
...@@ -199,26 +203,49 @@ class InetAddress implements java.io.Serializable { ...@@ -199,26 +203,49 @@ class InetAddress implements java.io.Serializable {
/* Specify address family preference */ /* Specify address family preference */
static transient boolean preferIPv6Address = false; static transient boolean preferIPv6Address = false;
/** static class InetAddressHolder {
* @serial
*/ InetAddressHolder() {}
InetAddressHolder(String hostName, int address, int family) {
this.hostName = hostName;
this.address = address;
this.family = family;
}
String hostName; String hostName;
String getHostName() {
return hostName;
}
/** /**
* Holds a 32-bit IPv4 address. * Holds a 32-bit IPv4 address.
*
* @serial
*/ */
int address; int address;
int getAddress() {
return address;
}
/** /**
* Specifies the address family type, for instance, '1' for IPv4 * Specifies the address family type, for instance, '1' for IPv4
* addresses, and '2' for IPv6 addresses. * addresses, and '2' for IPv6 addresses.
*
* @serial
*/ */
int family; int family;
int getFamily() {
return family;
}
}
/* Used to store the serializable fields of InetAddress */
private final transient InetAddressHolder holder;
InetAddressHolder holder() {
return holder;
}
/* Used to store the name service provider */ /* Used to store the name service provider */
private static List<NameService> nameServices = null; private static List<NameService> nameServices = null;
...@@ -251,6 +278,7 @@ class InetAddress implements java.io.Serializable { ...@@ -251,6 +278,7 @@ class InetAddress implements java.io.Serializable {
* put in the address cache, since it is not created by name. * put in the address cache, since it is not created by name.
*/ */
InetAddress() { InetAddress() {
holder = new InetAddressHolder();
} }
/** /**
...@@ -263,7 +291,7 @@ class InetAddress implements java.io.Serializable { ...@@ -263,7 +291,7 @@ class InetAddress implements java.io.Serializable {
*/ */
private Object readResolve() throws ObjectStreamException { private Object readResolve() throws ObjectStreamException {
// will replace the deserialized 'this' object // will replace the deserialized 'this' object
return new Inet4Address(this.hostName, this.address); return new Inet4Address(holder().getHostName(), holder().getAddress());
} }
/** /**
...@@ -500,10 +528,10 @@ class InetAddress implements java.io.Serializable { ...@@ -500,10 +528,10 @@ class InetAddress implements java.io.Serializable {
* @see SecurityManager#checkConnect * @see SecurityManager#checkConnect
*/ */
String getHostName(boolean check) { String getHostName(boolean check) {
if (hostName == null) { if (holder().getHostName() == null) {
hostName = InetAddress.getHostFromNameService(this, check); holder().hostName = InetAddress.getHostFromNameService(this, check);
} }
return hostName; return holder().getHostName();
} }
/** /**
...@@ -666,6 +694,7 @@ class InetAddress implements java.io.Serializable { ...@@ -666,6 +694,7 @@ class InetAddress implements java.io.Serializable {
* @return a string representation of this IP address. * @return a string representation of this IP address.
*/ */
public String toString() { public String toString() {
String hostName = holder().getHostName();
return ((hostName != null) ? hostName : "") return ((hostName != null) ? hostName : "")
+ "/" + getHostAddress(); + "/" + getHostAddress();
} }
...@@ -1522,14 +1551,58 @@ class InetAddress implements java.io.Serializable { ...@@ -1522,14 +1551,58 @@ class InetAddress implements java.io.Serializable {
} }
} }
private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE;
static {
try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset(
InetAddress.class.getDeclaredField("holder")
);
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private void readObject (ObjectInputStream s) throws private void readObject (ObjectInputStream s) throws
IOException, ClassNotFoundException { IOException, ClassNotFoundException {
s.defaultReadObject ();
if (getClass().getClassLoader() != null) { if (getClass().getClassLoader() != null) {
hostName = null;
address = 0;
throw new SecurityException ("invalid address type"); throw new SecurityException ("invalid address type");
} }
GetField gf = s.readFields();
String host = (String)gf.get("hostName", null);
int address= gf.get("address", 0);
int family= gf.get("family", 0);
InetAddressHolder h = new InetAddressHolder(host, address, family);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
/* needed because the serializable fields no longer exist */
/**
* @serialField hostName String
* @serialField address int
* @serialField family int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("hostName", String.class),
new ObjectStreamField("address", int.class),
new ObjectStreamField("family", int.class),
};
private void writeObject (ObjectOutputStream s) throws
IOException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
PutField pf = s.putFields();
pf.put("hostName", holder().getHostName());
pf.put("address", holder().getAddress());
pf.put("family", holder().getFamily());
s.writeFields();
s.flush();
} }
} }
......
...@@ -87,8 +87,8 @@ public class InetSocketAddress ...@@ -87,8 +87,8 @@ public class InetSocketAddress
if (hostname != null) if (hostname != null)
return hostname; return hostname;
if (addr != null) { if (addr != null) {
if (addr.hostName != null) if (addr.holder().getHostName() != null)
return addr.hostName; return addr.holder().getHostName();
else else
return addr.getHostAddress(); return addr.getHostAddress();
} }
......
/* /*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -120,6 +120,13 @@ public class LogStream extends PrintStream { ...@@ -120,6 +120,13 @@ public class LogStream extends PrintStream {
*/ */
@Deprecated @Deprecated
public static synchronized void setDefaultStream(PrintStream newDefault) { public static synchronized void setDefaultStream(PrintStream newDefault) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new java.util.logging.LoggingPermission("control", null));
}
defaultStream = newDefault; defaultStream = newDefault;
} }
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package java.security; package java.security;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
/** /**
* <p> The AccessController class is used for access control operations * <p> The AccessController class is used for access control operations
...@@ -264,6 +266,7 @@ public final class AccessController { ...@@ -264,6 +266,7 @@ public final class AccessController {
* @see java.security.DomainCombiner * @see java.security.DomainCombiner
*/ */
@CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action); public static native <T> T doPrivileged(PrivilegedAction<T> action);
/** /**
...@@ -288,14 +291,15 @@ public final class AccessController { ...@@ -288,14 +291,15 @@ public final class AccessController {
* *
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) { public static <T> T doPrivilegedWithCombiner(PrivilegedAction<T> action) {
AccessControlContext acc = getStackAccessControlContext(); AccessControlContext acc = getStackAccessControlContext();
if (acc == null) { if (acc == null) {
return AccessController.doPrivileged(action); return AccessController.doPrivileged(action);
} }
DomainCombiner dc = acc.getAssignedCombiner(); DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action, preserveCombiner(dc)); return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
} }
...@@ -326,6 +330,7 @@ public final class AccessController { ...@@ -326,6 +330,7 @@ public final class AccessController {
* @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/ */
@CallerSensitive
public static native <T> T doPrivileged(PrivilegedAction<T> action, public static native <T> T doPrivileged(PrivilegedAction<T> action,
AccessControlContext context); AccessControlContext context);
...@@ -353,6 +358,7 @@ public final class AccessController { ...@@ -353,6 +358,7 @@ public final class AccessController {
* @see #doPrivilegedWithCombiner(PrivilegedExceptionAction) * @see #doPrivilegedWithCombiner(PrivilegedExceptionAction)
* @see java.security.DomainCombiner * @see java.security.DomainCombiner
*/ */
@CallerSensitive
public static native <T> T public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action) doPrivileged(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException; throws PrivilegedActionException;
...@@ -383,34 +389,29 @@ public final class AccessController { ...@@ -383,34 +389,29 @@ public final class AccessController {
* *
* @since 1.6 * @since 1.6
*/ */
public static <T> T doPrivilegedWithCombiner @CallerSensitive
(PrivilegedExceptionAction<T> action) throws PrivilegedActionException { public static <T> T doPrivilegedWithCombiner(PrivilegedExceptionAction<T> action)
throws PrivilegedActionException
{
AccessControlContext acc = getStackAccessControlContext(); AccessControlContext acc = getStackAccessControlContext();
if (acc == null) { if (acc == null) {
return AccessController.doPrivileged(action); return AccessController.doPrivileged(action);
} }
DomainCombiner dc = acc.getAssignedCombiner(); DomainCombiner dc = acc.getAssignedCombiner();
return AccessController.doPrivileged(action, preserveCombiner(dc)); return AccessController.doPrivileged(action,
preserveCombiner(dc, Reflection.getCallerClass()));
} }
/** /**
* preserve the combiner across the doPrivileged call * preserve the combiner across the doPrivileged call
*/ */
private static AccessControlContext preserveCombiner private static AccessControlContext preserveCombiner(DomainCombiner combiner,
(DomainCombiner combiner) { Class<?> caller)
{
/**
* callerClass[0] = Reflection.getCallerClass
* callerClass[1] = AccessController.preserveCombiner
* callerClass[2] = AccessController.doPrivileged
* callerClass[3] = caller
*/
final Class<?> callerClass = sun.reflect.Reflection.getCallerClass(3);
ProtectionDomain callerPd = doPrivileged ProtectionDomain callerPd = doPrivileged
(new PrivilegedAction<ProtectionDomain>() { (new PrivilegedAction<ProtectionDomain>() {
public ProtectionDomain run() { public ProtectionDomain run() {
return callerClass.getProtectionDomain(); return caller.getProtectionDomain();
} }
}); });
...@@ -455,6 +456,7 @@ public final class AccessController { ...@@ -455,6 +456,7 @@ public final class AccessController {
* @see #doPrivileged(PrivilegedAction) * @see #doPrivileged(PrivilegedAction)
* @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext) * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/ */
@CallerSensitive
public static native <T> T public static native <T> T
doPrivileged(PrivilegedExceptionAction<T> action, doPrivileged(PrivilegedExceptionAction<T> action,
AccessControlContext context) AccessControlContext context)
......
...@@ -30,6 +30,7 @@ import java.util.ServiceLoader; ...@@ -30,6 +30,7 @@ import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
...@@ -192,14 +193,11 @@ public class DriverManager { ...@@ -192,14 +193,11 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url, public static Connection getConnection(String url,
java.util.Properties info) throws SQLException { java.util.Properties info) throws SQLException {
// Gets the classloader of the code that called this method, may return (getConnection(url, info, Reflection.getCallerClass()));
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
return (getConnection(url, info, callerCL));
} }
/** /**
...@@ -226,14 +224,11 @@ public class DriverManager { ...@@ -226,14 +224,11 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url, public static Connection getConnection(String url,
String user, String password) throws SQLException { String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties(); java.util.Properties info = new java.util.Properties();
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
if (user != null) { if (user != null) {
info.put("user", user); info.put("user", user);
} }
...@@ -241,7 +236,7 @@ public class DriverManager { ...@@ -241,7 +236,7 @@ public class DriverManager {
info.put("password", password); info.put("password", password);
} }
return (getConnection(url, info, callerCL)); return (getConnection(url, info, Reflection.getCallerClass()));
} }
/** /**
...@@ -259,16 +254,12 @@ public class DriverManager { ...@@ -259,16 +254,12 @@ public class DriverManager {
* has been exceeded and has at least tried to cancel the * has been exceeded and has at least tried to cancel the
* current database connection attempt * current database connection attempt
*/ */
@CallerSensitive
public static Connection getConnection(String url) public static Connection getConnection(String url)
throws SQLException { throws SQLException {
java.util.Properties info = new java.util.Properties(); java.util.Properties info = new java.util.Properties();
return (getConnection(url, info, Reflection.getCallerClass()));
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
return (getConnection(url, info, callerCL));
} }
/** /**
...@@ -282,21 +273,20 @@ public class DriverManager { ...@@ -282,21 +273,20 @@ public class DriverManager {
* that can connect to the given URL * that can connect to the given URL
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
@CallerSensitive
public static Driver getDriver(String url) public static Driver getDriver(String url)
throws SQLException { throws SQLException {
println("DriverManager.getDriver(\"" + url + "\")"); println("DriverManager.getDriver(\"" + url + "\")");
// Gets the classloader of the code that called this method, may Class<?> callerClass = Reflection.getCallerClass();
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded registeredDrivers attempting to locate someone // Walk through the loaded registeredDrivers attempting to locate someone
// who understands the given URL. // who understands the given URL.
for (DriverInfo aDriver : registeredDrivers) { for (DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) { if(isDriverAllowed(aDriver.driver, callerClass)) {
try { try {
if(aDriver.driver.acceptsURL(url)) { if(aDriver.driver.acceptsURL(url)) {
// Success! // Success!
...@@ -350,20 +340,18 @@ public class DriverManager { ...@@ -350,20 +340,18 @@ public class DriverManager {
* @param driver the JDBC Driver to drop * @param driver the JDBC Driver to drop
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
@CallerSensitive
public static synchronized void deregisterDriver(Driver driver) public static synchronized void deregisterDriver(Driver driver)
throws SQLException { throws SQLException {
if (driver == null) { if (driver == null) {
return; return;
} }
// Gets the classloader of the code that called this method,
// may be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
println("DriverManager.deregisterDriver: " + driver); println("DriverManager.deregisterDriver: " + driver);
DriverInfo aDriver = new DriverInfo(driver); DriverInfo aDriver = new DriverInfo(driver);
if(registeredDrivers.contains(aDriver)) { if(registeredDrivers.contains(aDriver)) {
if (isDriverAllowed(driver, callerCL)) { if (isDriverAllowed(driver, Reflection.getCallerClass())) {
registeredDrivers.remove(aDriver); registeredDrivers.remove(aDriver);
} else { } else {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
...@@ -384,18 +372,17 @@ public class DriverManager { ...@@ -384,18 +372,17 @@ public class DriverManager {
* *
* @return the list of JDBC Drivers loaded by the caller's class loader * @return the list of JDBC Drivers loaded by the caller's class loader
*/ */
@CallerSensitive
public static java.util.Enumeration<Driver> getDrivers() { public static java.util.Enumeration<Driver> getDrivers() {
java.util.Vector<Driver> result = new java.util.Vector<>(); java.util.Vector<Driver> result = new java.util.Vector<>();
// Gets the classloader of the code that called this method, may Class<?> callerClass = Reflection.getCallerClass();
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
// Walk through the loaded registeredDrivers. // Walk through the loaded registeredDrivers.
for(DriverInfo aDriver : registeredDrivers) { for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then // If the caller does not have permission to load the driver then
// skip it. // skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) { if(isDriverAllowed(aDriver.driver, callerClass)) {
result.addElement(aDriver.driver); result.addElement(aDriver.driver);
} else { } else {
println(" skipping: " + aDriver.getClass().getName()); println(" skipping: " + aDriver.getClass().getName());
...@@ -493,17 +480,13 @@ public class DriverManager { ...@@ -493,17 +480,13 @@ public class DriverManager {
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Internal method used to get the caller's class loader.
// Replaces the call to the native method
private static ClassLoader getCallerClassLoader() {
Class<?> cc = Reflection.getCallerClass(3);
ClassLoader cl = (cc != null) ? cc.getClassLoader() : null;
return cl;
}
// Indicates whether the class object that would be created if the code calling // Indicates whether the class object that would be created if the code calling
// DriverManager is accessible. // DriverManager is accessible.
private static boolean isDriverAllowed(Driver driver, Class<?> caller) {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
return isDriverAllowed(driver, callerCL);
}
private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) { private static boolean isDriverAllowed(Driver driver, ClassLoader classLoader) {
boolean result = false; boolean result = false;
if(driver != null) { if(driver != null) {
...@@ -556,7 +539,7 @@ public class DriverManager { ...@@ -556,7 +539,7 @@ public class DriverManager {
*/ */
try{ try{
while(driversIterator.hasNext()) { while(driversIterator.hasNext()) {
println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next()); driversIterator.next();
} }
} catch(Throwable t) { } catch(Throwable t) {
// Do nothing // Do nothing
...@@ -586,16 +569,17 @@ public class DriverManager { ...@@ -586,16 +569,17 @@ public class DriverManager {
// Worker method called by the public getConnection() methods. // Worker method called by the public getConnection() methods.
private static Connection getConnection( private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException { String url, java.util.Properties info, Class<?> caller) throws SQLException {
/* /*
* When callerCl is null, we should check the application's * When callerCl is null, we should check the application's
* (which is invoking this class indirectly) * (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar * classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here. * can be loaded from here.
*/ */
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) { synchronized(DriverManager.class) {
// synchronize loading of the correct classloader. // synchronize loading of the correct classloader.
if(callerCL == null) { if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader(); callerCL = Thread.currentThread().getContextClassLoader();
} }
} }
......
...@@ -28,6 +28,9 @@ import java.io.Serializable; ...@@ -28,6 +28,9 @@ import java.io.Serializable;
import java.io.ObjectOutputStream; import java.io.ObjectOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/** /**
* This class consists exclusively of static methods that operate on or return * This class consists exclusively of static methods that operate on or return
...@@ -264,8 +267,7 @@ public class Collections { ...@@ -264,8 +267,7 @@ public class Collections {
} }
private static <T> private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
{
int low = 0; int low = 0;
int high = list.size()-1; int high = list.size()-1;
...@@ -441,21 +443,21 @@ public class Collections { ...@@ -441,21 +443,21 @@ public class Collections {
/** /**
* Randomly permutes the specified list using a default source of * Randomly permutes the specified list using a default source of
* randomness. All permutations occur with approximately equal * randomness. All permutations occur with approximately equal
* likelihood.<p> * likelihood.
* *
* The hedge "approximately" is used in the foregoing description because * <p>The hedge "approximately" is used in the foregoing description because
* default source of randomness is only approximately an unbiased source * default source of randomness is only approximately an unbiased source
* of independently chosen bits. If it were a perfect source of randomly * of independently chosen bits. If it were a perfect source of randomly
* chosen bits, then the algorithm would choose permutations with perfect * chosen bits, then the algorithm would choose permutations with perfect
* uniformity.<p> * uniformity.
* *
* This implementation traverses the list backwards, from the last element * <p>This implementation traverses the list backwards, from the last
* up to the second, repeatedly swapping a randomly selected element into * element up to the second, repeatedly swapping a randomly selected element
* the "current position". Elements are randomly selected from the * into the "current position". Elements are randomly selected from the
* portion of the list that runs from the first element to the current * portion of the list that runs from the first element to the current
* position, inclusive.<p> * position, inclusive.
* *
* This method runs in linear time. If the specified list does not * <p>This method runs in linear time. If the specified list does not
* implement the {@link RandomAccess} interface and is large, this * implement the {@link RandomAccess} interface and is large, this
* implementation dumps the specified list into an array before shuffling * implementation dumps the specified list into an array before shuffling
* it, and dumps the shuffled array back into the list. This avoids the * it, and dumps the shuffled array back into the list. This avoids the
...@@ -469,9 +471,10 @@ public class Collections { ...@@ -469,9 +471,10 @@ public class Collections {
public static void shuffle(List<?> list) { public static void shuffle(List<?> list) {
Random rnd = r; Random rnd = r;
if (rnd == null) if (rnd == null)
r = rnd = new Random(); r = rnd = new Random(); // harmless race.
shuffle(list, rnd); shuffle(list, rnd);
} }
private static Random r; private static Random r;
/** /**
...@@ -1391,6 +1394,67 @@ public class Collections { ...@@ -1391,6 +1394,67 @@ public class Collections {
public int hashCode() {return m.hashCode();} public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();} public String toString() {return m.toString();}
// Override default methods in Map
@Override
@SuppressWarnings("unchecked")
public V getOrDefault(Object k, V defaultValue) {
// Safe cast as we don't change the value
return ((Map<K, V>)m).getOrDefault(k, defaultValue);
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
m.forEach(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
/** /**
* We need this class in addition to UnmodifiableSet as * We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map * Map.Entries themselves permit modification of the backing Map
...@@ -1590,9 +1654,9 @@ public class Collections { ...@@ -1590,9 +1654,9 @@ public class Collections {
* </pre> * </pre>
* Failure to follow this advice may result in non-deterministic behavior. * Failure to follow this advice may result in non-deterministic behavior.
* *
* <p>The returned collection does <i>not</i> pass the <tt>hashCode</tt> * <p>The returned collection does <i>not</i> pass the {@code hashCode}
* and <tt>equals</tt> operations through to the backing collection, but * and {@code equals} operations through to the backing collection, but
* relies on <tt>Object</tt>'s equals and hashCode methods. This is * relies on {@code Object}'s equals and hashCode methods. This is
* necessary to preserve the contracts of these operations in the case * necessary to preserve the contracts of these operations in the case
* that the backing collection is a set or a list.<p> * that the backing collection is a set or a list.<p>
* *
...@@ -2107,6 +2171,57 @@ public class Collections { ...@@ -2107,6 +2171,57 @@ public class Collections {
public String toString() { public String toString() {
synchronized (mutex) {return m.toString();} synchronized (mutex) {return m.toString();}
} }
// Override default methods in Map
@Override
public V getOrDefault(Object k, V defaultValue) {
synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
synchronized (mutex) {m.forEach(action);}
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
synchronized (mutex) {m.replaceAll(function);}
}
@Override
public V putIfAbsent(K key, V value) {
synchronized (mutex) {return m.putIfAbsent(key, value);}
}
@Override
public boolean remove(Object key, Object value) {
synchronized (mutex) {return m.remove(key, value);}
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
synchronized (mutex) {return m.replace(key, oldValue, newValue);}
}
@Override
public V replace(K key, V value) {
synchronized (mutex) {return m.replace(key, value);}
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.compute(key, remappingFunction);}
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.merge(key, value, remappingFunction);}
}
private void writeObject(ObjectOutputStream s) throws IOException { private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();} synchronized (mutex) {s.defaultWriteObject();}
} }
...@@ -2326,6 +2441,8 @@ public class Collections { ...@@ -2326,6 +2441,8 @@ public class Collections {
} }
public Iterator<E> iterator() { public Iterator<E> iterator() {
// JDK-6363904 - unwrapped iterator could be typecast to
// ListIterator with unsafe set()
final Iterator<E> it = c.iterator(); final Iterator<E> it = c.iterator();
return new Iterator<E>() { return new Iterator<E>() {
public boolean hasNext() { return it.hasNext(); } public boolean hasNext() { return it.hasNext(); }
...@@ -2717,6 +2834,16 @@ public class Collections { ...@@ -2717,6 +2834,16 @@ public class Collections {
throw new ClassCastException(badValueMsg(value)); throw new ClassCastException(badValueMsg(value));
} }
private BiFunction<? super K, ? super V, ? extends V> typeCheck(
BiFunction<? super K, ? super V, ? extends V> func) {
Objects.requireNonNull(func);
return (k, v) -> {
V newValue = func.apply(k, v);
typeCheck(k, newValue);
return newValue;
};
}
private String badKeyMsg(Object key) { private String badKeyMsg(Object key) {
return "Attempt to insert " + key.getClass() + return "Attempt to insert " + key.getClass() +
" key into map with key type " + keyType; " key into map with key type " + keyType;
...@@ -2768,7 +2895,7 @@ public class Collections { ...@@ -2768,7 +2895,7 @@ public class Collections {
Object v = e.getValue(); Object v = e.getValue();
typeCheck(k, v); typeCheck(k, v);
checked.add( checked.add(
new AbstractMap.SimpleImmutableEntry<>((K) k, (V) v)); new AbstractMap.SimpleImmutableEntry<>((K)k, (V)v));
} }
for (Map.Entry<K,V> e : checked) for (Map.Entry<K,V> e : checked)
m.put(e.getKey(), e.getValue()); m.put(e.getKey(), e.getValue());
...@@ -2782,6 +2909,74 @@ public class Collections { ...@@ -2782,6 +2909,74 @@ public class Collections {
return entrySet; return entrySet;
} }
// Override default methods in Map
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
m.forEach(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
m.replaceAll(typeCheck(function));
}
@Override
public V putIfAbsent(K key, V value) {
typeCheck(key, value);
return m.putIfAbsent(key, value);
}
@Override
public boolean remove(Object key, Object value) {
return m.remove(key, value);
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
typeCheck(key, newValue);
return m.replace(key, oldValue, newValue);
}
@Override
public V replace(K key, V value) {
typeCheck(key, value);
return m.replace(key, value);
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
return m.computeIfAbsent(key, k -> {
V value = mappingFunction.apply(k);
typeCheck(k, value);
return value;
});
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
return m.computeIfPresent(key, typeCheck(remappingFunction));
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
return m.compute(key, typeCheck(remappingFunction));
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
return m.merge(key, value, (v1, v2) -> {
V newValue = remappingFunction.apply(v1, v2);
typeCheck(null, newValue);
return newValue;
});
}
/** /**
* We need this class in addition to CheckedSet as Map.Entry permits * We need this class in addition to CheckedSet as Map.Entry permits
* modification of the backing Map via the setValue operation. This * modification of the backing Map via the setValue operation. This
...@@ -3456,6 +3651,67 @@ public class Collections { ...@@ -3456,6 +3651,67 @@ public class Collections {
public int hashCode() {return 0;} public int hashCode() {return 0;}
// Override default methods in Map
@Override
@SuppressWarnings("unchecked")
public V getOrDefault(Object k, V defaultValue) {
return defaultValue;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
// Preserves singleton property // Preserves singleton property
private Object readResolve() { private Object readResolve() {
return EMPTY_MAP; return EMPTY_MAP;
...@@ -3619,6 +3875,65 @@ public class Collections { ...@@ -3619,6 +3875,65 @@ public class Collections {
return values; return values;
} }
// Override default methods in Map
@Override
public V getOrDefault(Object key, V defaultValue) {
return eq(key, k) ? v : defaultValue;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
action.accept(k, v);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
} }
// Miscellaneous // Miscellaneous
......
# #
# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -28,7 +28,7 @@ formatVersion=1 ...@@ -28,7 +28,7 @@ formatVersion=1
# Version of the currency code information in this class. # Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment. # It is a serial number that accompanies with each amendment.
dataVersion=154 dataVersion=155
# List of all valid ISO 4217 currency codes. # List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes. # To ensure compatibility, do not remove codes.
...@@ -585,7 +585,7 @@ ZW=ZWL ...@@ -585,7 +585,7 @@ ZW=ZWL
minor0=\ minor0=\
ADP-BEF-BIF-BYB-BYR-CLF-CLP-DJF-ESP-GNF-\ ADP-BEF-BIF-BYB-BYR-CLF-CLP-DJF-ESP-GNF-\
GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-RWF-\ GRD-ISK-ITL-JPY-KMF-KRW-LUF-MGF-PYG-PTE-RWF-\
TPE-TRL-VND-VUV-XAF-XOF-XPF TPE-TRL-UGX-VND-VUV-XAF-XOF-XPF
minor1= minor1=
minor3=\ minor3=\
BHD-IQD-JOD-KWD-LYD-OMR-TND BHD-IQD-JOD-KWD-LYD-OMR-TND
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,7 +24,11 @@ ...@@ -24,7 +24,11 @@
*/ */
package java.util; package java.util;
import java.io.*; import java.io.*;
import java.util.function.Consumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/** /**
* Hash table based implementation of the <tt>Map</tt> interface. This * Hash table based implementation of the <tt>Map</tt> interface. This
...@@ -376,6 +380,13 @@ public class HashMap<K,V> ...@@ -376,6 +380,13 @@ public class HashMap<K,V>
return null == entry ? null : entry.getValue(); return null == entry ? null : entry.getValue();
} }
@Override
public V getOrDefault(Object key, V defaultValue) {
Entry<K,V> entry = getEntry(key);
return (entry == null) ? defaultValue : entry.getValue();
}
/** /**
* Returns <tt>true</tt> if this map contains a mapping for the * Returns <tt>true</tt> if this map contains a mapping for the
* specified key. * specified key.
...@@ -603,6 +614,261 @@ public class HashMap<K,V> ...@@ -603,6 +614,261 @@ public class HashMap<K,V>
return (e == null ? null : e.value); return (e == null ? null : e.value);
} }
// optimized implementations of default methods in Map
@Override
public V putIfAbsent(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for(; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
if(e.value != null) {
return e.value;
}
e.value = value;
modCount++;
e.recordAccess(this);
return null;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
@Override
public boolean remove(Object key, Object value) {
if (isEmpty()) {
return false;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
if (!Objects.equals(e.value, value)) {
return false;
}
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return true;
}
prev = e;
e = next;
}
return false;
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
if (isEmpty()) {
return false;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key) && Objects.equals(e.value, oldValue)) {
e.value = newValue;
e.recordAccess(this);
return true;
}
}
return false;
}
@Override
public V replace(K key, V value) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
return null;
}
@Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
return oldValue == null ? (e.value = mappingFunction.apply(key)) : oldValue;
}
}
V newValue = mappingFunction.apply(key);
if (newValue != null) {
modCount++;
addEntry(hash, key, newValue, i);
}
return newValue;
}
@Override
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
if (oldValue == null)
break;
V newValue = remappingFunction.apply(key, oldValue);
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
return newValue;
}
prev = e;
e = next;
}
return null;
}
@Override
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != oldValue) {
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
}
return newValue;
}
prev = e;
e = next;
}
V newValue = remappingFunction.apply(key, null);
if (newValue != null) {
modCount++;
addEntry(hash, key, newValue, i);
}
return newValue;
}
@Override
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
V newValue = remappingFunction.apply(oldValue, value);
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
return newValue;
}
prev = e;
e = next;
}
if (value != null) {
modCount++;
addEntry(hash, key, value, i);
}
return value;
}
// end of optimized implementations of default methods in Map
/** /**
* Removes and returns the entry associated with the specified key * Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping * in the HashMap. Returns null if the HashMap contains no mapping
...@@ -697,8 +963,8 @@ public class HashMap<K,V> ...@@ -697,8 +963,8 @@ public class HashMap<K,V>
return containsNullValue(); return containsNullValue();
Entry<?,?>[] tab = table; Entry<?,?>[] tab = table;
for (int i = 0; i < tab.length ; i++) for (int i = 0; i < tab.length; i++)
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (value.equals(e.value)) if (value.equals(e.value))
return true; return true;
return false; return false;
...@@ -709,8 +975,8 @@ public class HashMap<K,V> ...@@ -709,8 +975,8 @@ public class HashMap<K,V>
*/ */
private boolean containsNullValue() { private boolean containsNullValue() {
Entry<?,?>[] tab = table; Entry<?,?>[] tab = table;
for (int i = 0; i < tab.length ; i++) for (int i = 0; i < tab.length; i++)
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (e.value == null) if (e.value == null)
return true; return true;
return false; return false;
......
/* /*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,7 +24,11 @@ ...@@ -24,7 +24,11 @@
*/ */
package java.util; package java.util;
import java.io.*; import java.io.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
/** /**
* This class implements a hash table, which maps keys to values. Any * This class implements a hash table, which maps keys to values. Any
...@@ -455,6 +459,26 @@ public class Hashtable<K,V> ...@@ -455,6 +459,26 @@ public class Hashtable<K,V>
} }
} }
private void addEntry(int hash, K key, V value, int index) {
modCount++;
Entry<?,?> tab[] = table;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
/** /**
* Maps the specified <code>key</code> to the specified * Maps the specified <code>key</code> to the specified
* <code>value</code> in this hashtable. Neither the key nor the * <code>value</code> in this hashtable. Neither the key nor the
...@@ -492,21 +516,7 @@ public class Hashtable<K,V> ...@@ -492,21 +516,7 @@ public class Hashtable<K,V>
} }
} }
modCount++; addEntry(hash, key, value, index);
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
return null; return null;
} }
...@@ -892,6 +902,239 @@ public class Hashtable<K,V> ...@@ -892,6 +902,239 @@ public class Hashtable<K,V>
return h; return h;
} }
@Override
public synchronized V getOrDefault(Object key, V defaultValue) {
V result = get(key);
return (null == result) ? defaultValue : result;
}
@Override
public synchronized void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action); // explicit check required in case
// table is empty.
Entry<?,?>[] tab = table;
for (Entry<?,?> entry : tab) {
while (entry != null) {
action.accept((K)entry.key, (V)entry.value);
entry = entry.next;
}
}
}
@Override
public synchronized void replaceAll(
BiFunction<? super K, ? super V, ? extends V> function) {
Map.super.replaceAll(function);
}
@Override
public synchronized V putIfAbsent(K key, V value) {
Objects.requireNonNull(value);
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for (; entry != null; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
if (old == null) {
entry.value = value;
}
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
@Override
public synchronized boolean remove(Object key, Object value) {
Objects.requireNonNull(value);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
e.value = null;
return true;
}
}
return false;
}
@Override
public synchronized boolean replace(K key, V oldValue, V newValue) {
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
if (e.value.equals(oldValue)) {
e.value = newValue;
return true;
} else {
return false;
}
}
}
return false;
}
@Override
public synchronized V replace(K key, V value) {
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
return null;
}
@Override
public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
// Hashtable not accept null value
return e.value;
}
}
V newValue = mappingFunction.apply(key);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
@Override
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
V newValue = remappingFunction.apply(key, e.value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
return null;
}
@Override
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V newValue = remappingFunction.apply(key, e.value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
V newValue = remappingFunction.apply(key, null);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
@Override
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
V newValue = remappingFunction.apply(e.value, value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
if (value != null) {
addEntry(hash, key, value, index);
}
return value;
}
/** /**
* Save the state of the Hashtable to a stream (i.e., serialize it). * Save the state of the Hashtable to a stream (i.e., serialize it).
* *
......
...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap; ...@@ -57,6 +57,8 @@ import java.util.concurrent.ConcurrentMap;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.spi.ResourceBundleControlProvider; import java.util.spi.ResourceBundleControlProvider;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.util.locale.BaseLocale; import sun.util.locale.BaseLocale;
import sun.util.locale.LocaleObjectCache; import sun.util.locale.LocaleObjectCache;
...@@ -440,14 +442,10 @@ public abstract class ResourceBundle { ...@@ -440,14 +442,10 @@ public abstract class ResourceBundle {
/* /*
* Automatic determination of the ClassLoader to be used to load * Automatic determination of the ClassLoader to be used to load
* resources on behalf of the client. N.B. The client is getLoader's * resources on behalf of the client.
* caller's caller.
*/ */
private static ClassLoader getLoader() { private static ClassLoader getLoader(Class<?> caller) {
Class<?>[] stack = getClassContext(); ClassLoader cl = caller == null ? null : caller.getClassLoader();
/* Magic number 2 identifies our caller's caller */
Class<?> c = stack[2];
ClassLoader cl = (c == null) ? null : c.getClassLoader();
if (cl == null) { if (cl == null) {
// When the caller's loader is the boot class loader, cl is null // When the caller's loader is the boot class loader, cl is null
// here. In that case, ClassLoader.getSystemClassLoader() may // here. In that case, ClassLoader.getSystemClassLoader() may
...@@ -461,8 +459,6 @@ public abstract class ResourceBundle { ...@@ -461,8 +459,6 @@ public abstract class ResourceBundle {
return cl; return cl;
} }
private static native Class<?>[] getClassContext();
/** /**
* A wrapper of ClassLoader.getSystemClassLoader(). * A wrapper of ClassLoader.getSystemClassLoader().
*/ */
...@@ -746,11 +742,11 @@ public abstract class ResourceBundle { ...@@ -746,11 +742,11 @@ public abstract class ResourceBundle {
* if no resource bundle for the specified base name can be found * if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and the default locale * @return a resource bundle for the given base name and the default locale
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName) public static final ResourceBundle getBundle(String baseName)
{ {
return getBundleImpl(baseName, Locale.getDefault(), return getBundleImpl(baseName, Locale.getDefault(),
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
getDefaultControl(baseName)); getDefaultControl(baseName));
} }
...@@ -788,11 +784,11 @@ public abstract class ResourceBundle { ...@@ -788,11 +784,11 @@ public abstract class ResourceBundle {
* needed. * needed.
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, public static final ResourceBundle getBundle(String baseName,
Control control) { Control control) {
return getBundleImpl(baseName, Locale.getDefault(), return getBundleImpl(baseName, Locale.getDefault(),
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
control); control);
} }
...@@ -817,12 +813,12 @@ public abstract class ResourceBundle { ...@@ -817,12 +813,12 @@ public abstract class ResourceBundle {
* if no resource bundle for the specified base name can be found * if no resource bundle for the specified base name can be found
* @return a resource bundle for the given base name and locale * @return a resource bundle for the given base name and locale
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, public static final ResourceBundle getBundle(String baseName,
Locale locale) Locale locale)
{ {
return getBundleImpl(baseName, locale, return getBundleImpl(baseName, locale,
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
getDefaultControl(baseName)); getDefaultControl(baseName));
} }
...@@ -863,11 +859,11 @@ public abstract class ResourceBundle { ...@@ -863,11 +859,11 @@ public abstract class ResourceBundle {
* needed. * needed.
* @since 1.6 * @since 1.6
*/ */
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, Locale targetLocale, public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
Control control) { Control control) {
return getBundleImpl(baseName, targetLocale, return getBundleImpl(baseName, targetLocale,
/* must determine loader here, else we break stack invariant */ getLoader(Reflection.getCallerClass()),
getLoader(),
control); control);
} }
...@@ -1721,8 +1717,9 @@ public abstract class ResourceBundle { ...@@ -1721,8 +1717,9 @@ public abstract class ResourceBundle {
* @since 1.6 * @since 1.6
* @see ResourceBundle.Control#getTimeToLive(String,Locale) * @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/ */
@CallerSensitive
public static final void clearCache() { public static final void clearCache() {
clearCache(getLoader()); clearCache(getLoader(Reflection.getCallerClass()));
} }
/** /**
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
package java.util.concurrent; package java.util.concurrent;
import java.io.ObjectInputStream;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
import java.util.*; import java.util.*;
import java.io.Serializable; import java.io.Serializable;
...@@ -1483,7 +1484,23 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1483,7 +1484,23 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s) private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject(); // Don't call defaultReadObject()
ObjectInputStream.GetField oisFields = s.readFields();
final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null);
final int ssize = oisSegments.length;
if (ssize < 1 || ssize > MAX_SEGMENTS
|| (ssize & (ssize-1)) != 0 ) // ssize not power of two
throw new java.io.InvalidObjectException("Bad number of segments:"
+ ssize);
int sshift = 0, ssizeTmp = ssize;
while (ssizeTmp > 1) {
++sshift;
ssizeTmp >>>= 1;
}
UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift);
UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1);
UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments);
// set hashMask // set hashMask
UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
...@@ -1517,6 +1534,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1517,6 +1534,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
private static final long TBASE; private static final long TBASE;
private static final int TSHIFT; private static final int TSHIFT;
private static final long HASHSEED_OFFSET; private static final long HASHSEED_OFFSET;
private static final long SEGSHIFT_OFFSET;
private static final long SEGMASK_OFFSET;
private static final long SEGMENTS_OFFSET;
static { static {
int ss, ts; int ss, ts;
...@@ -1530,6 +1550,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1530,6 +1550,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
ss = UNSAFE.arrayIndexScale(sc); ss = UNSAFE.arrayIndexScale(sc);
HASHSEED_OFFSET = UNSAFE.objectFieldOffset( HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("hashSeed")); ConcurrentHashMap.class.getDeclaredField("hashSeed"));
SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segmentShift"));
SEGMASK_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segmentMask"));
SEGMENTS_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segments"));
} catch (Exception e) { } catch (Exception e) {
throw new Error(e); throw new Error(e);
} }
......
...@@ -38,7 +38,7 @@ import java.util.Map; ...@@ -38,7 +38,7 @@ import java.util.Map;
/** /**
* A {@link java.util.Map} providing additional atomic * A {@link java.util.Map} providing additional atomic
* <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods. * {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
* *
* <p>Memory consistency effects: As with other concurrent * <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a * collections, actions in a thread prior to placing an object into a
...@@ -57,6 +57,21 @@ import java.util.Map; ...@@ -57,6 +57,21 @@ import java.util.Map;
* @param <V> the type of mapped values * @param <V> the type of mapped values
*/ */
public interface ConcurrentMap<K, V> extends Map<K, V> { public interface ConcurrentMap<K, V> extends Map<K, V> {
/**
* {@inheritDoc}
*
* @implNote This implementation assumes that the ConcurrentMap cannot
* contain null values and get() returning null unambiguously means the key
* is absent. Implementations which support null values must override this
* default implementation.
*/
@Override
default V getOrDefault(Object key, V defaultValue) {
V v;
return ((v = get(key)) != null) ? v : defaultValue;
}
/** /**
* If the specified key is not already associated * If the specified key is not already associated
* with a value, associate it with the given value. * with a value, associate it with the given value.
...@@ -91,7 +106,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> { ...@@ -91,7 +106,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* Removes the entry for a key only if currently mapped to a given value. * Removes the entry for a key only if currently mapped to a given value.
* This is equivalent to * This is equivalent to
* <pre> {@code * <pre> {@code
* if (map.containsKey(key) && map.get(key).equals(value)) { * if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
* map.remove(key); * map.remove(key);
* return true; * return true;
* } else * } else
...@@ -101,8 +116,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> { ...@@ -101,8 +116,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* *
* @param key key with which the specified value is associated * @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key * @param value value expected to be associated with the specified key
* @return <tt>true</tt> if the value was removed * @return {@code true} if the value was removed
* @throws UnsupportedOperationException if the <tt>remove</tt> operation * @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this map * is not supported by this map
* @throws ClassCastException if the key or value is of an inappropriate * @throws ClassCastException if the key or value is of an inappropriate
* type for this map * type for this map
...@@ -117,7 +132,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> { ...@@ -117,7 +132,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* Replaces the entry for a key only if currently mapped to a given value. * Replaces the entry for a key only if currently mapped to a given value.
* This is equivalent to * This is equivalent to
* <pre> {@code * <pre> {@code
* if (map.containsKey(key) && map.get(key).equals(oldValue)) { * if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
* map.put(key, newValue); * map.put(key, newValue);
* return true; * return true;
* } else * } else
...@@ -128,8 +143,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> { ...@@ -128,8 +143,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* @param key key with which the specified value is associated * @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key * @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key * @param newValue value to be associated with the specified key
* @return <tt>true</tt> if the value was replaced * @return {@code true} if the value was replaced
* @throws UnsupportedOperationException if the <tt>put</tt> operation * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map * is not supported by this map
* @throws ClassCastException if the class of a specified key or value * @throws ClassCastException if the class of a specified key or value
* prevents it from being stored in this map * prevents it from being stored in this map
...@@ -154,11 +169,11 @@ public interface ConcurrentMap<K, V> extends Map<K, V> { ...@@ -154,11 +169,11 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* @param key key with which the specified value is associated * @param key key with which the specified value is associated
* @param value value to be associated with the specified key * @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or * @return the previous value associated with the specified key, or
* <tt>null</tt> if there was no mapping for the key. * {@code null} if there was no mapping for the key.
* (A <tt>null</tt> return can also indicate that the map * (A {@code null} return can also indicate that the map
* previously associated <tt>null</tt> with the key, * previously associated {@code null} with the key,
* if the implementation supports null values.) * if the implementation supports null values.)
* @throws UnsupportedOperationException if the <tt>put</tt> operation * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map * is not supported by this map
* @throws ClassCastException if the class of the specified key or value * @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map * prevents it from being stored in this map
......
...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic; ...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator; import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator; import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
...@@ -77,8 +80,9 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -77,8 +80,9 @@ public abstract class AtomicIntegerFieldUpdater<T> {
* or the field is inaccessible to the caller according to Java language * or the field is inaccessible to the caller according to Java language
* access control * access control
*/ */
@CallerSensitive
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName); return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName, Reflection.getCallerClass());
} }
/** /**
...@@ -365,9 +369,11 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -365,9 +369,11 @@ public abstract class AtomicIntegerFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, final String fieldName) { AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
final String fieldName,
final Class<?> caller)
{
final Field field; final Field field;
final Class<?> caller;
final int modifiers; final int modifiers;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -376,7 +382,6 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -376,7 +382,6 @@ public abstract class AtomicIntegerFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
......
...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic; ...@@ -37,6 +37,9 @@ package java.util.concurrent.atomic;
import java.util.function.LongUnaryOperator; import java.util.function.LongUnaryOperator;
import java.util.function.LongBinaryOperator; import java.util.function.LongBinaryOperator;
import sun.misc.Unsafe; import sun.misc.Unsafe;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
...@@ -77,11 +80,13 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -77,11 +80,13 @@ public abstract class AtomicLongFieldUpdater<T> {
* or the field is inaccessible to the caller according to Java language * or the field is inaccessible to the caller according to Java language
* access control * access control
*/ */
@CallerSensitive
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) { public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
Class<?> caller = Reflection.getCallerClass();
if (AtomicLong.VM_SUPPORTS_LONG_CAS) if (AtomicLong.VM_SUPPORTS_LONG_CAS)
return new CASUpdater<U>(tclass, fieldName); return new CASUpdater<U>(tclass, fieldName, caller);
else else
return new LockedUpdater<U>(tclass, fieldName); return new LockedUpdater<U>(tclass, fieldName, caller);
} }
/** /**
...@@ -365,9 +370,8 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -365,9 +370,8 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
CASUpdater(final Class<T> tclass, final String fieldName) { CASUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
final Field field; final Field field;
final Class<?> caller;
final int modifiers; final int modifiers;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -376,7 +380,6 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -376,7 +380,6 @@ public abstract class AtomicLongFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
...@@ -490,9 +493,8 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -490,9 +493,8 @@ public abstract class AtomicLongFieldUpdater<T> {
private final Class<T> tclass; private final Class<T> tclass;
private final Class<?> cclass; private final Class<?> cclass;
LockedUpdater(final Class<T> tclass, final String fieldName) { LockedUpdater(final Class<T> tclass, final String fieldName, final Class<?> caller) {
Field field = null; Field field = null;
Class<?> caller = null;
int modifiers = 0; int modifiers = 0;
try { try {
field = AccessController.doPrivileged( field = AccessController.doPrivileged(
...@@ -501,7 +503,6 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -501,7 +503,6 @@ public abstract class AtomicLongFieldUpdater<T> {
return tclass.getDeclaredField(fieldName); return tclass.getDeclaredField(fieldName);
} }
}); });
caller = sun.reflect.Reflection.getCallerClass(3);
modifiers = field.getModifiers(); modifiers = field.getModifiers();
sun.reflect.misc.ReflectUtil.ensureMemberAccess( sun.reflect.misc.ReflectUtil.ensureMemberAccess(
caller, tclass, null, modifiers); caller, tclass, null, modifiers);
......
...@@ -539,7 +539,7 @@ public abstract class EmbeddedFrame extends Frame ...@@ -539,7 +539,7 @@ public abstract class EmbeddedFrame extends Frame
public void toBack() {} public void toBack() {}
public void updateFocusableWindowState() {} public void updateFocusableWindowState() {}
public void updateAlwaysOnTop() {} public void updateAlwaysOnTop() {}
public void setAlwaysOnTop(boolean alwaysOnTop) {} public void updateAlwaysOnTopState() {}
public Component getGlobalHeavyweightFocusOwner() { return null; } public Component getGlobalHeavyweightFocusOwner() { return null; }
public void setBoundsPrivate(int x, int y, int width, int height) { public void setBoundsPrivate(int x, int y, int width, int height) {
setBounds(x, y, width, height, SET_BOUNDS); setBounds(x, y, width, height, SET_BOUNDS);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册