Mercurial > hg > release > icedtea7-forest-2.4 > jdk
changeset 7322:344829ae761e icedtea-2.4.8pre01
Merge jdk7u55-b14
line wrap: on
line diff
--- a/.hgtags Tue Apr 15 23:54:34 2014 +0100 +++ b/.hgtags Wed Apr 16 19:41:14 2014 +0100 @@ -387,6 +387,7 @@ 8c343a783777b8728cb819938f387db0acf7f3ac jdk7u45-b31 402d54c7d8ce95f3945cc3d698e528e4adec7b9b jdk7u45-b33 34e8f9f26ae612ebac36357eecbe70ea20e0233c jdk7u45-b34 +3dbb06a924cdf73d39b8543824ec88ae501ba5c6 jdk7u45-b35 3c9a6d9eafd31be44b0ade0354e60f5078b417a4 jdk7u51-b00 d76613074ff357d0664b97b4aaf99fbb65dcec47 jdk7u51-b01 fb057871f094ebe4906ad6856326768b01a62c45 jdk7u51-b02 @@ -405,3 +406,21 @@ f582aad1fce8fe3410728dd40778dbde12f63beb icedtea-2.4.6pre01 b5282042aae07c3f9b6fed8879b3db7352556286 icedtea-2.4.6 9448fff932863c309ac8361e7914e71e1b00d1a9 icedtea-2.4.7 +ef58b2b9a9a1e1a42b0139b57816a160c4681371 jdk7u51-b30 +5bca0d0969b13b1d9b8caba3cce8293a98d68318 jdk7u51-b31 +f5eee4f1d5b4a1e19febc9c26c863ae853ed6d2e jdk7u55-b00 +5010db5b9b5ab07a9409a5c557d3f43ab32dc428 jdk7u55-b01 +2ca3e1fa4455ad564228ad6e654498167af2f20d jdk7u55-b02 +c12b3c81366cb067ff4444952209d54bfa387353 jdk7u55-b03 +476d1bddaa32bf440953c3b1814ba38f16886c03 jdk7u55-b04 +7fa6d3ba2cc77cd1e6f24e33f0c39788cb2893b8 jdk7u55-b05 +795654fce29c38d4c8504f760d8d8a36248d38ed jdk7u55-b06 +4b2ed892b195e95f7541aaa3b129a2caa5faae1d jdk7u55-b07 +db1323224053a18ecc62bdc1d3902d93b33f0b70 jdk7u55-b08 +534eeff29ac9fcbbb99ef8908548dbb368d04baf jdk7u55-b09 +d39dd4135844ca5c707bc39ae1d7e020d49880ce jdk7u55-b09 +b231536550067c3b00c77d0e035afe8faaa15581 jdk7u55-b10 +2d80b7cd7aae76f0909a210414317dcf846ad651 jdk7u55-b11 +07be5d5508733ed37c11fcd21a13ae3c8288313b jdk7u55-b12 +92fd166252c2701092a510002f4cf9285a20473d jdk7u55-b13 +4a5651c84b1e6cf26dc9b19f00747e5004efba68 jdk7u55-b30
--- a/make/common/Defs-embedded.gmk Tue Apr 15 23:54:34 2014 +0100 +++ b/make/common/Defs-embedded.gmk Wed Apr 16 19:41:14 2014 +0100 @@ -71,7 +71,9 @@ # and it must be linked after fdlibm - this places it at the end after libc # -z muldefs avoids linker errors for duplicate symbols. ifeq ($(CROSS_COMPILE_ARCH), arm) - EXTRA_LIBS += $(EXT_LIBS_PATH)/sflt_glibc_jdk.a -Xlinker -z -Xlinker muldefs + ifneq ($(EXT_LIBS_PATH),) + EXTRA_LIBS += $(EXT_LIBS_PATH)/sflt_glibc_jdk.a -Xlinker -z -Xlinker muldefs + endif endif endif
--- a/make/java/java/Exportedfiles.gmk Tue Apr 15 23:54:34 2014 +0100 +++ b/make/java/java/Exportedfiles.gmk Wed Apr 16 19:41:14 2014 +0100 @@ -50,6 +50,7 @@ java/lang/SecurityManager.java \ java/lang/Shutdown.java \ java/lang/Package.java \ + java/lang/UNIXProcess.java \ java/lang/ref/Finalizer.java \ java/lang/reflect/AccessibleObject.java \ java/lang/reflect/Field.java \
--- a/make/java/java/Makefile Tue Apr 15 23:54:34 2014 +0100 +++ b/make/java/java/Makefile Wed Apr 16 19:41:14 2014 +0100 @@ -84,6 +84,7 @@ java/util/prefs/FileSystemPreferencesFactory.java \ FILES_c += UNIXProcess_md.c \ + childproc.c \ UnixFileSystem_md.c \ canonicalize_md.c \ TimeZone.c \ @@ -451,3 +452,36 @@ clean:: $(RM) $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java + +HELPER_EXE = $(LIBDIR)/$(LIBARCH)/jspawnhelper +BUILDHELPER = +ifeq ($(PLATFORM), solaris) + BUILDHELPER = 1 +endif +ifeq ($(PLATFORM), macosx) + HELPER_EXE = $(LIBDIR)/jspawnhelper + BUILDHELPER = 1 +endif + +ARCHFLAG = +ifeq ($(ARCH_DATA_MODEL), 64) +ARCHFLAG = -m64 +endif + +ifdef BUILDHELPER + +HELPER_EXE_FILES_c = jspawnhelper.c +HELPER_EXE_FILES_o = $(OBJDIR)/jspawnhelper.o \ + $(OBJDIR)/childproc.o + +$(HELPER_EXE): $(HELPER_EXE_FILES_o) + $(CC) $(ARCHFLAG) $(HELPER_EXE_FILES_o) \ + -o $(TEMPDIR)/jspawnhelper + $(CP) $(TEMPDIR)/jspawnhelper $(HELPER_EXE) + +build: $(HELPER_EXE) + +clean clobber:: + $(RM) $(HELPER_EXE_FILES_o) $(HELPER_EXE) + +endif #BUILDHELPER
--- a/make/java/java/mapfile-vers Tue Apr 15 23:54:34 2014 +0100 +++ b/make/java/java/mapfile-vers Wed Apr 16 19:41:14 2014 +0100 @@ -215,7 +215,7 @@ Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_lang_UNIXProcess_initIDs; + Java_java_lang_UNIXProcess_init; Java_java_lang_UNIXProcess_waitForProcessExit; Java_java_lang_UNIXProcess_forkAndExec; Java_java_lang_UNIXProcess_destroyProcess;
--- a/make/sun/javazic/tzdata/VERSION Tue Apr 15 23:54:34 2014 +0100 +++ b/make/sun/javazic/tzdata/VERSION Wed Apr 16 19:41:14 2014 +0100 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2013h +tzdata2013i
--- a/make/sun/javazic/tzdata/africa Tue Apr 15 23:54:34 2014 +0100 +++ b/make/sun/javazic/tzdata/africa Wed Apr 16 19:41:14 2014 +0100 @@ -500,14 +500,13 @@ Rule Libya 1997 only - Oct 4 0:00 0 - Rule Libya 2013 only - Mar lastFri 1:00 1:00 S Rule Libya 2013 only - Oct lastFri 2:00 0 - - -# The 1996 and 1997 entries are from Shanks & Pottenger; -# the IATA SSIM data contain some obvious errors. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Africa/Tripoli 0:52:44 - LMT 1920 1:00 Libya CE%sT 1959 2:00 - EET 1982 1:00 Libya CE%sT 1990 May 4 +# The 1996 and 1997 entries are from Shanks & Pottenger; +# the IATA SSIM data contain some obvious errors. 2:00 - EET 1996 Sep 30 1:00 Libya CE%sT 1997 Oct 4 2:00 - EET 2012 Nov 10 2:00
--- a/make/sun/javazic/tzdata/asia Tue Apr 15 23:54:34 2014 +0100 +++ b/make/sun/javazic/tzdata/asia Wed Apr 16 19:41:14 2014 +0100 @@ -1403,12 +1403,22 @@ # switch back to standard time this winter, so the will stay on DST # until about the same time next year (at least). # http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?NewsID=88950 -# -# From Paul Eggert (2013-09-21): -# It's looking like this change will be permanent; see -# Petra News Agency, Cancelling winter saved Jordan $7 million (2013-02-20) -# <http://www.albawaba.com/business/jordan-winter-electricity--472005>. -# So move Jordan to UTC+3 as of the abovementioned date. + +# From Steffen Thorsen (2013-12-11): +# Jordan Times and other sources say that Jordan is going back to +# UTC+2 on 2013-12-19 at midnight: +# http://jordantimes.com/govt-decides-to-switch-back-to-wintertime +# Official, in Arabic: +# http://www.petra.gov.jo/public_news/Nws_NewsDetails.aspx?Menu_ID=&Site_Id=2&lang=1&NewsID=133230&CatID=14 +# ... Our background/permalink about it +# http://www.timeanddate.com/news/time/jordan-reverses-dst-decision.html +# ... +# http://www.petra.gov.jo/Public_News/Nws_NewsDetails.aspx?lang=2&site_id=1&NewsID=133313&Type=P +# ... says midnight for the coming one and 1:00 for the ones in the future +# (and they will use DST again next year, using the normal schedule). + +# From Paul Eggert (2013-12-11): +# As Steffen suggested, consider the past 21-month experiment to be DST. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Jordan 1973 only - Jun 6 0:00 1:00 S @@ -1438,11 +1448,13 @@ Rule Jordan 2003 only - Oct 24 0:00s 0 - Rule Jordan 2004 only - Oct 15 0:00s 0 - Rule Jordan 2005 only - Sep lastFri 0:00s 0 - -Rule Jordan 2006 2012 - Oct lastFri 0:00s 0 - +Rule Jordan 2006 2011 - Oct lastFri 0:00s 0 - +Rule Jordan 2013 only - Dec 20 0:00 0 - +Rule Jordan 2014 max - Mar lastThu 24:00 1:00 S +Rule Jordan 2014 max - Oct lastFri 0:00s 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Amman 2:23:44 - LMT 1931 - 2:00 Jordan EE%sT 2012 Oct 26 0:00s - 3:00 - AST + 2:00 Jordan EE%sT # Kazakhstan
--- a/make/sun/javazic/tzdata/northamerica Tue Apr 15 23:54:34 2014 +0100 +++ b/make/sun/javazic/tzdata/northamerica Wed Apr 16 19:41:14 2014 +0100 @@ -2688,6 +2688,11 @@ # to DST--and one more hour on 1999-04-04--when the announcers will have # returned to Baltimore, which switches on that date.) +# From Steffen Thorsen (2013-11-11): +# DST start in Cuba in 2004 ... does not follow the same rules as the +# years before. The correct date should be Sunday 2004-03-28 00:00 ... +# https://web.archive.org/web/20040402060750/http://www.granma.cu/espanol/2004/marzo/sab27/reloj.html + # From Evert van der Veer via Steffen Thorsen (2004-10-28): # Cuba is not going back to standard time this year. # From Paul Eggert (2006-03-22): @@ -2877,7 +2882,8 @@ Rule Cuba 1997 only - Oct 12 0:00s 0 S Rule Cuba 1998 1999 - Mar lastSun 0:00s 1:00 D Rule Cuba 1998 2003 - Oct lastSun 0:00s 0 S -Rule Cuba 2000 2004 - Apr Sun>=1 0:00s 1:00 D +Rule Cuba 2000 2003 - Apr Sun>=1 0:00s 1:00 D +Rule Cuba 2004 only - Mar lastSun 0:00s 1:00 D Rule Cuba 2006 2010 - Oct lastSun 0:00s 0 S Rule Cuba 2007 only - Mar Sun>=8 0:00s 1:00 D Rule Cuba 2008 only - Mar Sun>=15 0:00s 1:00 D
--- a/src/macosx/classes/sun/font/CFontManager.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/font/CFontManager.java Wed Apr 16 19:41:14 2014 +0100 @@ -218,20 +218,22 @@ }); } }; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Object>() { - public Object run() { - /* The thread must be a member of a thread group - * which will not get GCed before VM exit. - * Make its parent the top-level thread group. - */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - fileCloser = new Thread(rootTG, fileCloserRunnable); - fileCloser.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(fileCloser); - return null; + AccessController.doPrivileged( + new PrivilegedAction<Void>() { + @Override + public Void run() { + /* The thread must be a member of a thread group + * which will not get GCed before VM exit. + * Make its parent the top-level thread group. + */ + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + fileCloser = new Thread(rootTG, fileCloserRunnable); + fileCloser.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(fileCloser); + return null; + } } - }); + ); } } }
--- a/src/macosx/classes/sun/font/CStrike.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/font/CStrike.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ import sun.awt.SunHints; -public class CStrike extends FontStrike { +public final class CStrike extends FontStrike { // Creates the native strike private static native long createNativeStrikePtr(long nativeFontPtr, @@ -68,10 +68,10 @@ Rectangle2D.Float result, double x, double y); - private CFont nativeFont; + private final CFont nativeFont; private AffineTransform invDevTx; - private GlyphInfoCache glyphInfoCache; - private GlyphAdvanceCache glyphAdvanceCache; + private final GlyphInfoCache glyphInfoCache; + private final GlyphAdvanceCache glyphAdvanceCache; private long nativeStrikePtr; CStrike(final CFont font, final FontStrikeDesc inDesc) { @@ -84,11 +84,11 @@ // Normally the device transform should be the identity transform // for screen operations. The device transform only becomes // interesting when we are outputting between different dpi surfaces, - // like when we are printing to postscript. + // like when we are printing to postscript or use retina. if (inDesc.devTx != null && !inDesc.devTx.isIdentity()) { try { invDevTx = inDesc.devTx.createInverse(); - } catch (NoninvertibleTransformException e) { + } catch (NoninvertibleTransformException ignored) { // ignored, since device transforms should not be that // complicated, and if they are - there is nothing we can do, // so we won't worry about it. @@ -134,15 +134,13 @@ nativeStrikePtr = 0; } - // the fractional metrics default on our platform is OFF - private boolean useFractionalMetrics() { - return desc.fmHint == SunHints.INTVAL_FRACTIONALMETRICS_ON; - } + @Override public int getNumGlyphs() { return nativeFont.getNumGlyphs(); } + @Override StrikeMetrics getFontMetrics() { if (strikeMetrics == null) { StrikeMetrics metrics = getFontMetrics(getNativeStrikePtr()); @@ -155,74 +153,24 @@ return strikeMetrics; } - float getGlyphAdvance(int glyphCode) { - return getScaledAdvanceForAdvance(getCachedNativeGlyphAdvance(glyphCode)); - } - - float getCodePointAdvance(int cp) { - float advance = getCachedNativeGlyphAdvance(nativeFont.getMapper().charToGlyph(cp)); - - double glyphScaleX = desc.glyphTx.getScaleX(); - double devScaleX = desc.devTx.getScaleX(); - - if (devScaleX == 0) { - glyphScaleX = Math.sqrt(desc.glyphTx.getDeterminant()); - devScaleX = Math.sqrt(desc.devTx.getDeterminant()); - } - - if (devScaleX == 0) { - devScaleX = Double.NaN; // this an undefined graphics state - } - advance = (float) (advance * glyphScaleX / devScaleX); - return useFractionalMetrics() ? advance : Math.round(advance); - } - - // calculate an advance, and round if not using fractional metrics - private float getScaledAdvanceForAdvance(float advance) { - if (invDevTx != null) { - advance *= invDevTx.getScaleX(); - } - advance *= desc.glyphTx.getScaleX(); - return useFractionalMetrics() ? advance : Math.round(advance); + @Override + float getGlyphAdvance(final int glyphCode) { + return getCachedNativeGlyphAdvance(glyphCode); } - Point2D.Float getCharMetrics(char ch) { - return getScaledPointForAdvance(getCachedNativeGlyphAdvance(nativeFont.getMapper().charToGlyph(ch))); - } - - Point2D.Float getGlyphMetrics(int glyphCode) { - return getScaledPointForAdvance(getCachedNativeGlyphAdvance(glyphCode)); + @Override + float getCodePointAdvance(final int cp) { + return getGlyphAdvance(nativeFont.getMapper().charToGlyph(cp)); } - // calculate an advance point, and round if not using fractional metrics - private Point2D.Float getScaledPointForAdvance(float advance) { - Point2D.Float pt = new Point2D.Float(advance, 0); - - if (!desc.glyphTx.isIdentity()) { - return scalePoint(pt); - } - - if (!useFractionalMetrics()) { - pt.x = Math.round(pt.x); - } - return pt; + @Override + Point2D.Float getCharMetrics(final char ch) { + return getGlyphMetrics(nativeFont.getMapper().charToGlyph(ch)); } - private Point2D.Float scalePoint(Point2D.Float pt) { - if (invDevTx != null) { - // transform the point out of the device space first - invDevTx.transform(pt, pt); - } - desc.glyphTx.transform(pt, pt); - pt.x -= desc.glyphTx.getTranslateX(); - pt.y -= desc.glyphTx.getTranslateY(); - - if (!useFractionalMetrics()) { - pt.x = Math.round(pt.x); - pt.y = Math.round(pt.y); - } - - return pt; + @Override + Point2D.Float getGlyphMetrics(final int glyphCode) { + return new Point2D.Float(getGlyphAdvance(glyphCode), 0.0f); } Rectangle2D.Float getGlyphOutlineBounds(int glyphCode) { @@ -414,9 +362,7 @@ private SparseBitShiftingTwoLayerArray secondLayerCache; private HashMap<Integer, Long> generalCache; - public GlyphInfoCache(final Font2D nativeFont, - final FontStrikeDesc desc) - { + GlyphInfoCache(final Font2D nativeFont, final FontStrikeDesc desc) { super(nativeFont, desc); firstLayerCache = new long[FIRST_LAYER_SIZE]; } @@ -527,7 +473,7 @@ final int shift; final int secondLayerLength; - public SparseBitShiftingTwoLayerArray(final int size, final int shift) { + SparseBitShiftingTwoLayerArray(final int size, final int shift) { this.shift = shift; this.cache = new long[1 << shift][]; this.secondLayerLength = size >> shift; @@ -559,6 +505,12 @@ private SparseBitShiftingTwoLayerArray secondLayerCache; private HashMap<Integer, Float> generalCache; + // Empty non private constructor was added because access to this + // class shouldn't be emulated by a synthetic accessor method. + GlyphAdvanceCache() { + super(); + } + public synchronized float get(final int index) { if (index < 0) { if (-index < SECOND_LAYER_SIZE) { @@ -609,9 +561,7 @@ final int shift; final int secondLayerLength; - public SparseBitShiftingTwoLayerArray(final int size, - final int shift) - { + SparseBitShiftingTwoLayerArray(final int size, final int shift) { this.shift = shift; this.cache = new float[1 << shift][]; this.secondLayerLength = size >> shift;
--- a/src/macosx/classes/sun/lwawt/LWToolkit.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/LWToolkit.java Wed Apr 16 19:41:14 2014 +0100 @@ -37,6 +37,7 @@ import sun.awt.*; import sun.lwawt.macosx.*; +import sun.misc.ThreadGroupUtils; import sun.print.*; import sun.misc.ThreadGroupUtils; @@ -68,15 +69,16 @@ AWTAutoShutdown.notifyToolkitThreadBusy(); ThreadGroup rootTG = AccessController.doPrivileged( - new PrivilegedAction<ThreadGroup>() { - public ThreadGroup run() { - return ThreadGroupUtils.getRootThreadGroup(); - } - } - ); + new PrivilegedAction<ThreadGroup>() { + @Override + public ThreadGroup run() { + return ThreadGroupUtils.getRootThreadGroup(); + } + }); Runtime.getRuntime().addShutdownHook( new Thread(rootTG, new Runnable() { + @Override public void run() { shutdown(); waitForRunState(STATE_CLEANUP);
--- a/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CInputMethod.java Wed Apr 16 19:41:14 2014 +0100 @@ -620,8 +620,7 @@ retString[0] = new String(selectedText); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(retString) { return retString[0]; } } @@ -669,8 +668,7 @@ }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(returnValue) { return returnValue; } } @@ -695,8 +693,7 @@ returnValue[0] = fIMContext.getInsertPositionOffset(); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } returnValue[1] = fCurrentTextLength; synchronized(returnValue) { return returnValue; } @@ -743,8 +740,7 @@ } }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } synchronized(rect) { return rect; } } @@ -764,8 +760,7 @@ insertPositionOffset[0] = fIMContext.getInsertPositionOffset(); }} }, fAwtFocussedComponent); - } catch (InterruptedException ie) { ie.printStackTrace(); } - catch (InvocationTargetException ite) { ite.printStackTrace(); } + } catch (InvocationTargetException ite) { ite.printStackTrace(); } // This bit of gymnastics ensures that the returned location is within the composed text. // If it falls outside that region, the input method will commit the text, which is inconsistent with native
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed Apr 16 19:41:14 2014 +0100 @@ -918,7 +918,7 @@ //Posting an empty to flush the EventQueue without blocking the main thread } }, target); - } catch (InterruptedException | InvocationTargetException e) { + } catch (InvocationTargetException e) { e.printStackTrace(); } }
--- a/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java Wed Apr 16 19:41:14 2014 +0100 @@ -97,6 +97,6 @@ setVisible(true); } }, this); - } catch (InterruptedException | InvocationTargetException ex) {} + } catch (InvocationTargetException ex) {} } }
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Wed Apr 16 19:41:14 2014 +0100 @@ -525,22 +525,21 @@ // Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop // The InvocationEvent will call LWCToolkit.stopAWTRunLoop() when finished, which will stop our manual runloop // Does not dispatch native events while in the loop - public static void invokeAndWait(Runnable event, Component component) throws InterruptedException, InvocationTargetException { + public static void invokeAndWait(Runnable runnable, Component component) throws InvocationTargetException { final long mediator = createAWTRunLoopMediator(); - InvocationEvent invocationEvent = - new InvocationEvent(component != null ? component : Toolkit.getDefaultToolkit(), event) { - @Override - public void dispatch() { - try { - super.dispatch(); - } finally { - if (mediator != 0) { - stopAWTRunLoop(mediator); + InvocationEvent invocationEvent = AWTAccessor.getInvocationEventAccessor() + .createEvent(component != null ? component : Toolkit.getDefaultToolkit(), + runnable, + new Runnable() { + @Override + public void run() { + if (mediator != 0) { + stopAWTRunLoop(mediator); + } } - } - } - }; + }, + true); if (component != null) { AppContext appContext = SunToolkit.targetToAppContext(component);
--- a/src/macosx/native/sun/awt/awt.m Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/native/sun/awt/awt.m Wed Apr 16 19:41:14 2014 +0100 @@ -437,6 +437,7 @@ jmethodID sjm_getRootThreadGroup = (*env)->GetStaticMethodID(env, jc_ThreadGroupUtils, "getRootThreadGroup", "()Ljava/lang/ThreadGroup;"); jobject rootThreadGroup = (*env)->CallStaticObjectMethod(env, jc_ThreadGroupUtils, sjm_getRootThreadGroup); [ThreadUtilities setAppkitThreadGroup:(*env)->NewGlobalRef(env, rootThreadGroup)]; + // The current thread was attached in getJNIEnvUncached. // Detach it back. It will be reattached later if needed with a proper TG [ThreadUtilities detachCurrentThread];
--- a/src/macosx/native/sun/font/AWTStrike.h Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/native/sun/font/AWTStrike.h Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -31,11 +31,12 @@ @interface AWTStrike : NSObject { @public AWTFont * fAWTFont; - CGFloat fSize; + CGFloat fSize; JRSFontRenderingStyle fStyle; - jint fAAStyle; + jint fAAStyle; CGAffineTransform fTx; + CGAffineTransform fDevTx; CGAffineTransform fAltTx; // alternate strike tx used for Sun2D CGAffineTransform fFontTx; }
--- a/src/macosx/native/sun/font/AWTStrike.m Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/native/sun/font/AWTStrike.m Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,7 @@ invDevTx.b *= -1; invDevTx.c *= -1; fFontTx = CGAffineTransformConcat(CGAffineTransformConcat(tx, invDevTx), sInverseTX); + fDevTx = CGAffineTransformInvert(invDevTx); // the "font size" is the square root of the determinant of the matrix fSize = sqrt(abs(fFontTx.a * fFontTx.d - fFontTx.b * fFontTx.c)); @@ -143,7 +144,8 @@ { CGSize advance; JNF_COCOA_ENTER(env); - AWTFont *awtFont = ((AWTStrike *)jlong_to_ptr(awtStrikePtr))->fAWTFont; + AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr); + AWTFont *awtFont = awtStrike->fAWTFont; // negative glyph codes are really unicodes, which were placed there by the mapper // to indicate we should use CoreText to substitute the character @@ -151,6 +153,10 @@ const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); CFRelease(fallback); + advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx); + if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) { + advance.width = round(advance.width); + } JNF_COCOA_EXIT(env); return advance.width;
--- a/src/macosx/native/sun/font/CGGlyphImages.m Tue Apr 15 23:54:34 2014 +0100 +++ b/src/macosx/native/sun/font/CGGlyphImages.m Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -455,6 +455,7 @@ #define CGGI_GLYPH_BBOX_PADDING 2.0f static inline GlyphInfo * CGGI_CreateNewGlyphInfoFrom(CGSize advance, CGRect bbox, + const AWTStrike *strike, const CGGI_RenderingMode *mode) { size_t pixelSize = mode->glyphDescriptor->pixelSize; @@ -477,6 +478,12 @@ width = 1; height = 1; } + advance = CGSizeApplyAffineTransform(advance, strike->fFontTx); + if (!JRSFontStyleUsesFractionalMetrics(strike->fStyle)) { + advance.width = round(advance.width); + advance.height = round(advance.height); + } + advance = CGSizeApplyAffineTransform(advance, strike->fDevTx); #ifdef USE_IMAGE_ALIGNED_MEMORY // create separate memory @@ -564,10 +571,10 @@ JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, style, &glyph, 1, &bbox); CGSize advance; - JRSFontGetAdvancesForGlyphsAndStyle(fallback, &tx, strike->fStyle, &glyph, 1, &advance); + CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); // create the Sun2D GlyphInfo we are going to strike into - GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, mode); + GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); // fix the context size, just in case the substituted character is unexpectedly large CGGI_SizeCanvas(canvas, info->width, info->height, mode->cgFontMode); @@ -715,7 +722,7 @@ JRSFontRenderingStyle bboxCGMode = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); JRSFontGetBoundingBoxesForGlyphsAndStyle((CTFontRef)font->fFont, &tx, bboxCGMode, glyphs, len, bboxes); - JRSFontGetAdvancesForGlyphsAndStyle((CTFontRef)font->fFont, &tx, strike->fStyle, glyphs, len, advances); + CTFontGetAdvancesForGlyphs((CTFontRef)font->fFont, kCTFontDefaultOrientation, glyphs, advances, len); size_t maxWidth = 1; size_t maxHeight = 1; @@ -732,7 +739,7 @@ CGSize advance = advances[i]; CGRect bbox = bboxes[i]; - GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, mode); + GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); if (maxWidth < glyphInfo->width) maxWidth = glyphInfo->width; if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height;
--- a/src/share/classes/com/sun/naming/internal/ResourceManager.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/com/sun/naming/internal/ResourceManager.java Wed Apr 16 19:41:14 2014 +0100 @@ -69,6 +69,14 @@ private static final String JRELIB_PROPERTY_FILE_NAME = "jndi.properties"; /* + * Internal environment property, that when set to "true", disables + * application resource files lookup to prevent recursion issues + * when validating signed JARs. + */ + private static final String DISABLE_APP_RESOURCE_FILES = + "com.sun.naming.disable.app.resource.files"; + + /* * The standard JNDI properties that specify colon-separated lists. */ private static final String[] listProperties = { @@ -218,6 +226,13 @@ } } + // Return without merging if application resource files lookup + // is disabled. + String disableAppRes = (String)env.get(DISABLE_APP_RESOURCE_FILES); + if (disableAppRes != null && disableAppRes.equalsIgnoreCase("true")) { + return env; + } + // Merge the above with the values read from all application // resource files. Colon-separated lists are concatenated. mergeTables(env, getApplicationResources());
--- a/src/share/classes/java/awt/EventQueue.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/java/awt/EventQueue.java Wed Apr 16 19:41:14 2014 +0100 @@ -1139,6 +1139,10 @@ if (entry.event instanceof SentEvent) { ((SentEvent)entry.event).dispose(); } + if (entry.event instanceof InvocationEvent) { + AWTAccessor.getInvocationEventAccessor() + .dispose((InvocationEvent)entry.event); + } if (prev == null) { queues[i].head = entry.next; } else {
--- a/src/share/classes/java/awt/event/InvocationEvent.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/java/awt/event/InvocationEvent.java Wed Apr 16 19:41:14 2014 +0100 @@ -25,6 +25,8 @@ package java.awt.event; +import sun.awt.AWTAccessor; + import java.awt.ActiveEvent; import java.awt.AWTEvent; @@ -56,6 +58,20 @@ */ public class InvocationEvent extends AWTEvent implements ActiveEvent { + static { + AWTAccessor.setInvocationEventAccessor(new AWTAccessor.InvocationEventAccessor() { + @Override + public void dispose(InvocationEvent invocationEvent) { + invocationEvent.finishedDispatching(false); + } + @Override + public InvocationEvent createEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables) { + return new InvocationEvent(source, runnable, listener, catchThrowables); + } + }); + } + /** * Marks the first integer id for the range of invocation event ids. */ @@ -85,6 +101,14 @@ protected Object notifier; /** + * The (potentially null) Runnable whose run() method will be called + * immediately after the event was dispatched or disposed. + * + * @see #isDispatched + */ + private final Runnable listener; + + /** * Indicates whether the <code>run()</code> method of the <code>runnable</code> * was executed or not. * @@ -147,7 +171,7 @@ * @see #InvocationEvent(Object, Runnable, Object, boolean) */ public InvocationEvent(Object source, Runnable runnable) { - this(source, runnable, null, false); + this(source, INVOCATION_DEFAULT, runnable, null, null, false); } /** @@ -185,7 +209,39 @@ */ public InvocationEvent(Object source, Runnable runnable, Object notifier, boolean catchThrowables) { - this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables); + this(source, INVOCATION_DEFAULT, runnable, notifier, null, catchThrowables); + } + + /** + * Constructs an <code>InvocationEvent</code> with the specified + * source which will execute the runnable's <code>run</code> + * method when dispatched. If listener is non-<code>null</code>, + * <code>listener.run()</code> will be called immediately after + * <code>run</code> has returned, thrown an exception or the event + * was disposed. + * <p>This method throws an <code>IllegalArgumentException</code> + * if <code>source</code> is <code>null</code>. + * + * @param source The <code>Object</code> that originated + * the event + * @param runnable The <code>Runnable</code> whose + * <code>run</code> method will be + * executed + * @param listener The <code>Runnable</code>Runnable whose + * <code>run()</code> method will be called + * after the {@code InvocationEvent} + * was dispatched or disposed + * @param catchThrowables Specifies whether <code>dispatch</code> + * should catch Throwable when executing + * the <code>Runnable</code>'s <code>run</code> + * method, or should instead propagate those + * Throwables to the EventDispatchThread's + * dispatch loop + * @throws IllegalArgumentException if <code>source</code> is null + */ + private InvocationEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables) { + this(source, INVOCATION_DEFAULT, runnable, null, listener, catchThrowables); } /** @@ -221,13 +277,18 @@ */ protected InvocationEvent(Object source, int id, Runnable runnable, Object notifier, boolean catchThrowables) { + this(source, id, runnable, notifier, null, catchThrowables); + } + + private InvocationEvent(Object source, int id, Runnable runnable, + Object notifier, Runnable listener, boolean catchThrowables) { super(source, id); this.runnable = runnable; this.notifier = notifier; + this.listener = listener; this.catchExceptions = catchThrowables; this.when = System.currentTimeMillis(); } - /** * Executes the Runnable's <code>run()</code> method and notifies the * notifier (if any) when <code>run()</code> has returned or thrown an exception. @@ -251,13 +312,7 @@ runnable.run(); } } finally { - dispatched = true; - - if (notifier != null) { - synchronized (notifier) { - notifier.notifyAll(); - } - } + finishedDispatching(true); } } @@ -331,6 +386,25 @@ } /** + * Called when the event was dispatched or disposed + * @param dispatched true if the event was dispatched + * false if the event was disposed + */ + private void finishedDispatching(boolean dispatched) { + this.dispatched = dispatched; + + if (notifier != null) { + synchronized (notifier) { + notifier.notifyAll(); + } + } + + if (listener != null) { + listener.run(); + } + } + + /** * Returns a parameter string identifying this event. * This method is useful for event-logging and for debugging. *
--- a/src/share/classes/java/lang/Thread.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/java/lang/Thread.java Wed Apr 16 19:41:14 2014 +0100 @@ -366,6 +366,8 @@ throw new NullPointerException("name cannot be null"); } + this.name = name.toCharArray(); + Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); if (g == null) { @@ -402,7 +404,6 @@ this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); - this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else
--- a/src/share/classes/java/util/logging/LogManager.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/java/util/logging/LogManager.java Wed Apr 16 19:41:14 2014 +0100 @@ -363,6 +363,9 @@ changes.removePropertyChangeListener(l); } + // LoggerContext maps from AppContext + private static WeakHashMap<Object, LoggerContext> contextsMap = null; + // Returns the LoggerContext for the user code (i.e. application or AppContext). // Loggers are isolated from each AppContext. private LoggerContext getUserContext() { @@ -371,33 +374,28 @@ SecurityManager sm = System.getSecurityManager(); JavaAWTAccess javaAwtAccess = SharedSecrets.getJavaAWTAccess(); if (sm != null && javaAwtAccess != null) { + // for each applet, it has its own LoggerContext isolated from others synchronized (javaAwtAccess) { - // AppContext.getAppContext() returns the system AppContext if called - // from a system thread but Logger.getLogger might be called from - // an applet code. Instead, find the AppContext of the applet code - // from the execution stack. - Object ecx = javaAwtAccess.getExecutionContext(); - if (ecx == null) { - // fall back to thread group seach of AppContext - ecx = javaAwtAccess.getContext(); - } + // find the AppContext of the applet code + // will be null if we are in the main app context. + final Object ecx = javaAwtAccess.getAppletContext(); if (ecx != null) { - context = (LoggerContext)javaAwtAccess.get(ecx, LoggerContext.class); + if (contextsMap == null) { + contextsMap = new WeakHashMap<>(); + } + context = contextsMap.get(ecx); if (context == null) { - if (javaAwtAccess.isMainAppContext()) { - context = userContext; - } else { - // Create a new LoggerContext for the applet. - // The new logger context has its requiresDefaultLoggers - // flag set to true - so that these loggers will be - // lazily added when the context is firt accessed. - context = new LoggerContext(true); - } - javaAwtAccess.put(ecx, LoggerContext.class, context); + // Create a new LoggerContext for the applet. + // The new logger context has its requiresDefaultLoggers + // flag set to true - so that these loggers will be + // lazily added when the context is firt accessed. + context = new LoggerContext(true); + contextsMap.put(ecx, context); } } } } + // for standalone app, return userContext return context != null ? context : userContext; }
--- a/src/share/classes/javax/security/auth/Subject.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/javax/security/auth/Subject.java Wed Apr 16 19:41:14 2014 +0100 @@ -941,14 +941,30 @@ /** * Reads this object from a stream (i.e., deserializes it) */ + @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField gf = s.readFields(); + + readOnly = gf.get("readOnly", false); + + Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null); // Rewrap the principals into a SecureSet - principals = Collections.synchronizedSet(new SecureSet<Principal> - (this, PRINCIPAL_SET, principals)); + if (inputPrincs == null) { + throw new NullPointerException + (ResourcesMgr.getString("invalid.null.input.s.")); + } + try { + principals = Collections.synchronizedSet(new SecureSet<Principal> + (this, PRINCIPAL_SET, inputPrincs)); + } catch (NullPointerException npe) { + // Sometimes people deserialize the principals set only. + // Subject is not accessible, so just don't fail. + principals = Collections.synchronizedSet + (new SecureSet<Principal>(this, PRINCIPAL_SET)); + } // The Credential <code>Set</code> is not serialized, but we do not // want the default deserialization routine to set it to null.
--- a/src/share/classes/sun/awt/AWTAccessor.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/awt/AWTAccessor.java Wed Apr 16 19:41:14 2014 +0100 @@ -29,6 +29,7 @@ import java.awt.KeyboardFocusManager; import java.awt.DefaultKeyboardFocusManager; import java.awt.event.InputEvent; +import java.awt.event.InvocationEvent; import java.awt.event.KeyEvent; import java.awt.geom.Point2D; @@ -690,6 +691,25 @@ } /* + * An accessor object for the InvocationEvent class + */ + public interface InvocationEventAccessor { + /** + * Disposes the InvocationEvent + */ + void dispose(InvocationEvent event); + + /** + * Creates an InvocationEvent with a completion listener - + * a Runnable whose run() method will be called immediately after + * the event is dispatched or disposed + */ + InvocationEvent createEvent(Object source, Runnable runnable, Runnable listener, + boolean catchThrowables); + } + + + /* * Accessor instances are initialized in the static initializers of * corresponding AWT classes by using setters defined below. */ @@ -716,6 +736,7 @@ private static TrayIconAccessor trayIconAccessor; private static DefaultKeyboardFocusManagerAccessor defaultKeyboardFocusManagerAccessor; private static SequencedEventAccessor sequencedEventAccessor; + private static InvocationEventAccessor invocationEventAccessor; /* * Set an accessor object for the java.awt.Component class. @@ -1110,4 +1131,18 @@ // (so not a single instance of the event has been created). return sequencedEventAccessor; } + + /* + * Get the accessor object for the java.awt.event.InvocationEvent class. + */ + public static void setInvocationEventAccessor(InvocationEventAccessor invocationEventAccessor) { + AWTAccessor.invocationEventAccessor = invocationEventAccessor; + } + + /* + * Set the accessor object for the java.awt.event.InvocationEvent class. + */ + public static InvocationEventAccessor getInvocationEventAccessor() { + return invocationEventAccessor; + } }
--- a/src/share/classes/sun/awt/AWTAutoShutdown.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/awt/AWTAutoShutdown.java Wed Apr 16 19:41:14 2014 +0100 @@ -32,8 +32,8 @@ import java.util.IdentityHashMap; import java.util.Map; +import sun.misc.ThreadGroupUtils; import sun.util.logging.PlatformLogger; -import sun.misc.ThreadGroupUtils; /** * This class is to let AWT shutdown automatically when a user is done @@ -216,10 +216,11 @@ synchronized (mainLock) { if (!isReadyToShutdown() && blockerThread == null) { AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { - activateBlockerThread(); - return null; - } + @Override + public Void run() { + activateBlockerThread(); + return null; + } }); } else { mainLock.notifyAll(); @@ -334,6 +335,8 @@ /** * Creates and starts a new blocker thread. Doesn't return until * the new blocker thread starts. + * + * Must be called with {@link sun.security.util.SecurityConstants#MODIFY_THREADGROUP_PERMISSION} */ private void activateBlockerThread() { Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), this, "AWT-Shutdown");
--- a/src/share/classes/sun/awt/AppContext.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/awt/AppContext.java Wed Apr 16 19:41:14 2014 +0100 @@ -837,21 +837,68 @@ public boolean isMainAppContext() { return (numAppContexts.get() == 1 && mainAppContext != null); } - public Object getContext() { - return getAppContext(); - } - public Object getExecutionContext() { - return getExecutionAppContext(); + + private boolean hasRootThreadGroup(final AppContext ecx) { + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + @Override + public Boolean run() { + return ecx.threadGroup.getParent() == null; + } + }); } - public Object get(Object context, Object key) { - return ((AppContext)context).get(key); + + /** + * Returns the AppContext used for applet logging isolation, or null if + * the default global context can be used. + * If there's no applet, or if the caller is a stand alone application, + * or running in the main app context, returns null. + * Otherwise, returns the AppContext of the calling applet. + * @return null if the global default context can be used, + * an AppContext otherwise. + **/ + public Object getAppletContext() { + // There's no AppContext: return null. + // No need to call getAppContext() if numAppContext == 0: + // it means that no AppContext has been created yet, and + // we don't want to trigger the creation of a main app + // context since we don't need it. + if (numAppContexts.get() == 0) return null; + + // Get the context from the security manager + AppContext ecx = getExecutionAppContext(); + + // Not sure we really need to re-check numAppContexts here. + // If all applets have gone away then we could have a + // numAppContexts coming back to 0. So we recheck + // it here because we don't want to trigger the + // creation of a main AppContext in that case. + // This is probably not 100% MT-safe but should reduce + // the window of opportunity in which that issue could + // happen. + if (numAppContexts.get() > 0) { + // Defaults to thread group caching. + // This is probably not required as we only really need + // isolation in a deployed applet environment, in which + // case ecx will not be null when we reach here + // However it helps emulate the deployed environment, + // in tests for instance. + ecx = ecx != null ? ecx : getAppContext(); + } + + // getAppletContext() may be called when initializing the main + // app context - in which case mainAppContext will still be + // null. To work around this issue we simply use + // AppContext.threadGroup.getParent() == null instead, since + // mainAppContext is the only AppContext which should have + // the root TG as its thread group. + // See: JDK-8023258 + final boolean isMainAppContext = ecx == null + || mainAppContext == ecx + || mainAppContext == null && hasRootThreadGroup(ecx); + + return isMainAppContext ? null : ecx; } - public void put(Object context, Object key, Object value) { - ((AppContext)context).put(key, value); - } - public void remove(Object context, Object key) { - ((AppContext)context).remove(key); - } + }); } }
--- a/src/share/classes/sun/font/CreatedFontTracker.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/font/CreatedFontTracker.java Wed Apr 16 19:41:14 2014 +0100 @@ -116,22 +116,24 @@ if (t == null) { // Add a shutdown hook to remove the temp file. AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { + @Override + public Void run() { /* The thread must be a member of a thread group * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - t = new Thread(rootTG, new Runnable() { - public void run() { - runHooks(); - } - }); - t.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(t); - return null; - } - }); + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + t = new Thread(rootTG, new Runnable() { + @Override + public void run() { + runHooks(); + } + }); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); + return null; + } + }); } }
--- a/src/share/classes/sun/font/SunFontManager.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/font/SunFontManager.java Wed Apr 16 19:41:14 2014 +0100 @@ -2523,18 +2523,19 @@ } }; AccessController.doPrivileged(new PrivilegedAction<Void>() { - public Void run() { + @Override + public Void run() { /* The thread must be a member of a thread group * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - fileCloser = new Thread(rootTG, fileCloserRunnable); - fileCloser.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(fileCloser); - return null; - } - }); + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + fileCloser = new Thread(rootTG, fileCloserRunnable); + fileCloser.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(fileCloser); + return null; + } + }); } } }
--- a/src/share/classes/sun/java2d/Disposer.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/java2d/Disposer.java Wed Apr 16 19:41:14 2014 +0100 @@ -75,22 +75,22 @@ } } disposerInstance = new Disposer(); - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { /* The thread must be a member of a thread group * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread t = new Thread(rootTG, disposerInstance, "Java2D Disposer"); - t.setContextClassLoader(null); - t.setDaemon(true); - t.setPriority(Thread.MAX_PRIORITY); - t.start(); - return null; + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread t = new Thread(rootTG, disposerInstance, "Java2D Disposer"); + t.setContextClassLoader(null); + t.setDaemon(true); + t.setPriority(Thread.MAX_PRIORITY); + t.start(); + return null; + } } - } ); }
--- a/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java Wed Apr 16 19:41:14 2014 +0100 @@ -49,8 +49,9 @@ * which will not get GCed before VM exit. */ flusher = AccessController.doPrivileged(new PrivilegedAction<QueueFlusher>() { + @Override public QueueFlusher run() { - return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup()); + return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup()); } }); }
--- a/src/share/classes/sun/misc/JavaAWTAccess.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/misc/JavaAWTAccess.java Wed Apr 16 19:41:14 2014 +0100 @@ -26,14 +26,16 @@ package sun.misc; public interface JavaAWTAccess { - public Object getContext(); - public Object getExecutionContext(); - public Object get(Object context, Object key); - public void put(Object context, Object key, Object value); - public void remove(Object context, Object key); + // Returns the AppContext used for applet logging isolation, or null if + // no isolation is required. + // If there's no applet, or if the caller is a stand alone application, + // or running in the main app context, returns null. + // Otherwise, returns the AppContext of the calling applet. + public Object getAppletContext(); - // convenience methods whose context is the object returned by getContext() + // convenience methods to cache objects in the current thread group's + // AppContext public Object get(Object key); public void put(Object key, Object value); public void remove(Object key);
--- a/src/share/classes/sun/misc/SharedSecrets.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/misc/SharedSecrets.java Wed Apr 16 19:41:14 2014 +0100 @@ -198,9 +198,6 @@ public static JavaAWTAccess getJavaAWTAccess() { // this may return null in which case calling code needs to // provision for. - if (javaAWTAccess == null || javaAWTAccess.getContext() == null) { - return null; - } return javaAWTAccess; } }
--- a/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java Wed Apr 16 19:41:14 2014 +0100 @@ -50,6 +50,7 @@ import sun.security.util.Cache; import sun.security.util.Debug; import sun.security.x509.X500Name; +import sun.security.action.GetBooleanAction; import sun.security.action.GetPropertyAction; /** @@ -135,6 +136,14 @@ private final static String PROP_LIFETIME = "sun.security.certpath.ldap.cache.lifetime"; + /* + * Internal system property, that when set to "true", disables the + * JNDI application resource files lookup to prevent recursion issues + * when validating signed JARs with LDAP URLs in certificates. + */ + private final static String PROP_DISABLE_APP_RESOURCE_FILES = + "sun.security.certpath.ldap.disable.app.resource.files"; + static { String s = AccessController.doPrivileged( new GetPropertyAction(PROP_LIFETIME)); @@ -236,6 +245,17 @@ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); + + // If property is set to true, disable application resource file lookup. + boolean disableAppResourceFiles = AccessController.doPrivileged( + new GetBooleanAction(PROP_DISABLE_APP_RESOURCE_FILES)); + if (disableAppResourceFiles) { + if (debug != null) { + debug.println("LDAPCertStore disabling app resource files"); + } + env.put("com.sun.naming.disable.app.resource.files", "true"); + } + try { ctx = new InitialDirContext(env); /*
--- a/src/share/classes/sun/util/resources/TimeZoneNames.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Alma-Ata Time", "ALMT", "Alma-Ata Summer Time", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Anadyr Time", "ANAT", "Anadyr Summer Time", "ANAST"}}, {"Asia/Aqtau", new String[] {"Aqtau Time", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_de.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_de.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Alma Ata Zeit", "ALMT", "Alma-Ata Sommerzeit", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Anadyr Zeit", "ANAT", "Anadyr Sommerzeit", "ANAST"}}, {"Asia/Aqtau", new String[] {"Aqtau Zeit", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_es.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_es.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Hora de Alma-Ata", "ALMT", "Hora de verano de Alma-Ata", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Hora de Anadyr", "ANAT", "Hora de verano de Anadyr", "ANAST"}}, {"Asia/Aqtau", new String[] {"Hora de Aqtau", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Heure d'Alma-Ata", "ALMT", "Heure d'\u00e9t\u00e9 d'Alma-Ata", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Heure d'Anadyr", "ANAT", "Heure d'\u00e9t\u00e9 d'Anadyr", "ANAST"}}, {"Asia/Aqtau", new String[] {"Heure d'Aqtau", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_it.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_it.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Ora di Alma-Ata", "ALMT", "Ora estiva di Alma-Ata", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Ora di Anadyr", "ANAT", "Ora estiva di Anadyr", "ANAST"}}, {"Asia/Aqtau", new String[] {"Ora di Aqtau", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"\u30a2\u30eb\u30de\u30a2\u30bf\u6642\u9593", "ALMT", "\u30a2\u30eb\u30de\u30a2\u30bf\u590f\u6642\u9593", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"\u30a2\u30ca\u30c9\u30a5\u30a4\u30ea\u6642\u9593", "ANAT", "\u30a2\u30ca\u30c9\u30a5\u30a4\u30ea\u590f\u6642\u9593", "ANAST"}}, {"Asia/Aqtau", new String[] {"\u30a2\u30af\u30bf\u30a6\u6642\u9593", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"\uc54c\ub9c8\uc544\ud0c0 \uc2dc\uac04", "ALMT", "\uc54c\ub9c8\uc544\ud0c0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"\uc544\ub098\ub514\ub974 \uc2dc\uac04", "ANAT", "\uc544\ub098\ub514\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ANAST"}}, {"Asia/Aqtau", new String[] {"\uc545\ud0c0\uc6b0 \uc2dc\uac04", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Fuso hor\u00e1rio de Alma-Ata", "ALMT", "Fuso hor\u00e1rio de ver\u00e3o de Alma-Ata", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Fuso hor\u00e1rio de Anadyr", "ANAT", "Fuso hor\u00e1rio de ver\u00e3o de Anadyr", "ANAST"}}, {"Asia/Aqtau", new String[] {"Fuso hor\u00e1rio de Aqtau", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Alma-Ata, normaltid", "ALMT", "Alma-Ata, sommartid", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"Anadyr, normaltid", "ANAT", "Anadyr, sommartid", "ANAST"}}, {"Asia/Aqtau", new String[] {"Aqtau, normaltid", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Alma-Ata \u65f6\u95f4", "ALMT", "Alma-Ata \u590f\u4ee4\u65f6", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"\u963f\u90a3\u5e95\u6cb3\u65f6\u95f4", "ANAT", "\u963f\u90a3\u5e95\u6cb3\u590f\u4ee4\u65f6", "ANAST"}}, {"Asia/Aqtau", new String[] {"Aqtau \u65f6\u95f4", "AQTT",
--- a/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -483,7 +483,7 @@ {"Asia/Aden", ARAST}, {"Asia/Almaty", new String[] {"Alma-Ata \u6642\u9593", "ALMT", "Alma-Ata \u590f\u4ee4\u6642\u9593", "ALMST"}}, - {"Asia/Amman", ARAST}, + {"Asia/Amman", EET}, {"Asia/Anadyr", new String[] {"\u963f\u90a3\u5e95\u6cb3\u6642\u9593", "ANAT", "\u963f\u90a3\u5e95\u6cb3\u590f\u4ee4\u6642\u9593", "ANAST"}}, {"Asia/Aqtau", new String[] {"Aqtau \u6642\u9593", "AQTT",
--- a/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Tue Apr 15 23:54:34 2014 +0100 +++ b/src/share/native/sun/font/layout/LigatureSubstProc2.cpp Wed Apr 16 19:41:14 2014 +0100 @@ -95,7 +95,7 @@ if (actionOffset != 0) { LEReferenceTo<LigatureActionEntry> ap(stHeader, success, ligActionOffset); // byte offset - ap.addObject(ligActionIndex - 1, success); // index offset ( one before the actual start, because we will pre-increment) + ap.addObject(ligActionIndex, success); LEReferenceToArrayOf<TTGlyphID> ligatureTable(stHeader, success, ligatureOffset, LE_UNBOUNDED_ARRAY); LigatureActionEntry action; le_int32 offset, i = 0; @@ -111,7 +111,6 @@ do { le_uint32 componentGlyph = componentStack[m--]; // pop off - ap.addObject(success); action = SWAPL(*ap.getAlias()); if (m < 0) { @@ -145,7 +144,8 @@ LE_DEBUG_BAD_FONT("m<0") } #endif - } while (!(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items + ap.addObject(success); + } while (LE_SUCCESS(success) && !(action & lafLast) && (m>=0) ); // stop if last bit is set, or if run out of items while (mm >= 0) { if (++m >= nComponents) {
--- a/src/solaris/classes/java/lang/UNIXProcess.java.bsd Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.bsd Wed Apr 16 19:41:14 2014 +0100 @@ -63,11 +63,59 @@ private /* final */ InputStream stdout; private /* final */ InputStream stderr; + private static enum LaunchMechanism { + FORK(1), + POSIX_SPAWN(2); + + private int value; + LaunchMechanism(int x) {value = x;} + }; + + /* On BSD, the default is to spawn */ + private static final LaunchMechanism launchMechanism; + private static byte[] helperpath; + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length-1] = (byte)0; + return result; + } + + static { + launchMechanism = AccessController.doPrivileged( + new PrivilegedAction<LaunchMechanism>() + { + public LaunchMechanism run() { + String javahome = System.getProperty("java.home"); + + helperpath = toCString(javahome + "/lib/jspawnhelper"); + String s = System.getProperty( + "jdk.lang.Process.launchMechanism", "posix_spawn"); + + try { + return LaunchMechanism.valueOf(s.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new Error(s + " is not a supported " + + "process launch mechanism on this platform."); + } + } + }); + } + /* this is for the reaping thread */ private native int waitForProcessExit(int pid); /** - * Create a process using fork(2) and exec(2). + * Create a process. Depending on the mode flag, this is done by + * one of the following mechanisms. + * - fork(2) and exec(2) + * - posix_spawn(2) * * @param fds an array of three file descriptors. * Indexes 0, 1, and 2 correspond to standard input, @@ -80,7 +128,8 @@ * output. * @return the pid of the subprocess */ - private native int forkAndExec(byte[] prog, + private native int forkAndExec(int mode, byte[] helperpath, + byte[] prog, byte[] argBlock, int argc, byte[] envBlock, int envc, byte[] dir, @@ -132,7 +181,9 @@ final boolean redirectErrorStream) throws IOException { - pid = forkAndExec(prog, + pid = forkAndExec(launchMechanism.value, + helperpath, + prog, argBlock, argc, envBlock, envc, dir, @@ -236,11 +287,10 @@ try { stderr.close(); } catch (IOException ignored) {} } - /* This routine initializes JNI field offsets for the class */ - private static native void initIDs(); + private static native void init(); static { - initIDs(); + init(); } /**
--- a/src/solaris/classes/java/lang/UNIXProcess.java.linux Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.linux Wed Apr 16 19:41:14 2014 +0100 @@ -63,11 +63,61 @@ private /* final */ InputStream stdout; private /* final */ InputStream stderr; + private static enum LaunchMechanism { + FORK(1), + VFORK(3); + + private int value; + LaunchMechanism(int x) {value = x;} + }; + + /* default is VFORK on Linux */ + private static final LaunchMechanism launchMechanism; + private static byte[] helperpath; + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length-1] = (byte)0; + return result; + } + + static { + launchMechanism = AccessController.doPrivileged( + new PrivilegedAction<LaunchMechanism>() + { + public LaunchMechanism run() { + String javahome = System.getProperty("java.home"); + String osArch = System.getProperty("os.arch"); + + helperpath = toCString(javahome + "/lib/" + osArch + "/jspawnhelper"); + String s = System.getProperty( + "jdk.lang.Process.launchMechanism", "vfork"); + + try { + return LaunchMechanism.valueOf(s.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new Error(s + " is not a supported " + + "process launch mechanism on this platform."); + } + } + }); + } + /* this is for the reaping thread */ private native int waitForProcessExit(int pid); /** - * Create a process using fork(2) and exec(2). + * Create a process. Depending on the mode flag, this is done by + * one of the following mechanisms. + * - fork(2) and exec(2) + * - clone(2) and exec(2) + * - vfork(2) and exec(2) * * @param fds an array of three file descriptors. * Indexes 0, 1, and 2 correspond to standard input, @@ -80,7 +130,8 @@ * output. * @return the pid of the subprocess */ - private native int forkAndExec(byte[] prog, + private native int forkAndExec(int mode, byte[] helperpath, + byte[] prog, byte[] argBlock, int argc, byte[] envBlock, int envc, byte[] dir, @@ -132,7 +183,9 @@ final boolean redirectErrorStream) throws IOException { - pid = forkAndExec(prog, + pid = forkAndExec(launchMechanism.value, + helperpath, + prog, argBlock, argc, envBlock, envc, dir, @@ -236,11 +289,10 @@ try { stderr.close(); } catch (IOException ignored) {} } - /* This routine initializes JNI field offsets for the class */ - private static native void initIDs(); + private static native void init(); static { - initIDs(); + init(); } /**
--- a/src/solaris/classes/java/lang/UNIXProcess.java.solaris Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.solaris Wed Apr 16 19:41:14 2014 +0100 @@ -26,6 +26,8 @@ package java.lang; import java.io.*; +import java.security.AccessController; +import java.security.PrivilegedAction; /* java.lang.Process subclass in the UNIX environment. * @@ -45,11 +47,65 @@ private DeferredCloseInputStream stdout_inner_stream; private InputStream stderr_stream; + private static enum LaunchMechanism { + FORK(1), + POSIX_SPAWN(2); + + private int value; + LaunchMechanism(int x) {value = x;} + }; + + /* On Solaris, the default is to spawn */ + private static final LaunchMechanism launchMechanism; + private static byte[] helperpath; + + private static byte[] toCString(String s) { + if (s == null) + return null; + byte[] bytes = s.getBytes(); + byte[] result = new byte[bytes.length + 1]; + System.arraycopy(bytes, 0, + result, 0, + bytes.length); + result[result.length-1] = (byte)0; + return result; + } + + static { + launchMechanism = AccessController.doPrivileged( + new PrivilegedAction<LaunchMechanism>() + { + public LaunchMechanism run() { + String javahome = System.getProperty("java.home"); + String osArch = System.getProperty("os.arch"); + if (osArch.equals("x86")) { + osArch = "i386"; + } else if (osArch.equals("x86_64")) { + osArch = "amd64"; + } + + helperpath = toCString(javahome + "/lib/" + osArch + "/jspawnhelper"); + String s = System.getProperty( + "jdk.lang.Process.launchMechanism", "fork"); + + try { + return LaunchMechanism.valueOf(s.toUpperCase()); + } catch (IllegalArgumentException e) { + throw new Error(s + " is not a supported " + + "process launch mechanism on this platform."); + } + } + }); + } + /* this is for the reaping thread */ private native int waitForProcessExit(int pid); /** - * Create a process using fork(2) and exec(2). + * Create a process. Depending on the mode flag, this is done by + * one of the following mechanisms. + * - fork(2) and exec(2) + * - posix_spawn(2) * * @param std_fds array of file descriptors. Indexes 0, 1, and * 2 correspond to standard input, standard output and @@ -61,7 +117,8 @@ * if and only if it is <em>not</em> -1 on output. * @return the pid of the subprocess */ - private native int forkAndExec(byte[] prog, + private native int forkAndExec(int mode, byte[] helperpath, + byte[] prog, byte[] argBlock, int argc, byte[] envBlock, int envc, byte[] dir, @@ -76,7 +133,9 @@ final int[] std_fds, final boolean redirectErrorStream) throws IOException { - pid = forkAndExec(prog, + pid = forkAndExec(launchMechanism.value, + helperpath, + prog, argBlock, argc, envBlock, envc, dir, @@ -294,10 +353,9 @@ } - /* This routine initializes JNI field offsets for the class */ - private static native void initIDs(); + private static native void init(); static { - initIDs(); + init(); } }
--- a/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Apr 16 19:41:14 2014 +0100 @@ -48,7 +48,8 @@ import javax.swing.UIDefaults; import sun.awt.*; import sun.font.FontConfigManager; -import sun.misc.*; +import sun.misc.PerformanceLogger; +import sun.misc.ThreadGroupUtils; import sun.print.PrintJob2D; import sun.security.action.GetPropertyAction; import sun.security.action.GetBooleanAction; @@ -373,8 +374,8 @@ init(); XWM.init(); SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME); - - PrivilegedAction<Thread> action = new PrivilegedAction() { + toolkitThread = AccessController.doPrivileged(new PrivilegedAction<Thread>() { + @Override public Thread run() { Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, "AWT-XAWT"); thread.setContextClassLoader(null); @@ -382,8 +383,7 @@ thread.setDaemon(true); return thread; } - }; - toolkitThread = AccessController.doPrivileged(action); + }); toolkitThread.start(); } }
--- a/src/solaris/classes/sun/awt/X11GraphicsDevice.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/classes/sun/awt/X11GraphicsDevice.java Wed Apr 16 19:41:14 2014 +0100 @@ -41,6 +41,7 @@ import sun.java2d.opengl.GLXGraphicsConfig; import sun.java2d.xr.XRGraphicsConfig; import sun.java2d.loops.SurfaceType; +import sun.misc.ThreadGroupUtils; import sun.misc.ThreadGroupUtils; @@ -426,22 +427,24 @@ // hook will have no effect) shutdownHookRegistered = true; PrivilegedAction<Void> a = new PrivilegedAction<Void>() { + @Override public Void run() { - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); Runnable r = new Runnable() { - public void run() { - Window old = getFullScreenWindow(); - if (old != null) { - exitFullScreenExclusive(old); - setDisplayMode(origDisplayMode); - } + @Override + public void run() { + Window old = getFullScreenWindow(); + if (old != null) { + exitFullScreenExclusive(old); + setDisplayMode(origDisplayMode); } - }; - Thread t = new Thread(rootTG, r,"Display-Change-Shutdown-Thread-"+screen); - t.setContextClassLoader(null); - Runtime.getRuntime().addShutdownHook(t); - return null; - } + } + }; + Thread t = new Thread(rootTG, r, "Display-Change-Shutdown-Thread-" + screen); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); + return null; + } }; AccessController.doPrivileged(a); }
--- a/src/solaris/native/java/lang/ProcessEnvironment_md.c Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/native/java/lang/ProcessEnvironment_md.c Wed Apr 16 19:41:14 2014 +0100 @@ -31,21 +31,24 @@ #ifdef __APPLE__ #include <crt_externs.h> #define environ (*_NSGetEnviron()) +#else +/* This is one of the rare times it's more portable to declare an + * external symbol explicitly, rather than via a system header. + * The declaration is standardized as part of UNIX98, but there is + * no standard (not even de-facto) header file where the + * declaration is to be found. See: + * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html + * + * "All identifiers in this volume of IEEE Std 1003.1-2001, except + * environ, are defined in at least one of the headers" (!) + */ +extern char **environ; #endif JNIEXPORT jobjectArray JNICALL Java_java_lang_ProcessEnvironment_environ(JNIEnv *env, jclass ign) { - /* This is one of the rare times it's more portable to declare an - * external symbol explicitly, rather than via a system header. - * The declaration is standardized as part of UNIX98, but there is - * no standard (not even de-facto) header file where the - * declaration is to be found. See: - * http://www.opengroup.org/onlinepubs/007908799/xbd/envvar.html */ -#ifndef __APPLE__ - extern char ** environ; /* environ[i] looks like: VAR=VALUE\0 */ -#endif - jsize count = 0; jsize i, j; jobjectArray result;
--- a/src/solaris/native/java/lang/UNIXProcess_md.c Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/native/java/lang/UNIXProcess_md.c Wed Apr 16 19:41:14 2014 +0100 @@ -47,19 +47,15 @@ #endif #include <signal.h> #include <string.h> -#include <errno.h> -#include <dirent.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#ifdef __APPLE__ -#include <crt_externs.h> -#define environ (*_NSGetEnviron()) +#if defined(__solaris__) || defined(_ALLBSD_SOURCE) +#include <spawn.h> #endif +#include "childproc.h" + /* - * There are 3 possible strategies we might use to "fork": + * There are 4 possible strategies we might use to "fork": * * - fork(2). Very portable and reliable but subject to * failure due to overcommit (see the documentation on @@ -94,81 +90,21 @@ * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311 * but the glibc maintainers closed it as WONTFIX. * + * - posix_spawn(). While posix_spawn() is a fairly elaborate and + * complicated system call, it can't quite do everything that the old + * fork()/exec() combination can do, so the only feasible way to do + * this, is to use posix_spawn to launch a new helper executable + * "jprochelper", which in turn execs the target (after cleaning + * up file-descriptors etc.) The end result is the same as before, + * a child process linked to the parent in the same way, but it + * avoids the problem of duplicating the parent (VM) process + * address space temporarily, before launching the target command. + * * Based on the above analysis, we are currently using vfork() on - * Linux and fork() on other Unix systems, but the code to use clone() - * remains. + * Linux, posix_spawn() on Mac and fork() on Solaris, but the code to + * use clone() and fork() remains. */ -#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */ - -#ifndef START_CHILD_USE_CLONE - #ifdef __linux__ - #define START_CHILD_USE_CLONE 1 - #else - #define START_CHILD_USE_CLONE 0 - #endif -#endif - -/* By default, use vfork() on Linux. */ -#ifndef START_CHILD_USE_VFORK - #ifdef __linux__ - #define START_CHILD_USE_VFORK 1 - #else - #define START_CHILD_USE_VFORK 0 - #endif -#endif - -#if START_CHILD_USE_CLONE -#include <sched.h> -#define START_CHILD_SYSTEM_CALL "clone" -#elif START_CHILD_USE_VFORK -#define START_CHILD_SYSTEM_CALL "vfork" -#else -#define START_CHILD_SYSTEM_CALL "fork" -#endif - -#ifndef STDIN_FILENO -#define STDIN_FILENO 0 -#endif - -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 -#endif - -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif - -#ifndef SA_NOCLDSTOP -#define SA_NOCLDSTOP 0 -#endif - -#ifndef SA_RESTART -#define SA_RESTART 0 -#endif - -#define FAIL_FILENO (STDERR_FILENO + 1) - -/* TODO: Refactor. */ -#define RESTARTABLE(_cmd, _result) do { \ - do { \ - _result = _cmd; \ - } while((_result == -1) && (errno == EINTR)); \ -} while(0) - -/* This is one of the rare times it's more portable to declare an - * external symbol explicitly, rather than via a system header. - * The declaration is standardized as part of UNIX98, but there is - * no standard (not even de-facto) header file where the - * declaration is to be found. See: - * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html - * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html - * - * "All identifiers in this volume of IEEE Std 1003.1-2001, except - * environ, are defined in at least one of the headers" (!) - */ -extern char **environ; - static void setSIGCHLDHandler(JNIEnv *env) @@ -245,53 +181,35 @@ } static const char * const * -splitPath(JNIEnv *env, const char *path) +effectivePathv(JNIEnv *env) { - const char *p, *q; - char **pathv; + char *p; int i; + const char *path = effectivePath(); int count = countOccurrences(path, ':') + 1; + size_t pathvsize = sizeof(const char *) * (count+1); + size_t pathsize = strlen(path) + 1; + const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize); - pathv = NEW(char*, count+1); + if (pathv == NULL) + return NULL; + p = (char *) pathv + pathvsize; + memcpy(p, path, pathsize); + /* split PATH by replacing ':' with NULs; empty components => "." */ + for (i = 0; i < count; i++) { + char *q = p + strcspn(p, ":"); + pathv[i] = (p == q) ? "." : p; + *q = '\0'; + p = q + 1; + } pathv[count] = NULL; - for (p = path, i = 0; i < count; i++, p = q + 1) { - for (q = p; (*q != ':') && (*q != '\0'); q++) - ; - if (q == p) /* empty PATH component => "." */ - pathv[i] = "./"; - else { - int addSlash = ((*(q - 1)) != '/'); - pathv[i] = NEW(char, q - p + addSlash + 1); - memcpy(pathv[i], p, q - p); - if (addSlash) - pathv[i][q - p] = '/'; - pathv[i][q - p + addSlash] = '\0'; - } - } - return (const char * const *) pathv; + return pathv; } -/** - * Cached value of JVM's effective PATH. - * (We don't support putenv("PATH=...") in native code) - */ -static const char *parentPath; - -/** - * Split, canonicalized version of parentPath - */ -static const char * const *parentPathv; - -static jfieldID field_exitcode; - JNIEXPORT void JNICALL -Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz) +Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz) { - field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I"); - - parentPath = effectivePath(); - parentPathv = splitPath(env, parentPath); - + parentPathv = effectivePathv(env); setSIGCHLDHandler(env); } @@ -358,96 +276,6 @@ } } -static ssize_t -restartableWrite(int fd, const void *buf, size_t count) -{ - ssize_t result; - RESTARTABLE(write(fd, buf, count), result); - return result; -} - -static int -restartableDup2(int fd_from, int fd_to) -{ - int err; - RESTARTABLE(dup2(fd_from, fd_to), err); - return err; -} - -static int -restartableClose(int fd) -{ - int err; - RESTARTABLE(close(fd), err); - return err; -} - -static int -closeSafely(int fd) -{ - return (fd == -1) ? 0 : restartableClose(fd); -} - -static int -isAsciiDigit(char c) -{ - return c >= '0' && c <= '9'; -} - -#ifdef _ALLBSD_SOURCE -#define FD_DIR "/dev/fd" -#define dirent64 dirent -#define readdir64 readdir -#else -#define FD_DIR "/proc/self/fd" -#endif - -static int -closeDescriptors(void) -{ - DIR *dp; - struct dirent64 *dirp; - int from_fd = FAIL_FILENO + 1; - - /* We're trying to close all file descriptors, but opendir() might - * itself be implemented using a file descriptor, and we certainly - * don't want to close that while it's in use. We assume that if - * opendir() is implemented using a file descriptor, then it uses - * the lowest numbered file descriptor, just like open(). So we - * close a couple explicitly. */ - - restartableClose(from_fd); /* for possible use by opendir() */ - restartableClose(from_fd + 1); /* another one for good luck */ - - if ((dp = opendir(FD_DIR)) == NULL) - return 0; - - /* We use readdir64 instead of readdir to work around Solaris bug - * 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9 - */ - while ((dirp = readdir64(dp)) != NULL) { - int fd; - if (isAsciiDigit(dirp->d_name[0]) && - (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) - restartableClose(fd); - } - - closedir(dp); - - return 1; -} - -static int -moveDescriptor(int fd_from, int fd_to) -{ - if (fd_from != fd_to) { - if ((restartableDup2(fd_from, fd_to) == -1) || - (restartableClose(fd_from) == -1)) - return -1; - } - return 0; -} - static const char * getBytes(JNIEnv *env, jbyteArray arr) { @@ -463,19 +291,6 @@ } static void -initVectorFromBlock(const char**vector, const char* block, int count) -{ - int i; - const char *p; - for (i = 0, p = block; i < count; i++) { - /* Invariant: p always points to the start of a C string. */ - vector[i] = p; - while (*(p++)); - } - vector[count] = NULL; -} - -static void throwIOException(JNIEnv *env, int errnum, const char *defaultDetail) { static const char * const format = "error=%d, %s"; @@ -490,6 +305,9 @@ } /* ASCII Decimal representation uses 2.4 times as many bits as binary. */ errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum)); + if (errmsg == NULL) + return; + sprintf(errmsg, format, errnum, detail); s = JNU_NewStringPlatform(env, errmsg); if (s != NULL) { @@ -515,180 +333,6 @@ } #endif /* DEBUG_PROCESS */ -/** - * Exec FILE as a traditional Bourne shell script (i.e. one without #!). - * If we could do it over again, we would probably not support such an ancient - * misfeature, but compatibility wins over sanity. The original support for - * this was imported accidentally from execvp(). - */ -static void -execve_as_traditional_shell_script(const char *file, - const char *argv[], - const char *const envp[]) -{ - /* Use the extra word of space provided for us in argv by caller. */ - const char *argv0 = argv[0]; - const char *const *end = argv; - while (*end != NULL) - ++end; - memmove(argv+2, argv+1, (end-argv) * sizeof (*end)); - argv[0] = "/bin/sh"; - argv[1] = file; - execve(argv[0], (char **) argv, (char **) envp); - /* Can't even exec /bin/sh? Big trouble, but let's soldier on... */ - memmove(argv+1, argv+2, (end-argv) * sizeof (*end)); - argv[0] = argv0; -} - -/** - * Like execve(2), except that in case of ENOEXEC, FILE is assumed to - * be a shell script and the system default shell is invoked to run it. - */ -static void -execve_with_shell_fallback(const char *file, - const char *argv[], - const char *const envp[]) -{ -#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK - /* shared address space; be very careful. */ - execve(file, (char **) argv, (char **) envp); - if (errno == ENOEXEC) - execve_as_traditional_shell_script(file, argv, envp); -#else - /* unshared address space; we can mutate environ. */ - environ = (char **) envp; - execvp(file, (char **) argv); -#endif -} - -/** - * 'execvpe' should have been included in the Unix standards, - * and is a GNU extension in glibc 2.10. - * - * JDK_execvpe is identical to execvp, except that the child environment is - * specified via the 3rd argument instead of being inherited from environ. - */ -static void -JDK_execvpe(const char *file, - const char *argv[], - const char *const envp[]) -{ - if (envp == NULL || (char **) envp == environ) { - execvp(file, (char **) argv); - return; - } - - if (*file == '\0') { - errno = ENOENT; - return; - } - - if (strchr(file, '/') != NULL) { - execve_with_shell_fallback(file, argv, envp); - } else { - /* We must search PATH (parent's, not child's) */ - char expanded_file[PATH_MAX]; - int filelen = strlen(file); - int sticky_errno = 0; - const char * const * dirs; - for (dirs = parentPathv; *dirs; dirs++) { - const char * dir = *dirs; - int dirlen = strlen(dir); - if (filelen + dirlen + 1 >= PATH_MAX) { - errno = ENAMETOOLONG; - continue; - } - memcpy(expanded_file, dir, dirlen); - memcpy(expanded_file + dirlen, file, filelen); - expanded_file[dirlen + filelen] = '\0'; - execve_with_shell_fallback(expanded_file, argv, envp); - /* There are 3 responses to various classes of errno: - * return immediately, continue (especially for ENOENT), - * or continue with "sticky" errno. - * - * From exec(3): - * - * If permission is denied for a file (the attempted - * execve returned EACCES), these functions will continue - * searching the rest of the search path. If no other - * file is found, however, they will return with the - * global variable errno set to EACCES. - */ - switch (errno) { - case EACCES: - sticky_errno = errno; - /* FALLTHRU */ - case ENOENT: - case ENOTDIR: -#ifdef ELOOP - case ELOOP: -#endif -#ifdef ESTALE - case ESTALE: -#endif -#ifdef ENODEV - case ENODEV: -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: -#endif - break; /* Try other directories in PATH */ - default: - return; - } - } - if (sticky_errno != 0) - errno = sticky_errno; - } -} - -/* - * Reads nbyte bytes from file descriptor fd into buf, - * The read operation is retried in case of EINTR or partial reads. - * - * Returns number of bytes read (normally nbyte, but may be less in - * case of EOF). In case of read errors, returns -1 and sets errno. - */ -static ssize_t -readFully(int fd, void *buf, size_t nbyte) -{ - ssize_t remaining = nbyte; - for (;;) { - ssize_t n = read(fd, buf, remaining); - if (n == 0) { - return nbyte - remaining; - } else if (n > 0) { - remaining -= n; - if (remaining <= 0) - return nbyte; - /* We were interrupted in the middle of reading the bytes. - * Unlikely, but possible. */ - buf = (void *) (((char *)buf) + n); - } else if (errno == EINTR) { - /* Strange signals like SIGJVM1 are possible at any time. - * See http://www.dreamsongs.com/WorseIsBetter.html */ - } else { - return -1; - } - } -} - -typedef struct _ChildStuff -{ - int in[2]; - int out[2]; - int err[2]; - int fail[2]; - int fds[3]; - const char **argv; - const char **envv; - const char *pdir; - jboolean redirectErrorStream; -#if START_CHILD_USE_CLONE - void *clone_stack; -#endif -} ChildStuff; - static void copyPipe(int from[2], int to[2]) { @@ -696,97 +340,67 @@ to[1] = from[1]; } -/** - * Child process after a successful fork() or clone(). - * This function must not return, and must be prepared for either all - * of its address space to be shared with its parent, or to be a copy. - * It must not modify global variables such as "environ". +/* arg is an array of pointers to 0 terminated strings. array is terminated + * by a null element. + * + * *nelems and *nbytes receive the number of elements of array (incl 0) + * and total number of bytes (incl. 0) + * Note. An empty array will have one null element + * But if arg is null, then *nelems set to 0, and *nbytes to 0 */ -static int -childProcess(void *arg) +static void arraysize(const char * const *arg, int *nelems, int *nbytes) { - const ChildStuff* p = (const ChildStuff*) arg; - - /* Close the parent sides of the pipes. - Closing pipe fds here is redundant, since closeDescriptors() - would do it anyways, but a little paranoia is a good thing. */ - if ((closeSafely(p->in[1]) == -1) || - (closeSafely(p->out[0]) == -1) || - (closeSafely(p->err[0]) == -1) || - (closeSafely(p->fail[0]) == -1)) - goto WhyCantJohnnyExec; - - /* Give the child sides of the pipes the right fileno's. */ - /* Note: it is possible for in[0] == 0 */ - if ((moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0], - STDIN_FILENO) == -1) || - (moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], - STDOUT_FILENO) == -1)) - goto WhyCantJohnnyExec; - - if (p->redirectErrorStream) { - if ((closeSafely(p->err[1]) == -1) || - (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1)) - goto WhyCantJohnnyExec; - } else { - if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], - STDERR_FILENO) == -1) - goto WhyCantJohnnyExec; + int i, bytes, count; + const char * const *a = arg; + char *p; + int *q; + if (arg == 0) { + *nelems = 0; + *nbytes = 0; + return; } + /* count the array elements and number of bytes */ + for (count=0, bytes=0; *a != 0; count++, a++) { + bytes += strlen(*a)+1; + } + *nbytes = bytes; + *nelems = count+1; +} - if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1) - goto WhyCantJohnnyExec; - - /* close everything */ - if (closeDescriptors() == 0) { /* failed, close the old way */ - int max_fd = (int)sysconf(_SC_OPEN_MAX); - int fd; - for (fd = FAIL_FILENO + 1; fd < max_fd; fd++) - if (restartableClose(fd) == -1 && errno != EBADF) - goto WhyCantJohnnyExec; - } - - /* change to the new working directory */ - if (p->pdir != NULL && chdir(p->pdir) < 0) - goto WhyCantJohnnyExec; - - if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) - goto WhyCantJohnnyExec; +/* copy the strings from arg[] into buf, starting at given offset + * return new offset to next free byte + */ +static int copystrings(char *buf, int offset, const char * const *arg) { + char *p; + const char * const *a; + int count=0; - JDK_execvpe(p->argv[0], p->argv, p->envv); - - WhyCantJohnnyExec: - /* We used to go to an awful lot of trouble to predict whether the - * child would fail, but there is no reliable way to predict the - * success of an operation without *trying* it, and there's no way - * to try a chdir or exec in the parent. Instead, all we need is a - * way to communicate any failure back to the parent. Easy; we just - * send the errno back to the parent over a pipe in case of failure. - * The tricky thing is, how do we communicate the *success* of exec? - * We use FD_CLOEXEC together with the fact that a read() on a pipe - * yields EOF when the write ends (we have two of them!) are closed. - */ - { - int errnum = errno; - restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum)); + if (arg == 0) { + return offset; } - restartableClose(FAIL_FILENO); - _exit(-1); - return 0; /* Suppress warning "no return value from function" */ + for (p=buf+offset, a=arg; *a != 0; a++) { + int len = strlen(*a) +1; + memcpy(p, *a, len); + p += len; + count += len; + } + return offset+count; } /** - * Start a child process running function childProcess. - * This function only returns in the parent. * We are unusually paranoid; use of clone/vfork is * especially likely to tickle gcc/glibc bugs. */ #ifdef __attribute_noinline__ /* See: sys/cdefs.h */ __attribute_noinline__ #endif + +#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */ + +#ifdef START_CHILD_USE_CLONE static pid_t -startChild(ChildStuff *c) { -#if START_CHILD_USE_CLONE +cloneChild(ChildStuff *c) { +#ifdef __linux__ #define START_CHILD_CLONE_STACK_SIZE (64 * 1024) /* * See clone(2). @@ -800,33 +414,161 @@ c->clone_stack + START_CHILD_CLONE_STACK_SIZE, CLONE_VFORK | CLONE_VM | SIGCHLD, c); #else - #if START_CHILD_USE_VFORK +/* not available on Solaris / Mac */ + assert(0); + return -1; +#endif +} +#endif + +static pid_t +vforkChild(ChildStuff *c) { + volatile pid_t resultPid; + /* * We separate the call to vfork into a separate function to make * very sure to keep stack of child from corrupting stack of parent, * as suggested by the scary gcc warning: * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork' */ - volatile pid_t resultPid = vfork(); - #else + resultPid = vfork(); + + if (resultPid == 0) { + childProcess(c); + } + assert(resultPid != 0); /* childProcess never returns */ + return resultPid; +} + +static pid_t +forkChild(ChildStuff *c) { + pid_t resultPid; + /* * From Solaris fork(2): In Solaris 10, a call to fork() is * identical to a call to fork1(); only the calling thread is * replicated in the child process. This is the POSIX-specified * behavior for fork(). */ - pid_t resultPid = fork(); - #endif - if (resultPid == 0) + resultPid = fork(); + + if (resultPid == 0) { childProcess(c); + } assert(resultPid != 0); /* childProcess never returns */ return resultPid; -#endif /* ! START_CHILD_USE_CLONE */ +} + +#if defined(__solaris__) || defined(_ALLBSD_SOURCE) +static pid_t +spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { + pid_t resultPid; + jboolean isCopy; + int i, offset, rval, bufsize, magic; + char *buf, buf1[16]; + char *hlpargs[2]; + SpawnInfo sp; + + /* need to tell helper which fd is for receiving the childstuff + * and which fd to send response back on + */ + snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]); + /* put the fd string as argument to the helper cmd */ + hlpargs[0] = buf1; + hlpargs[1] = 0; + + /* Following items are sent down the pipe to the helper + * after it is spawned. + * All strings are null terminated. All arrays of strings + * have an empty string for termination. + * - the ChildStuff struct + * - the SpawnInfo struct + * - the argv strings array + * - the envv strings array + * - the home directory string + * - the parentPath string + * - the parentPathv array + */ + /* First calculate the sizes */ + arraysize(c->argv, &sp.nargv, &sp.argvBytes); + bufsize = sp.argvBytes; + arraysize(c->envv, &sp.nenvv, &sp.envvBytes); + bufsize += sp.envvBytes; + sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1; + bufsize += sp.dirlen; + arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes); + bufsize += sp.parentPathvBytes; + /* We need to clear FD_CLOEXEC if set in the fds[]. + * Files are created FD_CLOEXEC in Java. + * Otherwise, they will be closed when the target gets exec'd */ + for (i=0; i<3; i++) { + if (c->fds[i] != -1) { + int flags = fcntl(c->fds[i], F_GETFD); + if (flags & FD_CLOEXEC) { + fcntl(c->fds[i], F_SETFD, flags & (~1)); + } + } + } + + rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ); + + if (rval != 0) { + return -1; + } + + /* now the lengths are known, copy the data */ + buf = NEW(char, bufsize); + if (buf == 0) { + return -1; + } + offset = copystrings(buf, 0, &c->argv[0]); + offset = copystrings(buf, offset, &c->envv[0]); + memcpy(buf+offset, c->pdir, sp.dirlen); + offset += sp.dirlen; + offset = copystrings(buf, offset, parentPathv); + assert(offset == bufsize); + + magic = magicNumber(); + + /* write the two structs and the data buffer */ + write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first + write(c->childenv[1], (char *)c, sizeof(*c)); + write(c->childenv[1], (char *)&sp, sizeof(sp)); + write(c->childenv[1], buf, bufsize); + free(buf); + + /* In this mode an external main() in invoked which calls back into + * childProcess() in this file, rather than directly + * via the statement below */ + return resultPid; +} +#endif + +/* + * Start a child process running function childProcess. + * This function only returns in the parent. + */ +static pid_t +startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) { + switch (c->mode) { + case MODE_VFORK: + return vforkChild(c); + case MODE_FORK: + return forkChild(c); +#if defined(__solaris__) || defined(_ALLBSD_SOURCE) + case MODE_POSIX_SPAWN: + return spawnChild(env, process, c, helperpath); +#endif + default: + return -1; + } } JNIEXPORT jint JNICALL Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, jobject process, + jint mode, + jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, @@ -836,32 +578,35 @@ { int errnum; int resultPid = -1; - int in[2], out[2], err[2], fail[2]; + int in[2], out[2], err[2], fail[2], childenv[2]; jint *fds = NULL; + const char *phelperpath = NULL; const char *pprog = NULL; const char *pargBlock = NULL; const char *penvBlock = NULL; ChildStuff *c; in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1; + childenv[0] = childenv[1] = -1; if ((c = NEW(ChildStuff, 1)) == NULL) return -1; c->argv = NULL; c->envv = NULL; c->pdir = NULL; -#if START_CHILD_USE_CLONE c->clone_stack = NULL; -#endif /* Convert prog + argBlock into a char ** argv. * Add one word room for expansion of argv for use by * execve_as_traditional_shell_script. + * This word is also used when using spawn mode */ assert(prog != NULL && argBlock != NULL); + if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch; if ((pprog = getBytes(env, prog)) == NULL) goto Catch; if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; c->argv[0] = pprog; + c->argc = argc + 2; initVectorFromBlock(c->argv+1, pargBlock, argc); if (envBlock != NULL) { @@ -882,6 +627,7 @@ if ((fds[0] == -1 && pipe(in) < 0) || (fds[1] == -1 && pipe(out) < 0) || (fds[2] == -1 && pipe(err) < 0) || + (pipe(childenv) < 0) || (pipe(fail) < 0)) { throwIOException(env, errno, "Bad file descriptor"); goto Catch; @@ -894,18 +640,29 @@ copyPipe(out, c->out); copyPipe(err, c->err); copyPipe(fail, c->fail); + copyPipe(childenv, c->childenv); c->redirectErrorStream = redirectErrorStream; + c->mode = mode; - resultPid = startChild(c); + resultPid = startChild(env, process, c, phelperpath); assert(resultPid != 0); if (resultPid < 0) { - throwIOException(env, errno, START_CHILD_SYSTEM_CALL " failed"); + switch (c->mode) { + case MODE_VFORK: + throwIOException(env, errno, "vfork failed"); + break; + case MODE_FORK: + throwIOException(env, errno, "fork failed"); + break; + case MODE_POSIX_SPAWN: + throwIOException(env, errno, "spawn failed"); + break; + } goto Catch; } - - restartableClose(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ + close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */ switch (readFully(fail[0], &errnum, sizeof(errnum))) { case 0: break; /* Exec succeeded */ @@ -923,18 +680,18 @@ fds[2] = (err[0] != -1) ? err[0] : -1; Finally: -#if START_CHILD_USE_CLONE free(c->clone_stack); -#endif /* Always clean up the child's side of the pipes */ closeSafely(in [0]); closeSafely(out[1]); closeSafely(err[1]); - /* Always clean up fail descriptors */ + /* Always clean up fail and childEnv descriptors */ closeSafely(fail[0]); closeSafely(fail[1]); + closeSafely(childenv[0]); + closeSafely(childenv[1]); releaseBytes(env, prog, pprog); releaseBytes(env, argBlock, pargBlock); @@ -952,9 +709,9 @@ Catch: /* Clean up the parent's side of the pipes in case of failure only */ - closeSafely(in [1]); - closeSafely(out[0]); - closeSafely(err[0]); + closeSafely(in [1]); in[1] = -1; + closeSafely(out[0]); out[0] = -1; + closeSafely(err[0]); err[0] = -1; goto Finally; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/solaris/native/java/lang/childproc.c Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,376 @@ +/* + * 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. + */ + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +#include "childproc.h" + + +ssize_t +restartableWrite(int fd, const void *buf, size_t count) +{ + ssize_t result; + RESTARTABLE(write(fd, buf, count), result); + return result; +} + +int +restartableDup2(int fd_from, int fd_to) +{ + int err; + RESTARTABLE(dup2(fd_from, fd_to), err); + return err; +} + +int +closeSafely(int fd) +{ + return (fd == -1) ? 0 : close(fd); +} + +int +isAsciiDigit(char c) +{ + return c >= '0' && c <= '9'; +} + +#ifdef _ALLBSD_SOURCE +#define FD_DIR "/dev/fd" +#define dirent64 dirent +#define readdir64 readdir +#else +#define FD_DIR "/proc/self/fd" +#endif + +int +closeDescriptors(void) +{ + DIR *dp; + struct dirent64 *dirp; + int from_fd = FAIL_FILENO + 1; + + /* We're trying to close all file descriptors, but opendir() might + * itself be implemented using a file descriptor, and we certainly + * don't want to close that while it's in use. We assume that if + * opendir() is implemented using a file descriptor, then it uses + * the lowest numbered file descriptor, just like open(). So we + * close a couple explicitly. */ + + close(from_fd); /* for possible use by opendir() */ + close(from_fd + 1); /* another one for good luck */ + + if ((dp = opendir(FD_DIR)) == NULL) + return 0; + + /* We use readdir64 instead of readdir to work around Solaris bug + * 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9 + */ + while ((dirp = readdir64(dp)) != NULL) { + int fd; + if (isAsciiDigit(dirp->d_name[0]) && + (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) + close(fd); + } + + closedir(dp); + + return 1; +} + +int +moveDescriptor(int fd_from, int fd_to) +{ + if (fd_from != fd_to) { + if ((restartableDup2(fd_from, fd_to) == -1) || + (close(fd_from) == -1)) + return -1; + } + return 0; +} + +int +magicNumber() { + return 43110; +} + +/* + * Reads nbyte bytes from file descriptor fd into buf, + * The read operation is retried in case of EINTR or partial reads. + * + * Returns number of bytes read (normally nbyte, but may be less in + * case of EOF). In case of read errors, returns -1 and sets errno. + */ +ssize_t +readFully(int fd, void *buf, size_t nbyte) +{ + ssize_t remaining = nbyte; + for (;;) { + ssize_t n = read(fd, buf, remaining); + if (n == 0) { + return nbyte - remaining; + } else if (n > 0) { + remaining -= n; + if (remaining <= 0) + return nbyte; + /* We were interrupted in the middle of reading the bytes. + * Unlikely, but possible. */ + buf = (void *) (((char *)buf) + n); + } else if (errno == EINTR) { + /* Strange signals like SIGJVM1 are possible at any time. + * See http://www.dreamsongs.com/WorseIsBetter.html */ + } else { + return -1; + } + } +} + +void +initVectorFromBlock(const char**vector, const char* block, int count) +{ + int i; + const char *p; + for (i = 0, p = block; i < count; i++) { + /* Invariant: p always points to the start of a C string. */ + vector[i] = p; + while (*(p++)); + } + vector[count] = NULL; +} + +/** + * Exec FILE as a traditional Bourne shell script (i.e. one without #!). + * If we could do it over again, we would probably not support such an ancient + * misfeature, but compatibility wins over sanity. The original support for + * this was imported accidentally from execvp(). + */ +void +execve_as_traditional_shell_script(const char *file, + const char *argv[], + const char *const envp[]) +{ + /* Use the extra word of space provided for us in argv by caller. */ + const char *argv0 = argv[0]; + const char *const *end = argv; + while (*end != NULL) + ++end; + memmove(argv+2, argv+1, (end-argv) * sizeof(*end)); + argv[0] = "/bin/sh"; + argv[1] = file; + execve(argv[0], (char **) argv, (char **) envp); + /* Can't even exec /bin/sh? Big trouble, but let's soldier on... */ + memmove(argv+1, argv+2, (end-argv) * sizeof(*end)); + argv[0] = argv0; +} + +/** + * Like execve(2), except that in case of ENOEXEC, FILE is assumed to + * be a shell script and the system default shell is invoked to run it. + */ +void +execve_with_shell_fallback(int mode, const char *file, + const char *argv[], + const char *const envp[]) +{ + if (mode == MODE_CLONE || mode == MODE_VFORK) { + /* shared address space; be very careful. */ + execve(file, (char **) argv, (char **) envp); + if (errno == ENOEXEC) + execve_as_traditional_shell_script(file, argv, envp); + } else { + /* unshared address space; we can mutate environ. */ + environ = (char **) envp; + execvp(file, (char **) argv); + } +} + +/** + * 'execvpe' should have been included in the Unix standards, + * and is a GNU extension in glibc 2.10. + * + * JDK_execvpe is identical to execvp, except that the child environment is + * specified via the 3rd argument instead of being inherited from environ. + */ +void +JDK_execvpe(int mode, const char *file, + const char *argv[], + const char *const envp[]) +{ + if (envp == NULL || (char **) envp == environ) { + execvp(file, (char **) argv); + return; + } + + if (*file == '\0') { + errno = ENOENT; + return; + } + + if (strchr(file, '/') != NULL) { + execve_with_shell_fallback(mode, file, argv, envp); + } else { + /* We must search PATH (parent's, not child's) */ + char expanded_file[PATH_MAX]; + int filelen = strlen(file); + int sticky_errno = 0; + const char * const * dirs; + for (dirs = parentPathv; *dirs; dirs++) { + const char * dir = *dirs; + int dirlen = strlen(dir); + if (filelen + dirlen + 2 >= PATH_MAX) { + errno = ENAMETOOLONG; + continue; + } + memcpy(expanded_file, dir, dirlen); + if (expanded_file[dirlen - 1] != '/') + expanded_file[dirlen++] = '/'; + memcpy(expanded_file + dirlen, file, filelen); + expanded_file[dirlen + filelen] = '\0'; + execve_with_shell_fallback(mode, expanded_file, argv, envp); + /* There are 3 responses to various classes of errno: + * return immediately, continue (especially for ENOENT), + * or continue with "sticky" errno. + * + * From exec(3): + * + * If permission is denied for a file (the attempted + * execve returned EACCES), these functions will continue + * searching the rest of the search path. If no other + * file is found, however, they will return with the + * global variable errno set to EACCES. + */ + switch (errno) { + case EACCES: + sticky_errno = errno; + /* FALLTHRU */ + case ENOENT: + case ENOTDIR: +#ifdef ELOOP + case ELOOP: +#endif +#ifdef ESTALE + case ESTALE: +#endif +#ifdef ENODEV + case ENODEV: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif + break; /* Try other directories in PATH */ + default: + return; + } + } + if (sticky_errno != 0) + errno = sticky_errno; + } +} + +/** + * Child process after a successful fork() or clone(). + * This function must not return, and must be prepared for either all + * of its address space to be shared with its parent, or to be a copy. + * It must not modify global variables such as "environ". + */ +int +childProcess(void *arg) +{ + const ChildStuff* p = (const ChildStuff*) arg; + + /* Close the parent sides of the pipes. + Closing pipe fds here is redundant, since closeDescriptors() + would do it anyways, but a little paranoia is a good thing. */ + if ((closeSafely(p->in[1]) == -1) || + (closeSafely(p->out[0]) == -1) || + (closeSafely(p->err[0]) == -1) || + (closeSafely(p->childenv[0]) == -1) || + (closeSafely(p->childenv[1]) == -1) || + (closeSafely(p->fail[0]) == -1)) + goto WhyCantJohnnyExec; + + /* Give the child sides of the pipes the right fileno's. */ + /* Note: it is possible for in[0] == 0 */ + if ((moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0], + STDIN_FILENO) == -1) || + (moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], + STDOUT_FILENO) == -1)) + goto WhyCantJohnnyExec; + + if (p->redirectErrorStream) { + if ((closeSafely(p->err[1]) == -1) || + (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1)) + goto WhyCantJohnnyExec; + } else { + if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], + STDERR_FILENO) == -1) + goto WhyCantJohnnyExec; + } + + if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1) + goto WhyCantJohnnyExec; + + /* close everything */ + if (closeDescriptors() == 0) { /* failed, close the old way */ + int max_fd = (int)sysconf(_SC_OPEN_MAX); + int fd; + for (fd = FAIL_FILENO + 1; fd < max_fd; fd++) + if (close(fd) == -1 && errno != EBADF) + goto WhyCantJohnnyExec; + } + + /* change to the new working directory */ + if (p->pdir != NULL && chdir(p->pdir) < 0) + goto WhyCantJohnnyExec; + + if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) + goto WhyCantJohnnyExec; + + JDK_execvpe(p->mode, p->argv[0], p->argv, p->envv); + + WhyCantJohnnyExec: + /* We used to go to an awful lot of trouble to predict whether the + * child would fail, but there is no reliable way to predict the + * success of an operation without *trying* it, and there's no way + * to try a chdir or exec in the parent. Instead, all we need is a + * way to communicate any failure back to the parent. Easy; we just + * send the errno back to the parent over a pipe in case of failure. + * The tricky thing is, how do we communicate the *success* of exec? + * We use FD_CLOEXEC together with the fact that a read() on a pipe + * yields EOF when the write ends (we have two of them!) are closed. + */ + { + int errnum = errno; + restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum)); + } + close(FAIL_FILENO); + _exit(-1); + return 0; /* Suppress warning "no return value from function" */ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/solaris/native/java/lang/childproc.h Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,145 @@ +/* + * 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. + */ + +#ifndef CHILDPROC_MD_H +#define CHILDPROC_MD_H + +#include <sys/types.h> + +#ifdef __APPLE__ +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +/* This is one of the rare times it's more portable to declare an + * external symbol explicitly, rather than via a system header. + * The declaration is standardized as part of UNIX98, but there is + * no standard (not even de-facto) header file where the + * declaration is to be found. See: + * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html + * + * "All identifiers in this volume of IEEE Std 1003.1-2001, except + * environ, are defined in at least one of the headers" (!) + */ +extern char **environ; +#endif + +#ifdef __linux__ +#include <sched.h> +#endif + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + +#ifndef SA_NOCLDSTOP +#define SA_NOCLDSTOP 0 +#endif + +#ifndef SA_RESTART +#define SA_RESTART 0 +#endif + +#define FAIL_FILENO (STDERR_FILENO + 1) + +/* TODO: Refactor. */ +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + +/* These numbers must be the same as the Enum in UNIXProcess.java + * Must be a better way of doing this. + */ +#define MODE_FORK 1 +#define MODE_POSIX_SPAWN 2 +#define MODE_VFORK 3 +#define MODE_CLONE 4 + +typedef struct _ChildStuff +{ + int in[2]; + int out[2]; + int err[2]; + int fail[2]; + int childenv[2]; + int fds[3]; + int mode; + const char **argv; + int argc; + const char **envv; + const char *pdir; + int redirectErrorStream; + void *clone_stack; +} ChildStuff; + +/* following used in addition when mode is SPAWN */ +typedef struct _SpawnInfo { + int nargv; /* number of argv array elements */ + int argvBytes; /* total number of bytes in argv array */ + int nenvv; /* number of envv array elements */ + int envvBytes; /* total number of bytes in envv array */ + int dirlen; /* length of home directory string */ + int nparentPathv; /* number of elements in parentPathv array */ + int parentPathvBytes; /* total number of bytes in parentPathv array */ +} SpawnInfo; + +/** + * The cached and split version of the JDK's effective PATH. + * (We don't support putenv("PATH=...") in native code) + */ +const char * const *parentPathv; + +ssize_t restartableWrite(int fd, const void *buf, size_t count); +int restartableDup2(int fd_from, int fd_to); +int closeSafely(int fd); +int isAsciiDigit(char c); +int closeDescriptors(void); +int moveDescriptor(int fd_from, int fd_to); + +int magicNumber(); +ssize_t readFully(int fd, void *buf, size_t nbyte); +void initVectorFromBlock(const char**vector, const char* block, int count); +void execve_as_traditional_shell_script(const char *file, + const char *argv[], + const char *const envp[]); +void execve_with_shell_fallback(int mode, const char *file, + const char *argv[], + const char *const envp[]); +void JDK_execvpe(int mode, const char *file, + const char *argv[], + const char *const envp[]); +int childProcess(void *arg); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/solaris/native/java/lang/jspawnhelper.c Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,149 @@ +/* + * 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. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "childproc.h" + +extern int errno; + +#define ALLOC(X,Y) { \ + void *mptr; \ + mptr = malloc (Y); \ + if (mptr == 0) { \ + error (fdout, ERR_MALLOC); \ + } \ + X = mptr; \ +} + +#define ERR_MALLOC 1 +#define ERR_PIPE 2 +#define ERR_ARGS 3 + +void error (int fd, int err) { + write (fd, &err, sizeof(err)); + exit (1); +} + +void shutItDown() { + fprintf(stdout, "This command is not for general use and should "); + fprintf(stdout, "only be run as the result of a call to\n"); + fprintf(stdout, "ProcessBuilder.start() or Runtime.exec() in a java "); + fprintf(stdout, "application\n"); + _exit(1); +} + +/* + * read the following off the pipefd + * - the ChildStuff struct + * - the SpawnInfo struct + * - the data strings for fields in ChildStuff + */ +void initChildStuff (int fdin, int fdout, ChildStuff *c) { + int n; + int argvBytes, nargv, envvBytes, nenvv; + int dirlen; + char *buf; + SpawnInfo sp; + int bufsize, offset=0; + int magic; + int res; + + res = readFully (fdin, &magic, sizeof(magic)); + if (res != 4 || magic != magicNumber()) { + error (fdout, ERR_PIPE); + } + + if (readFully (fdin, c, sizeof(*c)) == -1) { + error (fdout, ERR_PIPE); + } + + if (readFully (fdin, &sp, sizeof(sp)) == -1) { + error (fdout, ERR_PIPE); + } + + bufsize = sp.argvBytes + sp.envvBytes + + sp.dirlen + sp.parentPathvBytes; + + ALLOC(buf, bufsize); + + if (readFully (fdin, buf, bufsize) == -1) { + error (fdout, ERR_PIPE); + } + + /* Initialize argv[] */ + ALLOC(c->argv, sizeof(char *) * sp.nargv); + initVectorFromBlock (c->argv, buf+offset, sp.nargv-1); + offset += sp.argvBytes; + + /* Initialize envv[] */ + if (sp.nenvv == 0) { + c->envv = 0; + } else { + ALLOC(c->envv, sizeof(char *) * sp.nenvv); + initVectorFromBlock (c->envv, buf+offset, sp.nenvv-1); + offset += sp.envvBytes; + } + + /* Initialize pdir */ + if (sp.dirlen == 0) { + c->pdir = 0; + } else { + c->pdir = buf+offset; + offset += sp.dirlen; + } + + /* Initialize parentPathv[] */ + ALLOC(parentPathv, sizeof (char *) * sp.nparentPathv) + initVectorFromBlock ((const char**)parentPathv, buf+offset, sp.nparentPathv-1); + offset += sp.parentPathvBytes; +} + +int main(int argc, char *argv[]) { + ChildStuff c; + int t; + struct stat buf; + /* argv[0] contains the fd number to read all the child info */ + int r, fdin, fdout; + + r = sscanf (argv[argc-1], "%d:%d", &fdin, &fdout); + if (r == 2 && fcntl(fdin, F_GETFD) != -1) { + fstat(fdin, &buf); + if (!S_ISFIFO(buf.st_mode)) + shutItDown(); + } else { + shutItDown(); + } + initChildStuff (fdin, fdout, &c); + + childProcess (&c); + return 0; /* NOT REACHED */ +}
--- a/src/solaris/native/sun/awt/awt_LoadLibrary.c Tue Apr 15 23:54:34 2014 +0100 +++ b/src/solaris/native/sun/awt/awt_LoadLibrary.c Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ jvm = vm; /* Get address of this library and the directory containing it. */ - dladdr((void *)JNI_OnLoad, &dlinfo); + dladdr((void *)AWT_OnLoad, &dlinfo); realpath((char *)dlinfo.dli_fname, buf); len = strlen(buf); p = strrchr(buf, '/');
--- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Apr 16 19:41:14 2014 +0100 @@ -506,20 +506,19 @@ } } }; - comThread = - AccessController.doPrivileged( - new PrivilegedAction<Thread>() { - public Thread run() { + comThread = AccessController.doPrivileged(new PrivilegedAction<Thread>() { + @Override + public Thread run() { /* The thread must be a member of a thread group * which will not get GCed before VM exit. * Make its parent the top-level thread group. */ - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread thread = new Thread(rootTG, comRun, "Swing-Shell"); - thread.setDaemon(true); - return thread; - } - } + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread thread = new Thread(rootTG, comRun, "Swing-Shell"); + thread.setDaemon(true); + return thread; + } + } ); return comThread; }
--- a/src/windows/classes/sun/awt/windows/WToolkit.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/classes/sun/awt/windows/WToolkit.java Wed Apr 16 19:41:14 2014 +0100 @@ -235,10 +235,11 @@ // Find a root TG and attach Appkit thread to it ThreadGroup rootTG = AccessController.doPrivileged(new PrivilegedAction<ThreadGroup>() { - public ThreadGroup run() { - return ThreadGroupUtils.getRootThreadGroup(); - } - }); + @Override + public ThreadGroup run() { + return ThreadGroupUtils.getRootThreadGroup(); + } + }); if (!startToolkitThread(this, rootTG)) { Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows"); toolkitThread.setDaemon(true);
--- a/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Wed Apr 16 19:41:14 2014 +0100 @@ -92,25 +92,27 @@ public D3DScreenUpdateManager() { done = false; - AccessController.doPrivileged( - new PrivilegedAction<Void>() { - public Void run() { - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread shutdown = new Thread(rootTG, new Runnable() { + AccessController.doPrivileged( + new PrivilegedAction<Void>() { + @Override + public Void run() { + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread shutdown = new Thread(rootTG, new Runnable() { + @Override public void run() { done = true; wakeUpUpdateThread(); } }); - shutdown.setContextClassLoader(null); - try { - Runtime.getRuntime().addShutdownHook(shutdown); - } catch (Exception e) { - done = true; + shutdown.setContextClassLoader(null); + try { + Runtime.getRuntime().addShutdownHook(shutdown); + } catch (Exception e) { + done = true; + } + return null; } - return null; } - } ); } @@ -350,18 +352,19 @@ private synchronized void startUpdateThread() { if (screenUpdater == null) { screenUpdater = AccessController.doPrivileged( - new PrivilegedAction<Thread>() { - public Thread run() { - ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); - Thread t = new Thread(rootTG, - D3DScreenUpdateManager.this, - "D3D Screen Updater"); - // REMIND: should it be higher? - t.setPriority(Thread.NORM_PRIORITY + 2); - t.setDaemon(true); - return t; - } - }); + new PrivilegedAction<Thread>() { + @Override + public Thread run() { + ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup(); + Thread t = new Thread(rootTG, + D3DScreenUpdateManager.this, + "D3D Screen Updater"); + // REMIND: should it be higher? + t.setPriority(Thread.NORM_PRIORITY + 2); + t.setDaemon(true); + return t; + } + }); screenUpdater.start(); } else { wakeUpUpdateThread();
--- a/src/windows/native/java/lang/java_props_md.c Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/native/java/lang/java_props_md.c Wed Apr 16 19:41:14 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -448,6 +448,7 @@ case 0: sprops.os_name = "Windows Vista"; break; case 1: sprops.os_name = "Windows 7"; break; case 2: sprops.os_name = "Windows 8"; break; + case 3: sprops.os_name = "Windows 8.1"; break; default: sprops.os_name = "Windows NT (unknown)"; } } else { @@ -455,6 +456,7 @@ case 0: sprops.os_name = "Windows Server 2008"; break; case 1: sprops.os_name = "Windows Server 2008 R2"; break; case 2: sprops.os_name = "Windows Server 2012"; break; + case 3: sprops.os_name = "Windows Server 2012 R2"; break; default: sprops.os_name = "Windows NT (unknown)"; } }
--- a/src/windows/native/sun/font/fontpath.c Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/native/sun/font/fontpath.c Wed Apr 16 19:41:14 2014 +0100 @@ -185,6 +185,12 @@ return 0; } +/* This HDC is initialised and released in the populate family map + * JNI entry point, and used within the call which would otherwise + * create many DCs. + */ +static HDC screenDC = NULL; + static int DifferentFamily(wchar_t *family, wchar_t* fullName) { LOGFONTW lfw; CheckFamilyInfo info; @@ -202,7 +208,7 @@ memset(&lfw, 0, sizeof(lfw)); wcscpy(lfw.lfFaceName, fullName); lfw.lfCharSet = DEFAULT_CHARSET; - EnumFontFamiliesExW(GetDC(NULL), &lfw, + EnumFontFamiliesExW(screenDC, &lfw, (FONTENUMPROCW)CheckFontFamilyProcW, (LPARAM)(&info), 0L); @@ -299,7 +305,7 @@ memset(&lfa, 0, sizeof(lfa)); strcpy(lfa.lfFaceName, lpelfe->elfLogFont.lfFaceName); lfa.lfCharSet = lpelfe->elfLogFont.lfCharSet; - EnumFontFamiliesExA(GetDC(NULL), &lfa, + EnumFontFamiliesExA(screenDC, &lfa, (FONTENUMPROCA)EnumFontFacesInFamilyProcA, lParam, 0L); return 1; @@ -353,7 +359,7 @@ memset(&lfw, 0, sizeof(lfw)); wcscpy(lfw.lfFaceName, lpelfe->elfLogFont.lfFaceName); lfw.lfCharSet = lpelfe->elfLogFont.lfCharSet; - EnumFontFamiliesExW(GetDC(NULL), &lfw, + EnumFontFamiliesExW(screenDC, &lfw, (FONTENUMPROCW)EnumFontFacesInFamilyProcW, lParam, 0L); return 1; @@ -613,13 +619,17 @@ return; } + screenDC = GetDC(NULL); + if (screenDC == NULL) { + return; + } /* Enumerate fonts via GDI to build maps of fonts and families */ if (IS_NT) { LOGFONTW lfw; memset(&lfw, 0, sizeof(lfw)); lfw.lfCharSet = DEFAULT_CHARSET; /* all charsets */ wcscpy(lfw.lfFaceName, L""); /* one face per family (CHECK) */ - EnumFontFamiliesExW(GetDC(NULL), &lfw, + EnumFontFamiliesExW(screenDC, &lfw, (FONTENUMPROCW)EnumFamilyNamesW, (LPARAM)(&fmi), 0L); } else { @@ -627,7 +637,7 @@ memset(&lfa, 0, sizeof(lfa)); lfa.lfCharSet = DEFAULT_CHARSET; /* all charsets */ strcpy(lfa.lfFaceName, ""); /* one face per family */ - ret = EnumFontFamiliesExA(GetDC(NULL), &lfa, + ret = EnumFontFamiliesExA(screenDC, &lfa, (FONTENUMPROCA)EnumFamilyNamesA, (LPARAM)(&fmi), 0L); } @@ -637,6 +647,8 @@ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, fontKeyName, 0L, KEY_READ, &hkeyFonts); if (ret != ERROR_SUCCESS) { + ReleaseDC(NULL, screenDC); + screenDC = NULL; return; } @@ -653,6 +665,8 @@ dwMaxValueNameLen >= MAX_BUFFER || dwMaxValueDataLen >= MAX_BUFFER) { RegCloseKey(hkeyFonts); + ReleaseDC(NULL, screenDC); + screenDC = NULL; return; } for (nval = 0; nval < dwNumValues; nval++ ) { @@ -692,4 +706,6 @@ } } RegCloseKey(hkeyFonts); + ReleaseDC(NULL, screenDC); + screenDC = NULL; }
--- a/src/windows/resource/java.manifest Tue Apr 15 23:54:34 2014 +0100 +++ b/src/windows/resource/java.manifest Wed Apr 16 19:41:14 2014 +0100 @@ -44,9 +44,15 @@ <!-- Indicate this JDK version is Windows 7 compatible --> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> - <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows Vista --> <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> </application> - </compatibility> + </compatibility> </assembly>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Graphics2D/DrawString/DrawRotatedString.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,81 @@ +/* + * 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. + * + * 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. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +/** + * @test + * @bug 7190349 + * @summary Verifies that we get correct direction, when draw rotated string. + * @author Sergey Bylokhov + * @run main/othervm DrawRotatedString + */ +public final class DrawRotatedString { + + private static final int SIZE = 500; + + public static void main(final String[] args) throws IOException { + BufferedImage bi = createBufferedImage(true); + verify(bi); + bi = createBufferedImage(false); + verify(bi); + System.out.println("Passed"); + } + + private static void verify(BufferedImage bi) throws IOException { + for (int i = 0; i < SIZE; ++i) { + for (int j = 0; j < 99; ++j) { + //Text should not appear before 100 + if (bi.getRGB(i, j) != Color.RED.getRGB()) { + ImageIO.write(bi, "png", new File("image.png")); + throw new RuntimeException("Failed: wrong text location"); + } + } + } + } + + private static BufferedImage createBufferedImage(final boolean aa) { + final BufferedImage bi = new BufferedImage(SIZE, SIZE, + BufferedImage.TYPE_INT_RGB); + final Graphics2D bg = bi.createGraphics(); + bg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + aa ? RenderingHints.VALUE_ANTIALIAS_ON + : RenderingHints.VALUE_ANTIALIAS_OFF); + bg.setColor(Color.RED); + bg.fillRect(0, 0, SIZE, SIZE); + bg.translate(100, 100); + bg.rotate(Math.toRadians(90)); + bg.setColor(Color.BLACK); + bg.setFont(bg.getFont().deriveFont(20.0f)); + bg.drawString("MMMMMMMMMMMMMMMM", 0, 0); + bg.dispose(); + return bi; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Graphics2D/IncorrectTextSize/IncorrectTextSize.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,77 @@ +/* + * 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. + * + * 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. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8013569 + * @author Sergey Bylokhov + */ +public final class IncorrectTextSize { + + static final int scale = 2; + static final int width = 1200; + static final int height = 100; + static BufferedImage bi = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + static final String TEXT = "The quick brown fox jumps over the lazy dog" + + "The quick brown fox jumps over the lazy dog"; + + public static void main(final String[] args) throws IOException { + for (int point = 5; point < 11; ++point) { + Graphics2D g2d = bi.createGraphics(); + g2d.setFont(new Font(Font.DIALOG, Font.PLAIN, point)); + g2d.scale(scale, scale); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, width, height); + g2d.setColor(Color.green); + g2d.drawString(TEXT, 0, 20); + int length = g2d.getFontMetrics().stringWidth(TEXT); + if (length < 0) { + throw new RuntimeException("Negative length"); + } + for (int i = (length + 1) * scale; i < width; ++i) { + for (int j = 0; j < height; ++j) { + if (bi.getRGB(i, j) != Color.white.getRGB()) { + g2d.drawLine(length, 0, length, height); + ImageIO.write(bi, "png", new File("image.png")); + System.out.println("length = " + length); + System.err.println("Wrong color at x=" + i + ",y=" + j); + System.err.println("Color is:" + new Color(bi.getRGB(i, + j))); + throw new RuntimeException("Test failed."); + } + } + } + g2d.dispose(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/LoadAWTCrashTest/LoadAWTCrashTest.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8031477 + @summary Crash while awt starting + @author Petr Pchelko + @run main/othervm LoadAWTCrashTest +*/ + +public class LoadAWTCrashTest { + public static void main(String[] args) { + System.loadLibrary("awt"); + // If the bug is present JVM would crash or deadlock + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/font/TextLayout/TestAATMorxFont.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* @test + * @summary verify rendering of MORX fonts on OS X. + * @bug 8031462 + */ + +import javax.swing.*; +import javax.swing.border.LineBorder; +import java.awt.*; +import java.awt.event.ActionEvent; + +public class TestAATMorxFont extends JComponent { + public static void main(String[] args) { + String osName = System.getProperty("os.name"); + System.out.println("OS is " + osName); + osName = osName.toLowerCase(); + if (!osName.startsWith("mac")) { + return; + } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JFrame frame = new JFrame("Test Morx"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + TestAATMorxFont panel = new TestAATMorxFont(); + frame.add(panel); + frame.pack(); + frame.setVisible(true); + } + }); + } + + public Dimension getPreferredSize() { + return new Dimension(1200, 400); + } + + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + int y = 50; + g.setFont(new Font("Gujarati MT", Font.PLAIN, 40)); + System.out.println(g.getFont()); + g.drawString("\u0A95\u0ACD \u0A95\u0A95\u0A95 \u0A95\u0ACD\u0A95\u0ACD\u0A95", 20, y); + y += 50; + g.setFont(new Font("Tamil Sangam MN", Font.PLAIN, 40)); + System.out.println(g.getFont()); + g.drawString("\u0b95\u0bCD \u0b95\u0b95\u0b95 \u0b95\u0bCD\u0b95\u0bCD\u0b95", 20, y); + y += 50; + g.setFont(new Font("Telugu Sangam MN", Font.PLAIN, 40)); + System.out.println(g.getFont()); + g.drawString("\u0c15\u0c4D \u0c15\u0c15\u0c15 \u0c15\u0c4D\u0c15\u0c4D\u0c15", 20, y); + y += 50; + g.setFont(new Font("Devanagari Sangam MN", Font.PLAIN, 40)); + System.out.println(g.getFont()); + g.drawString("\u0915\u0940 \u0915\u0947 \u0915\u0942", 20, y); + y += 50; + g.drawString("\u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y); + y += 50; + g.drawString("\u0930\u093F\u0935\u094D\u092F\u0942 \u0915\u0947 \u092C\u093E\u0926 \u0935\u093F\u0915\u093E\u0938 \u0913\u0932\u0902\u092A\u093F\u0915 \u0938\u0947 \u092C\u093E\u0939\u0930 (\u0926\u0947\u0935\u0928\u093E\u0917\u0930\u0940) (\u0939\u093F\u0928\u094D\u0926\u0940) \u0907\u0930\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915\u094D\u0915", 20, y); + + } +} +
--- a/test/java/beans/Introspector/TestTypeResolver.java Tue Apr 15 23:54:34 2014 +0100 +++ b/test/java/beans/Introspector/TestTypeResolver.java Wed Apr 16 19:41:14 2014 +0100 @@ -113,6 +113,8 @@ // by private implementations of the various Type interfaces if (expect.equals(t) && t.equals(expect)) System.out.println(", as expected"); + else if ((expect.equals(t) || t.equals(expect)) && expect.toString().equals(t.toString())) + System.out.println(", as workaround of the 8023301 bug"); else { System.out.println(" BUT SHOULD BE " + expect); failedCases.add(c);
--- a/test/java/lang/ProcessBuilder/Basic.java Tue Apr 15 23:54:34 2014 +0100 +++ b/test/java/lang/ProcessBuilder/Basic.java Wed Apr 16 19:41:14 2014 +0100 @@ -29,6 +29,7 @@ * 4947220 7018606 7034570 * @summary Basic tests for Process and Environment Variable code * @run main/othervm/timeout=300 Basic + * @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic * @author Martin Buchholz */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/ProcessBuilder/BasicLauncher.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,99 @@ +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 5049299 + * @summary (process) Use posix_spawn, not fork, on S10 to avoid swap exhaustion + * @compile BasicLauncher.java Basic.java + * @run main BasicLauncher + */ + +import java.io.*; +import java.nio.file.*; + +public class BasicLauncher { + + private static boolean passed = false; + + public static void main(String args[]) throws Exception { + String osName = System.getProperty("os.name"); + if (osName.startsWith("SunOS")) { + BasicLauncher l = new BasicLauncher(); + l.start(); + } + } + + private void start() throws Exception { + String separator = System.getProperty("file.separator"); + String jdkpath = System.getProperty("test.jdk") + separator + "bin" + separator; + String srcpath = System.getProperty("test.src", ".") + separator; + String testClasses = System.getProperty("test.classes", "."); + + ProcessBuilder builder = new ProcessBuilder( + jdkpath + "java", + "-cp", + testClasses, + "-Djdk.lang.Process.launchMechanism=posix_spawn", + "Basic"); + builder.redirectErrorStream(true); + Process testProc = builder.start(); + printProcessThread ppt = + new printProcessThread(testProc, "testproc"); + ppt.start(); + testProc.waitFor(); + System.out.println("testproc done"); + + if (!passed) + throw new RuntimeException("Test Failed: "); + } + + + class printProcessThread extends Thread { + Process p; + String pName; + + public printProcessThread(Process p, String pName) { + this.p = p; + this.pName = pName; + } + + @Override + public void run() { + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(p.getInputStream()))) { + String line; + while ((line = reader.readLine()) != null) { + System.out.println("[Output: " + pName + "]" + line); + if (line.contains("failed = 0")) { + passed = true; + } + } + + } catch (Exception e) { + System.out.println("Exception encountered in " + pName + + " thread\n" + e); + } + } + } +}
--- a/test/java/util/logging/TestAppletLoggerContext.java Tue Apr 15 23:54:34 2014 +0100 +++ b/test/java/util/logging/TestAppletLoggerContext.java Wed Apr 16 19:41:14 2014 +0100 @@ -110,28 +110,19 @@ } TestExc exc; - TestExc global = new TestExc(); @Override - public Object getContext() { return active ? global : null; } - @Override - public Object getExecutionContext() { return active ? exc : null; } + public Object getAppletContext() { return active ? exc : null; } @Override - public Object get(Object o, Object o1) { return TestExc.exc(o).get(o1); } - @Override - public void put(Object o, Object o1, Object o2) { TestExc.exc(o).put(o1, o2); } + public Object get(Object o) { return exc.get(o); } @Override - public void remove(Object o, Object o1) { TestExc.exc(o).remove(o1); } - @Override - public Object get(Object o) { return global.get(o); } + public void put(Object o, Object o1) { exc.put(o, o1); } @Override - public void put(Object o, Object o1) { global.put(o, o1); } - @Override - public void remove(Object o) { global.remove(o); } + public void remove(Object o) { exc.remove(o); } @Override public boolean isDisposed() { return false; } @Override - public boolean isMainAppContext() { return exc == null; } + public boolean isMainAppContext() { return !active || exc == null; } } final static JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/TestLoggingWithMainAppContext.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,75 @@ +/* + * 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. + * + * 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. + */ +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8019853 8023258 + * @summary Test that the default user context is used when in the main + * application context. This test must not be run in same VM or agent + * VM mode: it would not test the intended behavior. + * @run main/othervm TestLoggingWithMainAppContext + */ +public class TestLoggingWithMainAppContext { + + public static void main(String[] args) throws IOException { + System.out.println("Creating loggers."); + + // These loggers will be created in the default user context. + final Logger foo1 = Logger.getLogger( "foo" ); + final Logger bar1 = Logger.getLogger( "foo.bar" ); + if (bar1.getParent() != foo1) { + throw new RuntimeException("Parent logger of bar1 "+bar1+" is not "+foo1); + } + System.out.println("bar1.getParent() is the same as foo1"); + + // Set a security manager + System.setSecurityManager(new SecurityManager()); + System.out.println("Now running with security manager"); + + // Triggers the creation of the main AppContext + ByteArrayInputStream is = new ByteArrayInputStream(new byte[] { 0, 1 }); + ImageIO.read(is); // triggers calls to system loggers & creation of main AppContext + + // verify that we're still using the default user context + final Logger bar2 = Logger.getLogger( "foo.bar" ); + if (bar1 != bar2) { + throw new RuntimeException("bar2 "+bar2+" is not the same as bar1 "+bar1); + } + System.out.println("bar2 is the same as bar1"); + if (bar2.getParent() != foo1) { + throw new RuntimeException("Parent logger of bar2 "+bar2+" is not foo1 "+foo1); + } + System.out.println("bar2.getParent() is the same as foo1"); + final Logger foo2 = Logger.getLogger("foo"); + if (foo1 != foo2) { + throw new RuntimeException("foo2 "+foo2+" is not the same as foo1 "+foo1); + } + System.out.println("foo2 is the same as foo1"); + + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/TestMainAppContext.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,85 @@ +/* + * 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. + * + * 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. + */ +import java.util.logging.Logger; +import sun.awt.AppContext; +import sun.awt.SunToolkit; + + +/** + * @test + * @bug 8026404 + * @summary checks that calling getLogger() from a Thread whose ThreadGroup is + * a child of the main root group doesn't throw an exception. + * @build TestMainAppContext + * @run main/othervm TestMainAppContext + * @author danielfuchs + */ +public class TestMainAppContext { + + static volatile Throwable thrown = null; + + public static void main(String... args) throws Exception { + ThreadGroup rootTG = Thread.currentThread().getThreadGroup(); + while (rootTG.getParent() != null) { + rootTG = rootTG.getParent(); + } + + ThreadGroup tg = new ThreadGroup(rootTG, "FakeApplet"); + final Thread t1 = new Thread(tg, "createNewAppContext") { + @Override + public void run() { + try { + AppContext context = SunToolkit.createNewAppContext(); + } catch(Throwable t) { + thrown = t; + } + } + }; + t1.start(); + t1.join(); + if (thrown != null) { + throw new RuntimeException("Unexpected exception: " + thrown, thrown); + } + Thread t2 = new Thread(tg, "BugDetector") { + + @Override + public void run() { + try { + Logger.getLogger("foo").info("Done"); + } catch (Throwable x) { + thrown = x; + } + } + + }; + + System.setSecurityManager(new SecurityManager()); + t2.start(); + t2.join(); + if (thrown != null) { + throw new RuntimeException("Test failed: " + thrown, thrown); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/imageio/plugins/jpeg/TruncatedImageWarningTest.java Wed Apr 16 19:41:14 2014 +0100 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.event.IIOReadWarningListener; +import javax.imageio.stream.ImageInputStream; + +public class TruncatedImageWarningTest implements IIOReadWarningListener { + + private static String fileName = "truncated.jpg"; + boolean receivedWarning = false; + + public static void main(String[] args) throws IOException { + + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String filePath = dir+sep+fileName; + System.out.println("Test file: " + filePath); + File f = new File(filePath); + ImageInputStream in = ImageIO.createImageInputStream(f); + ImageReader reader = ImageIO.getImageReaders(in).next(); + TruncatedImageWarningTest twt = new TruncatedImageWarningTest(); + reader.addIIOReadWarningListener(twt); + reader.setInput(in); + reader.read(0); + if (!twt.receivedWarning) { + throw new RuntimeException("No expected warning"); + } + } + + public void warningOccurred(ImageReader source, String warning) { + System.out.println("Expected warning: " + warning); + receivedWarning = true; + } +}